📘 LatentRAG — Master Manual  
Version 2.0 · "Notebook Edition" · 2026  
$ man latentrag — “Build Your Own Skills & Job.”  
 1 · Quick facts  
| | |  
|-|-|  
| Item | Value |   
|  Stack | Next.js (App Router) · TypeScript · Tailwind + shadcn · Prisma + SQLite · Zustand |   
|  Themes | dark honey-amber · light burnt-sienna · cyber phosphor-CRT — press T to cycle |   
|  Careers | AI & LLM Engineer · ML & MLOps Engineer · shared Foundations |   
|  Pricing | Free tier = Phase 1 · Pro $29/mo = all 15 courses |   
|  Module formats | video · notes.md · lab.ipynb · courseware.pdf · code/ |   
|  AI | per-module $ tutor --chat console · floating voice --listen tutor |   
|  Test card   (checkout) | 4242 4242 4242 4242, any future date, any CVC |   
2 · Project map  
src/ app/ layout.tsx fonts (Fraunces/JetBrains Mono/Space Grotesk), theme init script page.tsx view router — renders Header + current view + VoiceTutor globals.css ALL design tokens (:root[data-theme]) + notebook styles components/ theme-provider.tsx 3-state theme (dark/light/cyber), localStorage, [T] hotkey devlog-ui.tsx typewriter hook, Reveal, CountUp, CodeWindow (copy-flash) notebook-ui.tsx TerminalTabs, AsciiProgress, PathCrumb, Panel, TutorConsole, MarkdownLite, progress adapters voice-tutor.tsx floating voice --listen console (Web Speech API) header.tsx nav, live-learners pill, theme toggle, progress bar views/ landing, dashboard, course, module, pricing, checkout, account lib/ store.ts (Zustand) · auth.ts (cookie sessions) · utils.ts scripts/seed.ts the entire curriculum — EDIT ME to change content public/ hero/student-lady.png hero photo (swap freely) courseware/ drop PDFs here docs/ this manual (md + pdf, linked in footer)  
   
text  
   
---  
   
## 3 · Run locally (Windows / PowerShell)  
   
