Files
arnaudne 4e38b5a791 feat: initial commit — Curio mastery tutor
Full Next.js App Router application with:
- AI-graded lesson checkpoints (BKT/Elo mastery tracking)
- Auth.js v5: credentials, Google, GitHub, generic OIDC
- Anonymous-session-first with migrate-on-signin
- Admin panel: users, blueprints, reports, site settings
- Password reset + email verification (nodemailer/SMTP)
- Site config: require_auth + signups_enabled flags
- server-only guards on all DB/generation/verification modules
- PostgreSQL 16 + pgvector, Redis cache, Drizzle ORM
- 271 unit tests (Vitest), golden-eval harness, Playwright e2e stubs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:25:43 +02:00

151 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```bash
# 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
```bash
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`](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:
```bash
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