|
| 1 | +# CENTRAL.md — Working notes and orientation |
| 2 | + |
| 3 | +Living doc kept by Claude across sessions. Update after each big change. If you're picking up cold: read this top-to-bottom, then `git log --oneline -20`, then dive in. |
| 4 | + |
| 5 | +## Project shape |
| 6 | + |
| 7 | +DBSMO is a Next.js 15 (App Router) Postgres+Prisma platform for self-paced math olympiad training at Diocesan Boys' School. Everything is server-rendered by default; a handful of `"use client"` components handle interactive UI (typewriter greeting, theme toggle, answer grid, FTW match). |
| 8 | + |
| 9 | +Stack: Next.js, NextAuth (Google + dev bypass), Prisma, KaTeX for math, Lucide icons, Vitest. No Tailwind — single 5k-line `app/globals.css`. |
| 10 | + |
| 11 | +## Where things live |
| 12 | + |
| 13 | +- `app/` — routes. Server components unless marked `"use client"`. Admin under `app/admin/*`. |
| 14 | +- `app/api/**/route.ts` — REST handlers. |
| 15 | +- `lib/` — shared logic: `auth.ts`, `db.ts` (Prisma singleton), `grading.ts`, `permissions.ts`, `visibility.ts`, `analytics.ts`, plus the `import/` ZIP+JSON pipeline. |
| 16 | +- `prisma/schema.prisma` — single source of truth for the data model. |
| 17 | +- `tests/` — Vitest specs for grading, tags, ordering, visibility, import. |
| 18 | +- `app/globals.css` — all styles. Light mode at the top (`:root`), dark via `@media` and `html.dark`. |
| 19 | + |
| 20 | +## Conventions |
| 21 | + |
| 22 | +- Page files do their own `getServerSession` + permission gate; no shared middleware. |
| 23 | +- Permission keys in `lib/permissions.ts` — `admin:view`, `admin:content`, etc. Use `hasPermission(role, key)`. |
| 24 | +- LaTeX statements rendered through `<LatexStatement>` (KaTeX auto-render). |
| 25 | +- Answer normalisation lives in `grading.ts`; do not roll your own comparison. |
| 26 | +- CSS variables drive theming. Add new colors as variables in `:root` AND in dark overrides — both. Don't hard-code hex outside `globals.css`. |
| 27 | + |
| 28 | +## What's currently in flight |
| 29 | + |
| 30 | +### Now (this session) |
| 31 | + |
| 32 | +- **FTW (Alcumus For The Win) mode** — speed-based timed problem race against the clock. Single-player first; friends-async leaderboard. Scoring rewards fast correct answers (AoPS-style: max points decay with elapsed time). Routes under `/ftw`, schema additions `FtwMatch`/`FtwAnswer`. Gets a sidebar entry. |
| 33 | +- **Light-mode rehaul** — current light theme reads as flat AI-generated. Goals: warmer paper-white background, deliberate ink colors, fewer purple/cyan washes, pink reserved as accent (matches dark). Keep dark+pink as-is. |
| 34 | +- **Less AI vibe** — copy passes (no eyebrow soup, no "hero panel" walls of cards), tighter spacing, fewer gradients. Keep the typewriter greeting unchanged. |
| 35 | + |
| 36 | +### Next (after the above lands) |
| 37 | + |
| 38 | +- `/simplify` pass on the codebase. |
| 39 | +- Sweep for dead code and CSS leaves now that several features have rotated through. |
| 40 | + |
| 41 | +## Testing locally |
| 42 | + |
| 43 | +```bash |
| 44 | +npm run typecheck # tsc --noEmit |
| 45 | +npm run lint |
| 46 | +npm run test # vitest |
| 47 | +npm run build # next build (catches CSS/JSX issues at scale) |
| 48 | +npm run dev # next dev — open http://localhost:3000 |
| 49 | +``` |
| 50 | + |
| 51 | +`npm run dev` may fail without `DATABASE_URL`. Pages that hit Prisma will 500; static routes still render. `next build` runs without DB. |
| 52 | + |
| 53 | +## Git protocol for this repo |
| 54 | + |
| 55 | +- Push checkpoints to `origin/main` after each big milestone (user has bypass perms enabled and asked for this). |
| 56 | +- Use HEREDOC commit messages, two short paragraphs max. |
| 57 | +- Never `--no-verify`, never amend pushed commits, never force-push. |
| 58 | + |
| 59 | +## Recovery |
| 60 | + |
| 61 | +If a file goes missing: |
| 62 | +```bash |
| 63 | +git fetch origin |
| 64 | +git checkout origin/main -- <path> |
| 65 | +``` |
| 66 | +Then read the file, reconcile with what's in memory, keep going. |
| 67 | + |
| 68 | +## Open questions / followups |
| 69 | + |
| 70 | +- Realtime multiplayer FTW would need Pusher / WebSockets — out of scope for now. Async friend matches first. |
| 71 | +- `/api/practice/tags` is referenced from `practice/page.tsx` but I haven't reviewed it; check before touching. |
| 72 | +- `globals.css` has a "2026 refresh" overlay starting around line 2175 — overrides earlier rules. Edit there for visual changes, not the top. |
0 commit comments