Gamified Ukrainian NMT/ZNO prep: real tests, live XP, streaks, badges, quests, and leaderboards.
NMT Arena is a monorepo for a two-part product:
- A Next.js website for profiles, leaderboards, groups, daily challenges, quests, badges, and share cards.
- A Chrome Manifest V3 extension that runs on
zno.osvita.ua, detects finished test results, shows a live HUD, and submits validated sessions to the website.
The goal is simple: students keep practicing on real NMT/ZNO tests, while NMT Arena turns progress into visible momentum.
- Install the Chrome extension.
- Log in with Google or Discord through the website.
- Take real tests on
zno.osvita.ua. - The extension detects the result, calculates a secure session hash, and submits the score.
- The platform awards XP, updates streaks, grants badges, advances quests, and refreshes leaderboards.
| Layer | Tech |
|---|---|
| Monorepo | pnpm workspaces + Turborepo |
| Website | Next.js 14 App Router + React + TypeScript |
| Styling | Tailwind CSS, Material You inspired green theme |
| Auth + DB | Supabase Auth, Postgres, RLS, Realtime-ready tables |
| Extension | Chrome MV3 + Vite + React popup |
| Validation | Zod schemas in packages/shared |
| OG Images | @vercel/og |
nmt-arena/
├─ apps/
│ ├─ web/ # Next.js website
│ └─ extension/ # Chrome MV3 extension
├─ packages/
│ ├─ shared/ # constants, schemas, XP, anti-cheat helpers
│ └─ supabase/ # typed Supabase clients + DB types
├─ supabase/
│ ├─ migrations/ # SQL schema, RLS, views, functions
│ └─ seed.sql # subjects, badges, quests, daily challenge seed
├─ package.json
├─ pnpm-workspace.yaml
├─ turbo.json
└─ .env.example- Ukrainian landing page with product loop, rank ladder, badges, and daily challenge teaser.
- Auth pages for Supabase OAuth.
- Global and subject leaderboard routes.
- Public profile pages with XP, ranks, badges, recent sessions, and subject breakdown sections.
- Personal profile route.
- Challenges and quests page.
- Groups pages.
- Session ingestion API for extension submissions.
- Leaderboard API with filter support.
- Dynamic OG images for profiles and score sharing.
- Dark mode, responsive Tailwind design, accessible buttons and focus states.
- Manifest V3 extension shell.
- React popup with connected/disconnected states.
- Background auth bridge for website login.
- Content script for
zno.osvita.ua. - Shadow DOM HUD with timer, XP, messages, and draggable panel.
- Result detector with Ukrainian text parsing.
- Fingerprint tracker for timing, interactions, viewport, and visibility changes.
- Secure session hash generation before API submission.
- Tables for profiles, subjects, test sessions, XP events, badges, daily challenges, quests, friends, groups, and group members.
- Row Level Security policies.
- Global and subject leaderboard views.
award_xpRPC with daily XP cap.update_streakRPC.- Seed data for NMT subjects, 15 badge definitions, quest templates, and a daily challenge.
pnpm install
pnpm devCopy the environment template before running authenticated flows:
cp .env.example .env.localOn Windows PowerShell:
Copy-Item .env.example .env.local# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
# Extension connects to this
NEXT_PUBLIC_API_URL=https://nmt-arena.fun
# Optional transactional email
RESEND_API_KEY=
# Extension build
VITE_API_URL=https://nmt-arena.fun
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=pnpm dev # run all dev servers through Turbo
pnpm build # build all apps/packages
pnpm build:web # build only the website
pnpm build:extension # build only the Chrome extension
pnpm lint # run lint/type-style checks
pnpm typecheck # TypeScript checks
pnpm test # unit tests
pnpm db:migrate # push Supabase migrations
pnpm db:seed # seed Supabase data- Create a Supabase project.
- Enable Google and Discord auth providers.
- Fill
.env.localwith Supabase URL, anon key, and service role key. - Apply migrations:
pnpm db:migrate- Seed base data:
pnpm db:seedThe schema is in supabase/migrations/202605290001_initial_schema.sql.
Build the extension:
pnpm build:extensionThen load it in Chrome:
- Open
chrome://extensions. - Enable Developer Mode.
- Click Load unpacked.
- Select
apps/extension/dist. - Open the extension popup and connect your NMT Arena account.
XP calculation lives in packages/shared/src/xp.ts and is shared by the web app and extension-facing API.
- Base XP:
correct answers * 10 - Speed bonus:
+5 XP per correct answerwhen average time is under 30 seconds per question - Streak multiplier:
1.5xat 5+ streak,2xat 10+ streak - Per-session cap before award:
800 XP - Daily test XP cap in the database RPC:
2000 XP
| XP | Rank |
|---|---|
| 0 | 🎒 Школяр |
| 500 | 📖 Абітурієнт |
| 2,000 | ☕ Зубрила |
| 6,000 | 🧠 НМТшник |
| 15,000 | 🔥 Топ Предмет |
| 30,000 | 👑 200 з Усього |
- This repo is an early full-stack scaffold, not a deployed production instance yet.
- The extension detector is intentionally resilient, but
zno.osvita.uamarkup can change; add fixtures as the detector matures. - Local dependency installation previously hit a pnpm + Windows + Node 24 rename issue. Node 20 LTS is recommended for the next validation pass.
git diff --checkand static manifest parsing passed during scaffold creation.
- Add real fixture coverage for multiple
zno.osvita.uaresult page variants. - Finish end-to-end Supabase integration tests.
- Add CI for typecheck, tests, web build, and extension build.
- Add generated extension icons and Chrome Web Store packaging.
- Add richer profile editing, group creation, friend flows, and quest completion UI.
MIT. See LICENSE.