Author SHA1 Message Date
hahachait 59fcb4af17 docs: add v2 rebuild direction
Captures the new product vision: layout rebuild away from the
ChatGPT-style shell, practice games (timed, challenge, live,
leaderboard), and an animated stage panel alongside chat.

Records the wait-time analysis: playback is free, rendering is
never on the request path, so the cost is authoring. Strategy is a
parameterized composition library filled by AI JSON rather than
generated code per answer.

Six open decisions flagged with recommendations.
2026-11-11 00:48:01 -05:00
+196
View File
@@ -0,0 +1,196 @@
# padhle v2 — Rebuild Direction
Working doc. Decisions still open are marked **DECIDE**. This is a plan, not a commitment to every item.
---
## Why a rebuild
The current app is a competent ChatGPT clone. That was v1's thesis: an AI tutor in a chat box. It works, but the shell gives the product away — sidebar of threads, message list, input at the bottom. Every student has used that exact interface before, so nothing signals "this is different, this is built for CBSE."
v2 thesis: **the chat is one surface, not the whole product.** The differentiators are things a chat box cannot do — practice under time pressure, competition against other students, and seeing the concept move instead of reading about it.
---
## Current state (the baseline we're rebuilding from)
| Piece | What exists |
| --- | --- |
| Shell | `App.jsx` — `Sidebar` + `TopNav` + `ChatHistory` + `ChatInput`. 1046 lines of JSX total across 10 files. |
| Chat | `useChat` hook → `POST /api/chat`, **SSE streaming** (`backend/src/services/sse.js`). Real streaming, not fake typing. |
| Context | Grade → subject → chapter selector (`selector-flow`, `data/curriculum.js`) |
| Auth | Supabase, plus a 5-free-message anonymous trial (`backend/src/services/anonTrial.js`, in-memory) |
| Persistence | `sessions` / `messages` via Supabase + RLS (see `docs/security-audit-2026-08-20.md`, RLS bypass was fixed — do not regress it) |
| Styling | 1950 lines of hand-rolled CSS on Material-3 tokens, `className`-based |
| Astryx | Installed and wired (`theme-neutral`, layered CSS, `<Theme>` wrapper) but **zero components used yet** |
Two things worth naming before we start:
- **Astryx is now load-bearing or it should be removed.** A rebuild that adds game UI, modals, timers, leaderboard tables, and settings screens is exactly the workload that pays for 174 accessible primitives. Ship this rebuild on Astryx primitives or uninstall it — running it half-used is the worst of both.
- **The SSE contract is good and should survive the rebuild.** Don't re-invent the chat transport.
---
## 1. Layout — stop looking like ChatGPT
### The problem, precisely
Three things make the current shell read as ChatGPT: (a) persistent left thread sidebar, (b) single centered column of bubbles, (c) bottom-anchored input as the only action. Changing the colors won't fix it. The information architecture has to change.
### Direction A — "Study desk" (recommended)
The chat is one panel on a workspace, not the page itself.
```text
┌──────────────────────────────────────────────────────┐
│ chapter context bar: Class 12 · Economics · Ch 3 │ ← where you are, always
├───────────────────┬──────────────────────────────────┤
│ │ │
│ chat / tutor │ THE STAGE │
│ (left, narrow) │ animation · diagrams · │
│ │ formula breakdown · notes │
│ │ │
├───────────────────┴──────────────────────────────────┤
│ practice strip: [Quick quiz] [Timed game] [Ask] │ ← actions, not just typing
└──────────────────────────────────────────────────────┘
```
Key moves:
- Chapter context is a **persistent header**, not a modal flow. You always know what you're studying.
- Threads live in a **drawer/secondary surface**, not a permanent sidebar. Kills the #1 ChatGPT tell.
- The right side is *the reason to be here* — it holds the animation (section 3) and later notes/flashcards.
- The bottom strip is a **mode switcher**, so the product has more than one verb.
### Direction B — "Card feed"
Chapter opens as a deck of cards (concept, worked example, practice, quiz). Chat is a floating assistant available on any card. More differentiated, more work, abandons thread continuity. **DECIDE: A or B.**
### Direction C — "Dashboard-first"
Land on progress + weak chapters + streaks; chat is a drill-down. Good retention shape, but needs data you don't collect yet.
**Recommendation:** A now, C later — A's layout is a superset that C can fill in.
---
## 2. Practice games — timer, challenge, multiplayer, leaderboard
This is the feature that makes padhle not-a-chatbot. It's also the **only** feature here with no AI dependency, so it can ship independently and fast.
### Modes
| Mode | Shape | Notes |
| --- | --- | --- |
| **Solo timed** | N questions, countdown, score | Simplest. Ship first. No backend beyond scores. |
| **Challenge** | Share a link/code, friend plays the same question set, scores compared async | Cheap "multiplayer" — no realtime needed, still feels competitive |
| **Live match** | 2–4 players, same questions, realtime, reveal on sync | Needs realtime. Ship third. |
| **Leaderboard** | Per chapter / per grade / weekly | One table, one index. Not a service. |
### Realtime: use what you already pay for
Supabase Realtime (already a dependency) gives broadcast + presence. **Do not** add socket.io or a second server. Live match = one channel per room, host broadcasts question index, clients answer, host broadcasts result. Presence handles "player left."
### Anti-cheat floor (don't over-build this)
Answers must never ship to the client before the question is answered — send question + options, validate server-side. Countdown is server-authoritative (store `started_at`, reject answers after deadline + grace). Anything beyond that (tab-focus detection, etc.) is not worth the complexity for a study app.
### Question source — **DECIDE**
1. **Curated bank** — hand-written JSON per chapter. Fast, correct, pedagogical, boring to produce, but a bad question is worse than no question.
2. **AI-generated at runtime** — infinite supply, but latency + wrong answers + needs validation. Wrong answers in a study app are a trust-killer.
3. **AI-generated offline, curated before shipping** — generate with the model, human-review, store in the bank. Best of both; costs review time.
**Recommendation:** 3. Start with a tiny hand-written bank (30 questions, one chapter) to prove the loop, then batch-generate.
### Data model sketch
```sql
questions(id, chapter_id, subject, grade, prompt, options_json, correct_index, difficulty)
matches(id, chapter_id, mode, started_at, ended_at, state)
match_players(match_id, user_id, score, correct_count, ms_total, answers_json)
scores_weekly(view over match_players) ← leaderboard reads this, not the raw tables
```
---
## 3. The animated window — the hard one
### What it is
While the student reads/asks in the chat, a panel plays a generated animation of the concept — the equation moving, the graph drawing itself, the process stepping through. Teacher-on-a-whiteboard, not a video.
### The wait-time problem — this is the real risk, not rendering speed
The user flagged it correctly. Let's be precise about where the latency actually lives, because the obvious fix is the wrong one.
Three distinct costs get confused:
| Cost | Reality |
| --- | --- |
| **Playback** | Free. Both Remotion (`<Player>`) and Hyperframes run compositions live in the browser. This is *not* the problem. |
| **Authoring** | **This is the problem.** If the model writes new animation code per answer: LLM latency (2–8s) + code-must-be-correct-first-try + bundle/eval. Non-deterministic and slow. |
| **Rendering to MP4** | Only relevant if you pre-produce video. Headless-Chrome render is seconds-per-second-of-footage. Never do this on a request path. |
So the question is not "how do we render fast," it's **"how do we avoid generating animation at request time."**
### Remotion vs Hyperframes — pick per purpose, not one for both
- **Remotion** = React video → render to MP4. Right for **pre-produced content**: the launch trailer (`remotion-inst.txt`), chapter intros, marketing. `my-video/` and `remotion-testing/` already exist. Slow to build, deterministic to play.
- **Hyperframes** = HTML/CSS/GSAP composition that plays live in the browser. Right for **per-answer in-app animation** — no render step at all, it's just DOM.
For the in-chat stage: **Hyperframes (or Remotion `<Player>` on pre-built compositions)**. Do not put a render server on the request path.
### The strategy that actually kills the wait — bank, don't generate
1. **Pre-author a composition library.** One composition *family* per concept shape, not per topic: "solve an equation step-by-step," "draw a graph from a function," "walk a biological process," "annotate a diagram." A family is parameterized, so the same composition renders quadratic *and* linear equations.
2. **The AI fills parameters, not code.** It returns JSON — `{family: "solve-equation", steps: [{lhs, rhs, note}, ...]}` — validated against a schema. Deterministic, instant to apply, impossible to produce broken code.
3. **Unknown shape → text only.** If the reply doesn't map to a family, the animation panel stays collapsed. Never block the answer waiting for an illustration.
4. **Progressive reveal.** Text streams first (already works, SSE). The stage renders as soon as the first step arrives. The student never watches a spinner where an answer should be.
5. **Timing sync.** Animation steps advance as the corresponding text *sentences* stream in — one shared step timeline, driven by the SSE events you already emit. This is what makes it feel authored rather than bolted on.
That reduces wait time to **zero added latency** for the common case, and the only novel work is authoring ~6–10 composition families well.
### Fallbacks (always present)
Skeleton immediately → parameterized composition if it resolves → static render of the first frame if the composition errors → text only. The stage must never be the reason the app feels broken.
**DECIDE:** how many composition families for v2? **Recommendation: 3** — equation solving, graph drawing, step-through process — proven on one chapter each. Breadth is cheap once the parameter pipeline exists; depth is what's expensive.
---
## 4. Sequencing
Ordered by risk retired per unit of work, not by excitement.
| Phase | What | Why here |
| --- | --- | --- |
| **0** | Kill or commit Astryx; port existing chat into Astryx primitives | Every later phase builds on the shell. Decide once. |
| **1** | Layout rebuild (Direction A) with a **static** stage panel | Cheapest, most visible change; proves the shell before anything depends on it |
| **2** | Practice games: solo timed + question bank + leaderboard | Zero AI, zero realtime, fully shippable — first non-chat feature |
| **3** | Challenge links (async head-to-head) | Reuses phase 2 entirely; needs only share + compare |
| **4** | Stage panel goes live: 1 composition family end-to-end | Proves the bank-and-parameterize thesis on the cheapest concept |
| **5** | Live multiplayer match (Supabase Realtime) | Highest complexity; now has games + realtime budget proven |
| **6** | Composition families 2 & 3, chapter coverage | Scale once the pipeline is trusted |
| **7** | Dashboard-first landing (Direction C) | Needs the telemetry phases 2–5 generate |
Phases 1–3 make it a different product. Phases 4–5 make it a defensible one.
---
## Open decisions
- [ ] **Layout:** Direction A (study desk) / B (card feed) / C (dashboard-first) → *recommend A*
- [ ] **Astryx:** commit to primitives, or uninstall → *recommend commit; this rebuild is the justification*
- [ ] **Question bank:** curated / runtime-AI / offline-generated-then-curated → *recommend offline-generated-then-curated*
- [ ] **Stage engine:** Hyperframes / Remotion `<Player>` / both (Remotion for pre-produced only) → *recommend Hyperframes in-app, Remotion for trailer*
- [ ] **Composition families in v2:** how many, which ones → *recommend 3*
- [ ] **Scope guard:** does the existing chat/trial/auth/RLS behavior stay identical? → *recommend yes, untouched*
## Non-goals for v2
- Native mobile app
- Teacher/parent dashboards
- Video *lessons* (recorded lecture playback) — the stage is generated animation, not a video library
- Real-time text chat between students (multiplayer is score competition, not social)
- Rewriting the backend transport layer