8 min read

What this chapter does to you: Almost every tutorial starts at the code. That's backwards. The code is the easy part — anyone can learn a syntax. What separates a senior engineer from someone who can write CRUD is what happens before the first commit: turning a vague idea into a scoped, de-risked, buildable plan. This chapter gives you that process once. The next seven chapters apply it, fully, to seven real apps.


Why plan at all

Planning isn't bureaucracy. It's how you find the expensive mistakes while they're still free to fix. A wrong assumption caught in a PRD costs you a sentence. The same assumption caught after you've built the wrong schema costs you a migration, a rewrite, or a very bad week.

The point of every artifact below is the same: make a decision explicit, on paper, before it's expensive to change. Skipping straight to code doesn't mean you avoid these decisions — it means you make them implicitly, under time pressure, one line at a time, and you don't find out they were wrong until production tells you.

The stack we'll use for all 7 apps

We're deliberately using one consistent stack across every app in this playbook. That's a real-world choice, not a cop-out: switching stacks per project is expensive (new mental models, new bugs, new deploy pipelines) and teaches you very little about architecture that a stack swap didn't already explain. Holding the stack constant means every difference between chapter 1 and chapter 7 is a genuine architectural decision, not stack noise.

Core stack:

  • Next.js (App Router) + TypeScript — one codebase for frontend and backend. Route Handlers / Server Actions are the "backend."
  • PostgreSQL + Prisma — relational by default. Every app in this playbook has real relationships between entities; start relational, not schemaless.
  • Auth.js (NextAuth) — one auth story, reused everywhere.
  • Tailwind CSS — styling, matches this reader app itself.
  • Vercel + Neon/Supabase (Postgres) — deploy target.

Add-ons are introduced only when an app's requirements force them, never up front. Each addition gets a short ADR explaining exactly what problem it solves. This mirrors how real systems grow:

AppNew infra forced by requirements
3 — URL ShortenerRedis (cache + rate limiting)
4 — E-commerceIdempotency keys, payment webhook handling
5 — ChatA persistent WebSocket process (steps outside pure serverless)
7 — SaaS DashboardQueue (BullMQ + Redis), structured logging/tracing

If you find yourself reaching for a new piece of infrastructure in app 1, that's a sign you're solving a problem you don't have yet. Don't.

The 11-step skeleton

Every app chapter in this playbook fills in these eleven sections, in this order. Memorize the order — it's the order the real decisions have to be made in, because each step constrains the next one.

code
 1. Problem framing        →  what pain, for whom, why now
 2. PRD                    →  goals, non-goals, user stories, MVP cut
 3. Wireframes & UX flow   →  screens + how a user moves between them
 4. HLD                    →  components, data flow, stack rationale
 5. Data model / ERD       →  entities, relationships, constraints
 6. API design + flows     →  endpoint contract + per-flow sequence diagrams
 7. LLD                    →  modules, algorithms, edge cases
 8. NFRs                   →  performance, security/authz, observability
 9. ADRs                   →  the 2-4 decisions worth defending
10. Deploy plan            →  environments, CI/CD, definition of done
11. Retro / "at 10x"       →  what breaks first, what you'd change

1 — Problem framing

One paragraph. Who is the user, what's the pain, why does this need to exist. If you can't write this in five sentences, you don't understand the problem yet — writing code won't fix that, it'll just hide it.

2 — PRD (Product Requirements Doc)

The PRD's job is to draw a line around scope before anything else happens. Every PRD in this playbook has the same shape:

  • Goal — the single sentence this project exists to satisfy
  • Non-goals — explicitly out of scope for the MVP (this is the most skipped, most valuable section — it's what stops scope creep)
  • User stories — "As a <role>, I want <action>, so that <outcome>"
  • Success metrics — how you'd know this worked, in numbers
  • MVP cut line — what ships in v1 vs. what's explicitly deferred

3 — Wireframes & UX flow

Before any API contract exists, you need to know what screens exist and how a user moves between them. Low-fidelity is the point — boxes and arrows, not pixels. We'll express this two ways:

  • A screen inventory (list of screens + what's on each, as a table)
  • A navigation flow diagram (Mermaid flowchart) showing how a user gets from landing to their goal

If a screen in your wireframe has no arrow leading to it, either it's unreachable (bug) or you forgot a flow (also a bug). This is a cheap way to catch missing navigation before you've built any of it.

4 — HLD (High-Level Design)

Zoom out to boxes: browser, server, database, external services, and the arrows of data flow between them. The HLD answers one question — what talks to what, and why — and states the stack choice with a one-line rationale, not just a diagram.

5 — Data model / ERD

Every entity, every relationship, every cardinality, expressed as a Mermaid erDiagram. Get this wrong and everything downstream — API shapes, queries, even UI states — inherits the mistake.

Read the crow's-foot notation as: || = exactly one, o{ = zero or many, }o = many. Getting cardinality right here is what stops you from having to add a junction table three weeks into the build.

6 — API design + flow mapping

Two things, not one:

  • An endpoint contract table — method, path, request shape, response shape, auth requirement, per endpoint.
  • A sequence diagram per non-trivial user flow, showing exactly which component calls which, in order — this is where race conditions and missing error paths get caught, on paper, before they're bugs.

7 — LLD (Low-Level Design)

Now go inside the boxes from the HLD. Module/file breakdown, the actual algorithm for anything non-obvious, and — critically — the edge cases: empty states, concurrent writes, partial failures. If a reviewer would ask "what happens if X," LLD is where X gets an answer before it's asked.

8 — NFRs (Non-Functional Requirements)

The requirements that don't show up in a user story but absolutely show up in an incident:

  • Performance — target latency/throughput, and at what load
  • Security & authz — who can do what, enforced where
  • Observability — what you'd need logged/measured to debug this at 3am

9 — ADRs (Architecture Decision Records)

Short, not exhaustive. For each genuinely debatable call:

code
ADR-N: <decision>
Context:   <the situation forcing a choice>
Decision:  <what we chose>
Alternatives considered: <what we didn't pick>
Consequence: <what this costs us later>

If a decision is obvious, it doesn't need an ADR. ADRs are for the calls a reasonable engineer could have made differently.

10 — Deploy plan

Environments (dev/preview/prod), what CI runs on every push, what "done" means for this app, and a one-line rollback plan. An app that isn't deployed isn't finished — it's a demo.

11 — Retro / "at 10x"

The honest part: what's the first thing that breaks if this got 10x the users overnight, and what would you actually change. This is where you practice thinking about scale after shipping something real, which is the order it happens in actual jobs — you rarely get to design for scale you don't have yet.


The 7 apps

Each one is chosen to force exactly one or two new hard problems on top of everything before it — not to be harder for its own sake.

#AppForces you to learn
1Todo appClient–server–DB split, basic REST CRUD, what "MVP" really means
2Library managementRelational modeling with real constraints, roles, business rules
3URL shortener + analyticsRead vs. write-heavy split, ID generation, caching, event logging
4E-commerce checkoutTransactions under concurrency, payment integration, async side effects
5Realtime chatStateful connections, pub/sub, presence, scaling beyond serverless
6Social feedFan-out on write vs. read, pagination at scale, denormalization
7Multi-tenant SaaS dashboardTenant isolation, queues, observability, CI/CD, cost-aware scaling

By the end of app 7 you'll have used the same eleven-step process to plan seven apps of increasing real-world shape — and you'll have a template you can point at your next idea, the one that isn't in this book.