feat: full feature buildout — streaming, i18n, mastery map, admin, jobs

Progressive lesson streaming via onSegment callback (fixes SSE for non-English
users — locale was shadowed in lesson-reader useEffect). Adds: BullMQ workers,
Redis stream buffer, token budget enforcement, Langfuse tracing, golden-eval
runner, Playwright e2e scaffolding, lesson depth/locale/preferences schema,
mastery map UI, admin panel (blueprints/users/reports/quality/misconceptions),
image queries, source citations, view transitions, reading animations, i18n
(next-intl), PDF export, surprise endpoint, and 402 passing unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 22:08:14 +02:00
parent 4e38b5a791
commit 5bf6013460
161 changed files with 27152 additions and 1161 deletions
+70
View File
@@ -0,0 +1,70 @@
# Theme Map — Implementation Plan
## Goal
A visual theme map that lets users discover and start lessons by topic domain. Entry flow B: clicking a theme pre-fills the home intent input, keeping the intent-driven flow intact.
## Fixed taxonomy (12 themes, stable slugs)
| Slug | Label (FR) | Label (EN) | Emoji |
|---|---|---|---|
| `sciences-naturelles` | Sciences naturelles | Natural sciences | 🔬 |
| `mathematiques` | Mathématiques | Mathematics | ∑ |
| `histoire` | Histoire | History | 📜 |
| `geographie` | Géographie | Geography | 🌍 |
| `langues-litterature` | Langues & littérature | Languages & literature | 📖 |
| `arts-culture` | Arts & culture | Arts & culture | 🎨 |
| `technologie-informatique` | Technologie | Technology | 💻 |
| `philosophie-ethique` | Philosophie & éthique | Philosophy & ethics | 💭 |
| `economie-societe` | Économie & société | Economics & society | 📊 |
| `sante-medecine` | Santé & médecine | Health & medicine | 🏥 |
| `sport-activite` | Sport & activité | Sport & activity | ⚡ |
| `autre` | Autre | Other | ✦ |
## Phases
### Phase 1 — Data model
- `theme` table: `id (uuid pk), slug (unique), label_en, label_fr, emoji`
- `blueprint_theme` join: `blueprint_id → blueprint, theme_id → theme` (composite pk)
- Seed `theme` rows in migration (fixed taxonomy, never regenerated)
- Add `themes: string[]` to `BlueprintContentSchema` Zod schema
- Bump `GENERATE_BLUEPRINT` to v3 — instruct LLM to pick 13 slugs from taxonomy
- Update `generate-blueprint.ts` — after blueprint insert, upsert `blueprint_theme` rows
### Phase 2 — Static cluster view (`/map`)
- New page `/map` — grid of theme cards
- Each card: emoji + label + count of user's blueprints in theme
- Click card → `/?theme=<slug>` (home page with pre-filled context)
- No graph lib needed — pure CSS
### Phase 3 — Home page theme pre-fill
- Read `useSearchParams().get('theme')` on home page
- If present: pre-fill the intent input placeholder and initial value with a localised prompt
e.g. `?theme=sciences-naturelles` → input shows "En savoir plus sur les sciences naturelles…"
- Clear the param after submission
### Phase 4 — Graph view
- Toggle on `/map`: list view ↔ graph view
- SVG-based radial layout — 12 theme nodes arranged in a circle, no physics
- Blueprint sub-nodes orbit each theme (smaller dots)
- Node color = mastery aggregate for that theme (green / amber / grey)
- Click node → `/?theme=<slug>`
- Pure SVG + CSS transitions, no animation library
## Adjacency (hardcoded, for SVG edges)
Related themes share an edge in the graph:
- sciences-naturelles ↔ mathematiques, geographie, sante-medecine, technologie-informatique
- mathematiques ↔ technologie-informatique, economie-societe
- histoire ↔ geographie, philosophie-ethique, arts-culture, langues-litterature
- geographie ↔ economie-societe, sport-activite
- langues-litterature ↔ arts-culture, philosophie-ethique
- arts-culture ↔ philosophie-ethique
- technologie-informatique ↔ economie-societe
- philosophie-ethique ↔ economie-societe
- sante-medecine ↔ sport-activite
## Invariants respected
- No new LLM provider — theme assignment uses same generator model via client.ts
- Theme prompt is versioned in the registry
- Blueprint generation stays synchronous (themes saved in same transaction)
- No animation library — SVG + CSS transitions only
- Mobile responsive — graph falls back to list on small screens