arnaudne 5bf6013460 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>
2026-07-08 22:08:14 +02:00

Curio

A curiosity-led mastery tutor. Learner states intent → gets a bounded ~10-minute Lesson → AI diagnoses free-text responses against pre-verified rubrics and a per-concept misconception library → gates advancement on demonstrated mastery.

The moat is diagnosis: inferring what a learner misunderstands and why, not content generation.


Prerequisites

  • Node.js 20+, pnpm 9+
  • Docker (for Postgres + Redis)
  • API keys: Anthropic (generator) + OpenAI (grader) at minimum

Quick start

# 1. Clone and install
pnpm install

# 2. Copy env and fill in API keys
cp .env.example .env.local
# Required: ANTHROPIC_API_KEY, OPENAI_API_KEY
# Optional: LANGFUSE_* for tracing, UPSTASH_* for rate limiting

# 3. Start Postgres (port 5433) + Redis (port 6379)
docker compose up -d

# 4. Run migrations
pnpm drizzle-kit generate && pnpm drizzle-kit migrate

# 5. Seed the JS Closures demo topic
pnpm seed

# 6. Start dev server
pnpm dev
# → http://localhost:3000

Environment variables

All vars documented in .env.example. Key ones:

Variable Required Description
DATABASE_URL postgresql://curio:curio@localhost:5433/curio (docker default)
REDIS_URL redis://localhost:6379 (docker default)
ANTHROPIC_API_KEY Generator model (default: claude-sonnet-4-6)
OPENAI_API_KEY Grader + embeddings (default: gpt-4o-mini, text-embedding-3-small)
LANGFUSE_SECRET_KEY LLM call tracing; logs to console when absent
SESSION_TOKEN_BUDGET Per-session output token cap (default: 50000)
CONTENT_SAFETY_MODE open / controlled (default) / enterprise-safe

Provider-agnostic: generator, grader, and embeddings are each independently configurable. Supported: Anthropic, OpenAI, Google Gemini, Mistral, Cohere, Groq, xAI, AWS Bedrock, Azure OpenAI, OpenRouter, Ollama (fully local, no API keys). See .env.example for all options.


Commands

pnpm dev                     # Next.js dev server
pnpm build                   # Production build
pnpm test                    # Vitest unit tests (LLM mocked — no API keys needed)
pnpm test:watch              # Watch mode
pnpm test:e2e                # Playwright end-to-end
pnpm test:golden             # Real-model grading eval (CI-gated, needs API keys)
pnpm test:golden:misconceptions  # Misconception quality eval
pnpm test:golden:content     # Content verification eval
pnpm workers                 # BullMQ background workers (lesson generation, blueprint promotion)
pnpm seed                    # Seed JS Closures demo corpus (idempotent)
pnpm seed -- --force         # Drop and re-seed
pnpm lint                    # ESLint
pnpm format                  # Prettier
pnpm drizzle-kit generate    # Generate migration from schema changes
pnpm drizzle-kit migrate     # Apply pending migrations
pnpm drizzle-kit studio      # Drizzle Studio (DB browser)

Architecture

Request path (fast, no generation):
  GET /api/lessons → Redis cache → Postgres → LessonResponse

Generation path (background, async):
  POST /api/lessons cold-start → enqueue BullMQ job → generate-lesson-job
  Blueprint promotion (T2 verify + variants) → promote-blueprint-job

Grading (per response):
  POST /api/grade → cheapGrader (rubric match) → escalate to strong grader if uncertain/novel
  → persist response + grade → update mastery (BKT) → auto-flag collective failures

LLM:
  All calls via src/lib/llm/client.ts — never call providers directly
  Prompts in src/lib/llm/prompts/ (versioned registry)
  Contracts are Zod schemas in src/schemas/ (shared API ↔ LLM ↔ UI)

See docs/curio-specification.md for full product + architecture reference.


Repo structure

src/
  app/                  # Next.js App Router: pages + api/ route handlers
  components/           # UI components (LessonReader, GradeDisplay, …)
  lib/
    llm/                # LLM client + versioned prompt registry
    generation/         # RAG-grounded content generation
    verification/       # Content cascade (T0T2) + response grader
    memory/             # Mastery (BKT/Elo) + spaced repetition
    intent/             # Intent normalization + blueprint lookup
    db/                 # Drizzle schema, queries, migrations, seed data
    cache/              # Redis lesson buffer
    jobs/               # BullMQ queue helpers
    observability/      # Langfuse / OpenTelemetry tracing
  schemas/              # Zod contracts (shared)
  styles/               # Design tokens (CSS custom properties)
jobs/                   # BullMQ workers (generation, promotion)
tests/golden/           # Frozen eval sets: grading accuracy + content verification
e2e/                    # Playwright
docs/
  curio-specification.md

Running workers

Background jobs handle lesson generation and blueprint promotion (T2 verification + difficulty variant generation). Run separately from the web server:

pnpm workers

Workers require Postgres, Redis, and API keys. In production, run as a separate process or container.


Tech stack

Next.js 15 (App Router) · TypeScript · Vercel AI SDK · Zod · PostgreSQL 16 + pgvector · Drizzle ORM · Redis · BullMQ · Tailwind · Vitest · Playwright

S
Description
No description provided
Readme 674 KiB
Languages
TypeScript 89.9%
CSS 9.8%
Dockerfile 0.2%