This is the actual "AI Intelligence Learning Agent" — not a mockup. It's built
and typechecks (npx tsc --noEmit passes) and production-builds
(npx next build succeeds) as-is. What's missing is a real database and API
key, and the frontend (which already exists as static HTML prototypes from
earlier in this project — not yet wired to these endpoints).
npm installcp .env.example .env.localand fill in:DATABASE_URL— a Postgres connection string (Railway, Supabase, Neon, or local)ANTHROPIC_API_KEY— from https://console.anthropic.com/NEXTAUTH_SECRET— generate withnpx auth secretNEXTAUTH_URL—http://localhost:3000for local devGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET— from https://console.cloud.google.com/apis/credentials (OAuth 2.0 Client ID, redirect URIhttp://localhost:3000/api/auth/callback/google)
npm run db:setup— appliesdb/schema.sqlthen seeds the Automation Tester flagship goal (15 topics, real dependency graph, curated resources)npm run dev— starts the app at http://localhost:3000
npm run db:dev starts a real embedded PostgreSQL on port 5433 (data lives in
.pgdata/, nothing to install) — keep it running in its own terminal and set
DATABASE_URL=postgres://postgres:postgres@localhost:5433/learnyantra. If
ANTHROPIC_API_KEY is missing or a placeholder, development mode substitutes a
clearly-labeled stub for LLM output so the flow stays testable end to end;
production still requires a real key and will refuse to start without one.
| Piece | Status |
|---|---|
| Postgres schema | Real — matches exactly what the 4 agent functions need, nothing speculative |
| Automation Tester dependency graph | Real — 15 topics, verified acyclic (see chat), sequenced by an actual SDET's judgment |
| Curated resources | Real — genuine official docs / well-known resources, not placeholder links |
| Topic sequencing | Real — deterministic topological sort, not LLM-guessed order (see comment in lib/agent.ts) |
| Roadmap narrative | Real LLM call (Claude Sonnet) — writes framing text around the already-correct order |
| Daily plan generation | Real LLM call (Claude Haiku) — references actual current topic + weak topics from DB |
| Resource matching | Real — but it's a DB lookup, not live web discovery. This is intentionally the "v1" version of the blueprint's Resource Discovery Agent — see the earlier cost/scope conversation for why |
| Auth | Real — NextAuth.js (email/password via bcrypt, plus Google OAuth). All API routes read the user from the session; a user can only ever access their own data |
| Frontend | Partially wired. pages/auth/signin.tsx (sign up/in) and pages/onboarding/index.tsx (the 6-step onboarding flow) are real, working pages that call the live API. Dashboard/roadmap/today pages are still the next piece of work (Phase 2/3) |
| Other 2 flagship goals (UPSC CSE, Class 12 Science) | Not authored yet. Only automation-tester has seed data |
All routes below require an authenticated session (NextAuth cookie) and
operate on the signed-in user only — there is no client-supplied userId
anymore.
POST /api/auth/register— body:{ email, password }. Creates a new user with a bcrypt-hashed password. Sign in afterward via NextAuth'scredentialsprovider.POST /api/onboarding— body:{ persona, goalSlug, interests, skills, hoursPerWeek, deadline }. Updates the signed-in user's profile, then callsgenerateRoadmap()andgenerateDailyPlan(). Returns{ userId }.GET /api/roadmap— returns the roadmap narrative plus every topic with its status (locked/current/done) and dependency info, for the signed-in user.GET /api/daily-plan— returns today's plan for the signed-in user, generating one if it doesn't exist yet.POST /api/progress— body:{ topicSlug, confidence }. Marks a topic done for the signed-in user, unlocks any topic whose dependencies are now satisfied.
NextAuth.js (v5 beta) with two providers:
- Credentials (email/password) —
pages/auth/signin.tsxposts to/api/auth/registerto create the account, then signs in. Passwords are hashed with bcrypt (lib/auth.ts). - Google OAuth — needs
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETset.
Sessions are JWT-based (no separate session table lookups needed per
request). See lib/auth.ts for the full config and types/next-auth.d.ts
for the session.user.id type augmentation.
Note for future sessions: auth() from lib/auth.ts must be called as
auth(req, res) inside Pages Router API routes (see any file under
pages/api/) — calling it with no arguments only works in App Router
Server Components, and will silently return null here.
This is worth understanding before touching lib/agent.ts: topic order
comes from topologicalSort(), a plain graph algorithm over the
hand-authored depends_on edges in db/seed_automation_tester.sql. An LLM
asked to sequence a dependency graph will occasionally produce an invalid
order (skip a prerequisite, loop back). A topological sort mathematically
cannot. The LLM's only job is writing the narrative text around an order
that's already guaranteed correct. This is the actual honest shape of
"dynamic roadmap generation" for an MVP — real per-user computation, without
pretending an LLM is doing graph theory it doesn't need to do.
The app is deploy-ready as-is — no code changes needed once you're in the
Railway dashboard. railway.json pins the build to Nixpacks and the start
command to npm run start; lib/db.ts auto-enables SSL for any
DATABASE_URL that isn't localhost (Railway's managed Postgres requires
it). This section is the checklist for the actual deploy, which only you can
do (it needs your Railway account and control of learnyantra.com's DNS).
- Create the Railway project —
railway.app→ New Project → Deploy from GitHub repo (this repo). Add a Postgres plugin to the same project; Railway setsDATABASE_URLfor you automatically. - Set these environment variables on the app service (Railway →
service → Variables):
DATABASE_URL— already set by the Postgres plugin, leave as-isANTHROPIC_API_KEY— a real key from https://console.anthropic.com/ (production refuses to start without one — no dev-stub fallback)NEXTAUTH_SECRET— generate a fresh one withnpx auth secret(don't reuse the.env.localdev value)NEXTAUTH_URL—https://learnyantra.comGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET— from https://console.cloud.google.com/apis/credentials. Add a second authorized redirect URI to the same OAuth client (don't need a new one):https://learnyantra.com/api/auth/callback/google— keep thelocalhostone too so local dev keeps working.
- Apply the schema once — from your machine, with
DATABASE_URLtemporarily set to the Railway Postgres's connection string (Railway → Postgres plugin → Connect tab has it):npm run db:setup. This is a one-time step, not something that runs on every deploy. - Point the domain — Railway → service → Settings → Networking →
Custom Domain → add
learnyantra.com. Railway gives you a CNAME (or A/ALIAS) target; add that record at whichever registrarlearnyantra.comis registered with. DNS propagation can take up to ~30 minutes. - Verify:
https://learnyantra.comloads the app, Google sign-in redirects back tolearnyantra.com(not localhost), and a fresh sign-up → onboarding → roadmap run completes end to end.
See PHASES.md for the full remaining roadmap to your Sep 1st-week launch, with literal copy-paste prompts for each phase and a week-by-week calendar. See CLAUDE.md for the architectural decisions and conventions every future session (Claude Code or otherwise) on this repo should follow — it's written so you can work independently from here without needing this conversation's context.