- Created handover document outlining design decisions and application functionality. - Developed implementation plan detailing phased approach for service development. - Specified ingestion service responsibilities, API surface, and processing pipeline.
5.0 KiB
CLAUDE.md
What you are building
A mobile-first progressive web application for employee learning. Employees follow a perpetual 26-week curriculum built from an internal knowledge base. An AI assistant called R42 is available on every screen. Admins upload source documents that are processed into the knowledge base by AI.
Read the full design before writing any code:
- /docs/handover.md — all decisions made, rationale, constraints
- /docs/architecture.md — system design, data flows, tech stack
- /docs/data-model.md — all PocketBase collections, Qdrant schema, types
- /docs/ingestion-spec.md — ingestion service (build this first)
- /docs/implementation-plan.md — ordered build sequence with acceptance criteria
Absolute constraints
These rules are non-negotiable and apply to every session:
- Never modify any file listed in PROTECTED.md
- Never modify any file outside /app — the pipeline, Dockerfile, ansible, and docker-compose files are frozen
- Never delete files without explicit confirmation
- Never change package.json scripts that contain 'deploy' or 'build:prod'
- Ask before acting when scope is unclear — do not infer intent from legacy/ code
Repository structure
repo/
├── CLAUDE.md ← you are here
├── PROTECTED.md ← files you must never touch
├── docs/ ← spec files — read, never modify
├── legacy/ ← old prototype — read-only reference only
└── app/ ← your working directory
├── frontend/ ← Next.js 14 PWA
└── services/
├── ingestion/ ← build first
├── generation/ ← build second
├── curriculum/ ← build third
├── embedding/ ← integrated into ingestion, separate later
├── chat/ ← R42
└── progress/ ← gamification
All work happens inside /app. No exceptions.
Tech stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, TypeScript strict, Tailwind CSS, PWA |
| Backend state | PocketBase (binary, not source — do not scaffold from scratch) |
| Vector store | Qdrant via REST client |
| AI generation | Claude Sonnet 4 — model string: claude-sonnet-4-20250514 |
| AI chat (R42) | Claude Haiku 4.5 — model string: claude-haiku-4-5-20251001 |
| Embeddings | OpenAI text-embedding-3-small |
| Services | Node.js, Fastify, TypeScript strict |
| Validation | Zod on all external data (API responses, AI output, PocketBase) |
Stylesheet
An existing stylesheet lives at /stylesheet.css in the repo root. This is the authoritative visual style for the application.
Rules:
- Never modify stylesheet.css
- Import it as a global stylesheet in the Next.js frontend
- Do not override its rules with Tailwind utility classes or inline styles
- When Tailwind and the stylesheet conflict, the stylesheet wins
- If a UI element is not covered by the stylesheet, use Tailwind — but match the visual language (spacing, colour, type scale) of the existing stylesheet
Code conventions
- TypeScript strict mode everywhere — no
anytypes - All Claude API responses validated through Zod before use
- All PocketBase writes typed against collection schemas in data-model.md
- Qdrant payloads explicitly typed — no untyped objects
- No inline hardcoded API keys — environment variables only
- REST conventions for all service APIs
- Mobile-first CSS — design for 375px width, scale up
Build order
Follow /docs/implementation-plan.md exactly. Do not skip phases. Do not build phase N+1 before phase N passes its acceptance criteria.
Current phase: Phase 1 — Infrastructure + ingestion service
Session discipline
Each session has a defined scope in implementation-plan.md. At the start of each session:
- State which phase and step you are working on
- Read the relevant spec file(s)
- Propose a file structure or change plan before writing code
- Implement after the plan is clear
At the end of each session:
- State what was completed
- State what acceptance criteria have been met
- State what the next session should start with
When you are uncertain
Check the spec files in /docs first. If the spec does not cover it, flag the gap explicitly rather than making an assumption. Do not look at legacy/ code for implementation guidance — it is a different stack and will lead you in the wrong direction.
Environment variables
Each service has its own .env file. Templates are defined in each service spec. Never commit actual values. Always use .env.example with placeholder values.
The full set across all services:
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
POCKETBASE_URL=
POCKETBASE_ADMIN_EMAIL=
POCKETBASE_ADMIN_PASSWORD=
QDRANT_URL=
QDRANT_API_KEY=
INGESTION_PORT=3001
GENERATION_PORT=3002
CURRICULUM_PORT=3003
CHAT_PORT=3004
PROGRESS_PORT=3005
NEXT_PUBLIC_API_URL=
NEXT_PUBLIC_POCKETBASE_URL=