Base Version: v1.0.0 (tagged
v1.0.0-basein git) This is the complete, production-ready base/legacy version. All future development builds on top of this.
Goal-anchored exam prep: schedule, journal, test, revise — all attached to one central object: your exam.
ExamOps is a full-stack, multi-exam study tracker built around the exam-day deadline. It combines priority-weighted study planning, SM-2 spaced repetition, gamified XP/streaks, an admin-curated question catalog, and a futuristic admin CMS — all running on a single-page Next.js shell.
New here? Start with docs/HANDOVER.md.
The app is published at: https://hgtwbefvf.space-z.ai/
- Demo student:
demo@examops.local/demo123 - Demo admin:
admin@examops.local/admin123
⚠️ This URL is for TESTING ONLY — it runs on a sandbox cluster and is reset periodically. Do not store real data and do not modify the deployment directly. For real production deployment, followdocs/SETUP.md(Deployment section).
For Students
- 🗓️ Multi-exam tracking — prepare for several exams simultaneously, each with its own date, hour budget, and topic selections.
- 🧠 Auto-generated study plans — priority-weighted daily allocations from today through the day before your exam.
- 🔁 Spaced repetition (SM-2) — saved questions reschedule themselves based on a 0–5 quality grade.
- 📚 Question repository — admin-curated PYQs + your own saved questions with smart answer matching (case/punctuation/number/keyword/Levenshtein aware).
- 🎮 Gamification — XP per study hour, per topic done, per test logged, per journal entry; streaks, 19 achievement badges, quadratic level curve.
- 📊 Analytics — readiness %, pace projection, subject-progress rings, score trends, study heatmap.
- 🗒️ Markdown journal with mood tracking + tags.
- ⏱️ Pomodoro widget, command palette, quick-add FAB, notification bell.
- 🚨 Exam-day mode — stripped-down revision view for the final 7 days, with logistics checklist.
For Admins
- 🧙 5-step Exam Creation Wizard — weightage ring, duplicate detection, structure tree, marking scheme, cutoffs, version snapshot.
- 📥 JSON import/export for exams, subjects, topics, PYQs — with DRY_RUN validation.
- 🗂️ Entity library — master tree with merge tool (promote PRIVATE → GLOBAL).
- 🗑️ Universal trash — soft-delete with 30-day grace + auto-purge sweep.
- 🧑🎓 Student analytics — per-student dashboards with weak-area detection.
- 🔔 Approvals + broadcasts — catalog request workflow + role-targeted notifications.
- 📈 Admin overview dashboard — platform-wide KPIs, consistency metrics, activity export.
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack, standalone output) |
| Language | TypeScript 5 (strict) |
| ORM | Prisma 6 |
| Database | SQLite (dev) / PostgreSQL (prod, swap provider) |
| Styling | Tailwind CSS 4 + shadcn/ui (New York) |
| Auth | bcryptjs + JWT in httpOnly cookies (custom, not NextAuth) |
| Server state | TanStack Query 5 |
| UI state | Zustand 5 (persisted) |
| Animation | Framer Motion 12 |
| Charts | Recharts 2 |
| Markdown | @mdxeditor/editor + react-markdown |
| Icons | lucide-react |
| Runtime | Bun (dev) / Node 18+ (prod) |
next-authis installed as a dependency but is not wired up — custom JWT auth is used instead (seesrc/lib/auth.ts).
# 1. Clone & install
git clone <repo-url> examops
cd examops
bun install
# 2. Configure env
cp .env.example .env
# Edit .env: set JWT_SECRET to a 32+ char random string
# openssl rand -base64 32
# 3. Push schema to SQLite + generate Prisma client
bun run db:push
# 4. Seed demo data (idempotent)
bun run db:seed
# 5. Start dev server
bun run devVisit http://localhost:3000.
⚠️ DEMO ONLY — these accounts ship inprisma/seed.tsand have weak passwords. Change or delete them before any real deployment.
| Role | Password | |
|---|---|---|
| Admin | admin@examops.local |
admin123 |
| Student | demo@examops.local |
demo123 |
First-user-auto-admin: the very first user to register via
POST /api/auth/registerbecomesADMINautomatically (seesrc/app/api/auth/register/route.ts). All subsequent registrations areSTUDENT.
examops/
├── prisma/
│ ├── schema.prisma # 31 models, SQLite provider
│ └── seed.ts # idempotent demo data
├── src/
│ ├── app/
│ │ ├── page.tsx # SPA entry — mounts <ExamOpsApp/>
│ │ ├── layout.tsx # root layout (ThemeProvider, Sonner toaster)
│ │ ├── globals.css # Tailwind 4 + design tokens
│ │ └── api/ # 124 route.ts files across /api/**
│ ├── components/
│ │ ├── examops/ # app shell + section views + wizard + widgets
│ │ │ └── sections/ # 10 top-level view components
│ │ └── ui/ # shadcn/ui primitives (50+ components)
│ ├── lib/
│ │ ├── auth.ts # bcrypt + JWT + cookie + rate limiter
│ │ ├── db.ts # Prisma singleton (hot-reload safe)
│ │ ├── constants.ts # type-safe enums + XP/SRS rules
│ │ ├── examops-utils.ts # SM-2, XP math, readiness, date helpers
│ │ ├── api-client.ts # typed fetch wrapper (client side)
│ │ ├── store.ts # Zustand store (UI/nav state)
│ │ ├── daily-entry.ts # daily study log reconstruction helpers
│ │ ├── notifications.ts # broadcast merge + auto-archive
│ │ ├── trash.ts # universal trash sweep + soft-delete helpers
│ │ └── answer-matcher.ts # 6-strategy smart answer grader
│ └── hooks/ # use-toast, use-mobile
├── fixtures/ # 9 example JSON payloads + README
├── tests/ # e2e.ts, e2e-full.ts, smoke.ts, test-import-export.ts
├── docs/ # ← this documentation set
├── agent-ctx/ # 23 historical handover notes (Phase 4 work)
└── package.json
For the full annotated tree, see docs/ARCHITECTURE.md (Directory Structure section).
| Command | Description |
|---|---|
bun run lint |
ESLint (Next.js core-web-vitals + TypeScript rules) → must exit 0 |
bunx tsc --noEmit |
TypeScript type-check (no build artifacts) → must pass |
bun run test:unit / bun test tests/unit/ |
Unit tests (SRS, XP, answer-matcher, conflict-resolution) |
bun run tests/e2e.ts |
End-to-end API suite (GET-heavy, ~100 assertions) |
bun run tests/e2e-full.ts |
Comprehensive E2E (CRUD + security + import/export, ~300 assertions) |
bun run tests/smoke.ts |
Quick smoke test of key endpoints |
bun run tests/test-import-export.ts |
Import/export flow tests with dummy fixtures |
E2E tests require a running dev server (bun run dev in another terminal). The tests/e2e-full.ts suite honors the E2E_BASE env var (defaults to http://localhost:3000).
See docs/CONVENTIONS.md (Testing section) for what "done" means.
GitHub Actions workflows are in .github/workflows/:
ci.yml— runs lint, typecheck, unit tests, and smoke tests on every push/PR tomain. Uploadsdev.logas an artifact on failure for debugging.deploy.yml— Vercel production deployment workflow. Disabled by default (if: ${{ false }}) — flip the guard toif: github.event_name == 'push'and configureVERCEL_TOKEN,VERCEL_ORG_ID,VERCEL_PROJECT_IDsecrets to enable auto-deploy.
The CI pipeline uses bun install --frozen-lockfile for reproducible builds, starts the dev server in the background with a 60s curl-based health check, and runs the smoke suite against it.
Before starting any work on this project:
- Read
docs/HANDOVER.md— the single entry point for project knowledge - Read the tail of
worklog.md— the chronological source of truth - Read
docs/MASTER_FEEDBACK.md— the user's exact requirements - Read
docs/MASTER_PLAN.md— the phased implementation plan - Check
docs/CONVENTIONS.md— repo-specific patterns to follow - NEVER create
.jsxfiles — this is a.tsx-only codebase - NEVER create cron jobs — the user has explicitly forbidden this
- ALWAYS run
bun run lint+bunx tsc --noEmitbefore considering work done - ALWAYS append your work record to
worklog.md(don't create separate report files) - The published URL (https://hgtwbefvf.space-z.ai/) is for TESTING ONLY — don't modify it directly
See also docs/HANDOVER.md (AI Agent Guide section) for the dedicated agent guide with testing commands and common patterns.
ExamOps deploys free-tier on Vercel (frontend + API) + Neon (PostgreSQL).
- Switch the Prisma datasource provider
sqlite→postgresqlinprisma/schema.prisma - Set
DATABASE_URL,JWT_SECRET,NODE_ENV=productionin Vercel env vars - Push the schema to prod:
DATABASE_URL=… bun run db:push - Seed (optional):
DATABASE_URL=… bun run db:seed - Change the demo admin password or delete the seeded admin before going live
Full guide with rollback plan: docs/SETUP.md (Deployment section).
MIT