Build full-stack systems with AI agents, the way the spec decides
A dissection of JavaScript Mastery's four-hour build, every technical claim checked against the vendors' current docs, and a working system you can run on one laptop for $0: sign-up with email verification, projects, sharing, a live multiplayer canvas, and an AI architect that runs in the background.
Recorded from the real system (63 s, no audio): Ada signs up, verifies by email, creates a project, draws two shapes and shares it with Grace. Grace joins live, asks the AI architect for a payments platform, and Ada watches the design appear, then generates a spec.
What the video actually builds
The thumbnail shows a sign-up flow (modal, email, create account, verify email, AI agent). That diagram is sample content drawn inside the app. The app itself is "Ghost AI": a collaborative system-design workspace where you describe a system in plain English, an AI agent draws it on a shared canvas, and the app writes a technical spec from the result.
The real lesson is the process
About 10 minutes on how to think before prompting, then 29 small, spec'd units. The creator never types code by hand. The point is that the agent stays consistent because it always reads the same six files and one narrow spec.
The stack in the video
Next.js 16, React 19, TypeScript, Tailwind, shadcn/ui · Clerk (auth) · Prisma + Postgres · Liveblocks + React Flow (realtime) · Trigger.dev (background AI) · Vercel Blob · Gemini via the Vercel AI SDK · CodeRabbit (review) · Vercel (deploy). Four of these are the video's sponsors.
The method, step by step
Tool-agnostic: it works with Claude Code, Codex or Cursor, and any stack. This is the part worth copying.
1 · Plan before the first prompt
Talk the system through with a planning model: what it does, who uses it, the core flows, the hard parts, what could go wrong. Push back until the design is clear. Then prompt with decisions, not wishes:
✗ wish
Build me a SaaS app with auth
and a real-time canvas.
✓ decision
Add the realtime room provider to the
workspace route. Auth is already handled
by the session helper. Issue room tokens
only after verifying project membership.
Don't touch the sidebar or navbar.
2 · Write six context files the agent reads every session
Summary, measurable goals, the full user flow, in scope and out of scope, success criteria as checks.
Stack and each tool's role, where code lives, storage model, cross-service security rules, invariants.
Language rules, status codes, styling tokens, error handling, test rules. Feature 16 looks like feature 5.
One unit at a time, don't mix subsystems, don't exceed the spec, what to do when a decision is needed.
The feel, tokens, type, components. Turn tokens into CSS variables first or the agent hard-codes hex.
Current phase, done (and how it was verified), decisions with reasons, lessons. The only file that changes every session.
AGENTS.md at the repo root tells any agent to read these first. Claude Code reads AGENTS.md natively when there's no CLAUDE.md; if both exist, import one from the other.
3 · One spec per unit
# NN — Unit name
## Goal one or two sentences
## Depends on earlier units
## Design decisions point at UI tokens
## Implementation files, exact APIs and
versions, what NOT to touch
## Out of scope
## Verification
- [ ] typecheck, lint, tests
- [ ] a behaviour someone can check
Sizing rules that held up
One subsystem per unit, small enough for one focused session. Backend and UI wiring are separate units. Put version-specific gotchas in the spec (for example: Next.js 16 renamed middleware.ts to proxy.ts, and agents trained on older code create the old file).
4 · The unit loop
- New chat per unit. Stay in a chat only to fix the unit you just built.
- Prompt: read the spec, mark it in progress in the tracker, implement exactly as specified, don't go beyond scope.
- Run the checklist, then read the diff yourself. You didn't write this code; review is how you stay in control of it.
- Independent review. When it shows the spec was wrong, fix the spec too, so code and spec agree.
- Update the tracker (done, decisions, lessons), commit, next unit.
5 · The debugging loop
- Write the bug in
context/current-issues.md: steps, exact error, URL, screenshots. Git-ignore it on day one. In the video it was committed with a live auth token inside. - Ask the agent to analyse and propose, then wait. Approve, then fix.
- One issue at a time: in a batch of seven, one slipped through unfixed.
- When a library misbehaves, point the agent at the vendor's agent skill or docs page. Three rounds of guessing failed in the video; the skill found the cause on the first read.
The demo system
Same architecture as the video, but every paid service sits behind one module with a local implementation. Swapping to the hosted service later is one file.
Video → local adapter → production swap
| Video | Here | Production |
|---|---|---|
| Clerk | Better Auth + Mailpit | Better Auth or Clerk |
| Liveblocks | Yjs room server | Liveblocks (ID tokens) |
| Trigger.dev | pg-boss worker | Trigger.dev or keep pg-boss |
| Vercel Blob | private disk store | Blob (private), R2, S3 |
| Gemini | Ollama, JSON schema | Claude, Gemini 3.x |
| CodeRabbit | /code-review + CI | any reviewer + a human |
Invariants (never broken)
- Request handlers never run AI work: validate, check access and caps, enqueue, return
202. - Every mutation checks session and ownership on the server. Identity comes from the session only.
- "Not found" and "not allowed" both return
404. - Room tokens: after a membership check, 10 minutes, one room, own secret. Closed at expiry or on removal.
- Model output and other clients' edits are untrusted: schema-validated, capped, laid out by our code.
- Metadata in Postgres, artifacts in private blobs, read back through an access-checked route.
- AI caps live in the database, counted under a lock, with a kill switch.
Walkthrough of the running system
Every screen below was captured from the real app by an automated browser run, not mocked. Use the list or the arrow keys.
Run it yourself
The repo is ~/Git/spec-driven-fullstack-template on this machine (branch feat/spec-driven-demo, not pushed). Needs Docker, Node 22+, and Ollama with a model.
- Pull a local model
ollama pull llama3.2
- Config: copy the example and put random values in the two secrets.
cp .env.example .env openssl rand -base64 32 # BETTER_AUTH_SECRET openssl rand -base64 32 # REALTIME_SECRET
- Services and database: Postgres 17 and Mailpit, bound to 127.0.0.1 only.
docker compose up -d --wait npm ci npm run db:migrate
- Three processes, one terminal each.
npm run dev # http://localhost:3200 npm run realtime # ws://localhost:3201 npm run worker # background AI jobs
- Prove it works
npm test # 17 unit tests npm run test:e2e # 41 checks, two users, over HTTP npm run test:ui # Playwright in your installed Chrome
- Use it: sign up at
localhost:3200, open the email in Mailpit at127.0.0.1:8035, follow the link, create a project, open a second browser profile as another user.
Before production
☐ Swap each adapter in lib/ for the hosted service, with production projects and keys (separate from dev).
☐ Real email sender (Resend) on a verified subdomain.
☐ Pin the model in config and keep a small eval set; check the provider's deprecation page.
☐ Database-backed auth rate limits and a trusted-proxy list before running more than one instance.
☐ Keep package-lock.json; deploy with npm ci; add prisma generate to postinstall (Prisma 7).
☐ Private blob store; nothing user-owned under public/.
☐ CI green before merge (workflow included).
☐ Privacy policy, terms, data deletion and accessibility checks for the target market.
Every claim, checked
Vendor docs and primary sources, all read on 9 Nov 2026. The video was uploaded six months earlier; several things changed or were never quite true.
| Verdict | Claim in the video | What the source says today |
|---|---|---|
| Outdated | An AI call over 60 s in an API route times out in production. | With Fluid compute, Vercel's default is 300 s on every plan, up to 800 s on Pro. Long AI work still belongs in a job. Vercel |
| Changed | Protect routes in Clerk middleware with a route matcher. | createRouteMatcher() is deprecated; Clerk now says to protect each page, route handler and server function with auth(). Clerk |
| Corrected | Clerk is free up to 50,000 monthly users. | 50,000 MRU (monthly retained users) per app. Clerk pricing |
| Changed | Use Prisma Accelerate for prisma+postgres:// URLs. | Accelerate retires on 1 Dec 2026. Also: npm's latest tag for prisma now points at an 8.0 release candidate; pin prisma@7. Prisma |
| Outdated | Use Gemini 2.0 Flash, then 2.5 Flash. | 2.0 Flash shut down 1 Jun 2026; 2.5 Flash shuts down 1 Dec 2026; Google recommends gemini-3.8-flash. Google |
| Outdated | generateText structured output is experimental; switch to tool calls. | AI SDK is on v7 and Output.object() is stable; the docs say to catch and inspect AI_NoObjectGeneratedError. AI SDK |
| Corrected | Liveblocks access tokens per room. | Public key = anyone reaches any room. For production Liveblocks recommends the secret key with ID tokens. Liveblocks |
| Unconfirmed | Liveblocks dev keys are rate-limited. | Not in the docs. Production projects get higher limits and encrypted keys. Liveblocks |
| Detail | Trigger.dev max duration is "compute seconds". | Right, and it's required, counts CPU time not wall time (waits don't count), minimum 5 s. Trigger.dev |
| Vendor data | "AI code creates 1.7x more problems." | CodeRabbit's own study (a sponsor): 470 PRs, AI authorship inferred, its own issue taxonomy. Report |
| Confirmed | Next.js 16 renamed middleware.ts to proxy.ts. | Yes; the exported function is also renamed to proxy(). Next.js |
| Confirmed | create-next-app writes an AGENTS.md telling agents to read the installed docs. | Yes, since 16.3; it also enables Cache Components by default, which changes how session reads must be written. Next.js |
| Confirmed | Vercel Blob private storage; uploads fail on an existing path unless overwrite is allowed. | Yes. Private stores are GA; access mode is fixed at creation. Vercel |
| Confirmed | Vendor agent skills via npx skills add …. | Yes for Clerk, Prisma (v7) and Liveblocks; Trigger.dev now installs skills through its own CLI. The skills CLI is a Vercel Labs project. Agent Skills spec |
| Confirmed | React StrictMode runs effects twice in development; the isMounted guard was the bug. | Yes; React says to write cleanup instead of guarding with refs. React |
| Matches practice | Senior engineers write design docs before building. | Design docs, RFCs and ADRs are standard practice; the "weeks or months" figure is the speaker's generalisation. Design Docs at Google · ADR |
What an independent review found
All tests were green. Then a separate read-only reviewer went through the code, which is the video's "review every unit" step, and found six real problems. Each is fixed and now has a regression check.
| Problem | Fix | Proven by |
|---|---|---|
| One 3 MB websocket frame crashed the whole room server | Error listener on every socket and on the upgrade | e2e: server survives a 3 MB frame |
| A removed collaborator kept editing through an open connection | Close at token expiry; app kicks the user on removal | e2e: socket closes immediately |
| A bad node written by one client crashed every viewer's canvas | Render only schema-valid shared data | shared validation path |
| Stuck runs could lock a user out of AI | Failed enqueue marks the run; stale runs time out; retries finish cleanly | run route + worker |
| 10 parallel requests slipped past the AI spend cap | Count and insert under a per-user advisory lock | e2e: 2 accepted, 8 refused |
| Anyone could appear as another user, or fake "AI is working" | Room server rewrites identity from the token | e2e: spoof attempt shows the real name |
Bugs only a browser showed
A "New project" dialog stayed open, invisible, on the previous page that Next 16 keeps mounted, and made the new page ignore every click. HTTP tests passed; typing into the page didn't. Fix: modals close in their effect cleanup.
Leaks the logs showed
The dev server printed full verification URLs, and the token in them is a JWT containing the email. Filtered with logging.incomingRequests.ignore. React Flow's attribution had been hidden, which needs a paid licence; restored.
Don't copy these from the video
Committed debug notes with a token
Git-ignore current-issues.md from the start. Rotate any secret that reached a remote.
git push --force
Pull or rebase. Never force-push a shared branch.
Deleting the lockfile to fix a deploy
Keep it, fix the version mismatch, deploy with npm ci.
Merging 1.7M lines unreviewed
Install agent skills in their own commit so app diffs stay reviewable.
No tests
"Build passes and it looked right" missed six security problems here. Unit, end-to-end and browser tests, gated in CI.
No AI limits
Caps in the database, counted under a lock, plus a kill switch, before any paid model call.
Sources
Video: How Senior Engineers Actually Build With AI in 2026 | Build a Full Stack Systems Architecture App, JavaScript Mastery, uploaded 1 May 2026, 3 h 58 m. Transcribed locally and summarised; no transcript or video frames are reproduced here. The workflow is the creator's practice; vendor claims were checked against the pages linked in the table above.
Method references: Claude Code best practices · Claude Code memory (AGENTS.md) · GitHub Spec Kit · DORA trunk-based development · OWASP LLM05 · NIST SP 800-63B rev 4 · Twelve-Factor config · Transactional outbox.