```powershell  
cd C:\Users\Owner\ai-careers  
npm install  
npx prisma db push          # create/sync SQLite db  
npx tsx scripts/seed.ts     # load curriculum (idempotent — safe to re-run)  
npm run dev                 # → http://localhost:3000  
First run checklist: sign up → pick a track → open Phase 1 course → send /help in the tutor console → checkout with the test card → verify Phase 4 unlocks.  
4 · Managing the landing page  
All public-facing copy lives as constants at the top of src/components/views/landing.tsx — no digging through JSX:  
| | |  
|-|-|  
|  What you see |  Constant to edit |   
|  Typewriter phrases | PHRASES (5 strings; hex strings welcome) |   
|  Italic subtitle | SUB |   
|  Paragraph under it | DESC |   
|  Big stats (15 / 60+ / 14) | the <CountUp to={…}> values in the hero stats grid |   
|  Marquee tech list | TECH array |   
|  Track cards (01/02/03) | TRACKS array (num, tag, title, meta, body) |   
|  Five-phase archive list | PHASES array |   
|  Floating glass chips on photo | the three .glass-chip divs in the hero (tracks / tutor / salary) |   
   
   
   
   
Hero photo: replace public/hero/student-lady.png (portrait, 3:4 ideal). Crop is automatic (object-cover); adjust framing via objectPosition (default "center 22%" = face-forward). The cyber theme applies a phosphor duotone automatically — no extra work.  
Footer: edit the echo "…" line and the man --md / man --pdf links (serve files from public/docs/).  
5 · Managing content (courses & modules)  
Everything is one file: scripts/seed.ts. It is idempotent — re-running updates existing records by id and never duplicates or wipes progress.  
5.1 Anatomy of a module (all 5 formats)  
ts  
{  
  title: "Hybrid Retrieval: Dense + Sparse",  
  type: "lab",               // label shown on tabs/cards  
  order: 2,                  // position inside the course  
  durationMin: 75,  
  videoUrl: "https://your-cdn.com/w6l2.mp4",        // ① video tab (any mp4 URL)  
  notesMd: "# Hybrid retrieval\nWhy BM25 still matters…",   // ② notes.md tab  
  labMd: "## Lab 2\n1. Implement bm25()…",                  // ③ lab.ipynb tab  
  pdfUrl: "/courseware/w6l2.pdf",                    // ④ pdf tab (file in public/courseware/)  
  sampleCode: [                                      // ⑤ code/ tab — copy-flash windows  
    { filename: "hybrid_search.py", raw: "def hybrid_search(...):\n    ..." },  
  ],  
}  
Leave any field empty and that tab shows a helpful $ placeholder instead of breaking.  
5.2 Course-level fields  
ts  
title, description,  
track: "shared" | "ai-llm" | "ml-mlops",   // "shared" = visible to both tracks (free tier)  
phase: 1..5,                                // drives dashboard grouping  
tier: "free" | "pro",                       // "pro" = locked until subscription  
5.3 Workflow  
Edit scripts/seed.ts (add a module, tweak copy, attach a PDF).  
Re-run npx tsx scripts/seed.ts.  
Refresh the site — dashboards, progress, and locks update automatically.  
Video hosting options (cheapest first): direct MP4 on any object storage · Cloudflare Stream (~$5/mo) · Mux · Vimeo unlisted. Paste the URL into videoUrl.  
6 · Users, auth & subscriptions  
Auth: email + password, cookie session (src/lib/auth.ts). The in-memory session map is hoisted to globalThis so it survives dev-mode module splits.  
Gating: a course with tier: "pro" shows the access --denied panel for free users; the dashboard marks rows upgrade →.  
Checkout: currently the built-in mock (test card 4242…). To go live, replace the card block in /api/subscribe/route.ts with stripe.checkout.sessions.create() — the route's shape is already structured for it.  
Account changes: PATCH /api/account (e.g., { "track": "ai-llm" }) — used by the dashboard track picker.
6.1 Domain (latentrag.com): Vercel → Project → Settings → Domains → addlatentrag.com + www.latentrag.com. 
At your registrar:A record @ → 76.76.21.21 · CNAME www → cname.vercel-dns.com.SSL is automatic. 
Set www → apex redirect in Vercel. metadataBase is already set.  
7 · AI instructors  
| | | |  
|-|-|-|  
| Feature | Where | Notes |   
| Module tutor console | notebook-ui.tsx → TutorConsole | slash commands: /explain /quiz /hint /clear /help; replies type out char-by-char |   
| Voice tutor | voice-tutor.tsx | push-to-talk mic chip; replies spoken via TTS (tts:on/off); needs Chrome/Edge for mic — text input works everywhere |   
| Backend | POST /api/instructor/chat | context-aware when moduleId is sent; general career mode otherwise (voice-friendly short answers) |   
| Model | z-ai-web-dev-sdk in the route | swap for OpenAI/Anthropic by editing that one file's SDK call |   
Mic permissions: first click triggers the browser prompt — the tutor prints a friendly error if denied. Mute: the tts:off toggle stops all speech; visual typewriter output continues.  
8 · Theme system  
Switch: header pill (moon/sun/terminal) or press T anywhere (ignored while typing in inputs). Persists in localStorage key aihub-theme; a pre-hydration script prevents flash-of-wrong-theme.  
Recolor: every color is a CSS variable in globals.css under :root[data-theme="dark|light|cyber"]. Key tokens:  
| | |  
|-|-|  
| Token | Meaning |   
| --acc / --acc2 | primary accent / secondary accent (buttons, tags, gradients) |   
| --paper, --panel | page background / card background |   
| --ink, --ink-dim, --ink-mut | text / dim text / muted text |   
| --line, --line-strong | borders |   
| --code-bg, --code-fg | terminal windows |   
shadcn bridge: the HSL variables under each theme recolor all existing shadcn components automatically.  
Rule for new code: use style={{ color: "var(--acc)" }}-style tokens — never hardcode Tailwind palette colors, or the cyber theme will break.  
9 · API reference  
| | | | |  
|-|-|-|-|  
| Method | Path | Body | Returns |   
| POST | /api/auth/signup | { email, password } | session cookie |   
| POST | /api/auth/login | { email, password } | session cookie |   
| GET | /api/auth/me | — | { user } |   
| GET | /api/courses | — | { courses } |   
| GET | /api/courses/{id} | — | { course } incl. modules[] |   
| GET | /api/modules/{id} | — | { module } (all 5 format fields) |   
| GET | /api/progress | — | completed module ids (any shape — normalizer handles) |   
| POST | /api/progress | { moduleId, completed } | { ok } |   
| POST | /api/subscribe | { plan } | activates tier (Stripe swap point) |   
| PATCH | /api/account | { track?, … } | updated profile |   
| POST | /api/instructor/chat | { moduleId?, messages } | { reply } |   
10 · Troubleshooting  
| | | |  
|-|-|-|  
| Symptom | Cause | Fix |   
| White flash on reload before theme | init script removed | keep theme-init Script (beforeInteractive) in layout.tsx |   
| Session lost between API routes (dev) | in-memory map per module scope | confirm globalThis hoist in lib/auth.ts (already applied) |   
| "voice not supported" | Firefox/Safari lack Web Speech | use Chrome/Edge, or type in the $ input |   
| Typewriter/stats don't animate | OS "reduce motion" enabled | by design (prefers-reduced-motion) |   
| Progress not saving | 401 on /api/progress | log in again; check cookie SameSite in DevTools → Application |   
| PDF tab blank | pdfUrl missing / file not in public/courseware/ | add file + set pdfUrl, re-seed |   
| Locked course won't open | expected | free tier — checkout with test card or upgrade |   
| Theme flips while typing "t" | old theme provider | the new provider ignores keystrokes in inputs/textareas |   
11 · Deployment — cheapest live path ($0/mo to start)  
Push the repo to GitHub.  
Neon (neon.tech) → create project → copy the Postgres connection string.  
prisma/schema.prisma: change provider = "sqlite" → "postgresql" → npx prisma migrate deploy.  
Vercel → import repo → env vars: DATABASE_URL, any auth secret your code uses.  
Deploy → seed once against Neon (DATABASE_URL=<neon> npx tsx scripts/seed.ts).  
Domain: add it in Vercel → Project → Domains; update metadata in layout.tsx; point your registrar's nameservers/A-record per Vercel's instructions.  
Swap mock checkout → Stripe keys when ready to charge.  
12 · Maintenance schedule  
| | |  
|-|-|  
| Cadence | Tasks |   
| Weekly | add/refresh a module in seed.ts; skim console errors in dev log |   
| Monthly | npm audit; back up the DB file (dev) or Neon snapshot (prod); test signup→checkout path |   
| Quarterly | review pricing vs. market; refresh PHRASES/hero copy; prune old PDFs |   
Appendix A · Keyboard & commands  
| | |  
|-|-|  
| Input | Action |   
| T | cycle dark → light → cyber |   
| /explain /quiz /hint /clear /help | tutor console commands (module + voice panels) |   
| Enter | send tutor message |   
| Tab keys | module content: video / notes.md / lab.ipynb / pdf / code/ |   
Appendix B · One-line memory hooks  
Content → scripts/seed.ts. Colors → globals.css tokens. Copy → constants atop landing.tsx.  
Anything marked ⚠️ ADAPTER = the only lines touching v1 store/API names.  
If a color looks wrong in cyber theme → someone hardcoded a Tailwind color; replace with var(--acc).  
— end of manual · $ echo "good luck, engineer" | sudo tee /dev/stdout  
text  
   
---  

Appendix C · Phase 2 — Media on Cloudflare R2
See docs/PHASE2-R2-ADDENDUM.md (app on Vercel, videos/PDFs on cdn.latentrag.com, $0 egress).
   
