FORM NOT VOID, MIND NO CORE

Chapter 3: Architecture Design—The Art of the Blueprint

2026.08.10

You ask AI to build a "user management module." It's obedient and finishes in an hour—using Express + MongoDB. You realize something's wrong: your project uses Next.js + PostgreSQL. You ask it to rewrite, and it switches to Prisma + Postgres. But this time, it changes the field-naming style in the user table from camelCase to snake_case—and all the code you'd already written now has to change along with it.

You ask AI to build a "user management module." It's obedient and finishes in an hour—using Express + MongoDB. You realize something's wrong: your project uses Next.js + PostgreSQL. You ask it to rewrite, and it switches to Prisma + Postgres. But this time, it changes the field-naming style in the user table from camelCase to snake_case—and all the code you'd already written now has to change along with it.

Where's the problem? It isn't that AI is disobedient—it's that you never gave it a "map." You gave it a destination ("user management module") but didn't tell it which roads to take and which roads are off-limits. AI can only pick a route by instinct, and instinct is the least reliable thing in engineering.

3.1 Why a Blueprint Is the Essential Foundation for AI Coding

In traditional development, the importance of architecture design is self-evident—it determines the system's maintainability, extensibility, and performance. But in AI coding, the blueprint has an even more decisive role: it is the AI coding tool's only working context.

AI has no long-term memory. Every conversation, it faces a blank page. If you don't give it context, it can only "guess"—guess the tech stack, guess the naming style, guess the data structures. And "guessing" is the most expensive thing in engineering, because different conversations produce different guesses.

Without a blueprint, here's how AI "behaves by default": it picks the highest-probability solution from its training data. What appears most often in the training data? CRUD examples using React + Node.js + MongoDB. So if you don't spell things out, AI defaults to that trio. But your project might use Vue + Go + PostgreSQL, or you might be a Java team, a .NET team—AI's "default guess" is almost never what you want.

The subtler problem is naming style. In the first conversation, AI uses camelCase because "your sample code uses camelCase." But in the second conversation (you've reset the context), AI doesn't see that earlier sample code, so it uses snake_case—because snake_case is also common in the training data. The code generated across the two conversations has inconsistent field-naming styles, and the data models collide.

The essence of a blueprint isn't documentation; it's a constraint engine. It compresses AI's space of possibility from "infinite" down to "within your project's scope." When the blueprint says "use Prisma ORM, camelCase naming, unified AppException error handling," AI will honor these conventions no matter how many conversations it starts, because every time it sees the blueprint, these "rules" are fixed.

A blueprint isn't optional overhead; it's the essential foundation of AI coding.

3.2 The Structure of a Blueprint

A complete blueprint (CONTEXT.md) should include the following sections.

1. Project Overview

# Project Name

One-sentence description: what system is this, and what problem does it solve?

## Core Value Proposition

What is the fundamental reason this system exists? Why would users choose it over alternatives?

2. Core Glossary—the Most Important Part of the Blueprint

The glossary is the most easily overlooked yet most important part of the blueprint. Before discussing technical solutions, pin down the definitions of your core domain terms. Vague terminology means the architecture is vague from the very start.

Why does the glossary matter so much? Because the destructiveness of vague terminology far exceeds what you imagine. A single "order" can be understood three different ways by three different people: what Sales calls an "order" is "a customer's purchase request" (including unpaid ones); what Finance calls an "order" is "a paid transaction record" (excluding unpaid ones); what the Warehouse calls an "order" is "a work order that needs shipping" (covering paid and partially shipped ones). These three understandings lead to completely different data models, state machines, and API designs.

Consider a composite legacy-project case. While a user system is developed, the terms "customer" and "user" are mixed. AI creates a customer table in feature A and a user table in feature B; they store similar data but use different fields and relationships. As dependencies accumulate, merging them affects many joins and creates substantial migration cost. The text does not invent "more than 20 queries" or "three months" as a real record; the case only shows how terminological divergence accumulates along code paths.

The maintenance discipline for the glossary is simple: define a new term the moment you encounter it; don't wait for the "design phase." During requirements analysis, when you hear a business person use a new word, immediately ask, "what does this word mean?" and write the definition into the glossary. Don't wait until you're designing the database tables to go back and ask—by then you might have already forgotten.

3. Tech Stack

## Tech Stack

| Layer | Technology | Version | Notes |
|:---|:---|:---|:---|
| Frontend Framework | Next.js | 14+ | App Router |
| Styling | Tailwind CSS | 3.x | — |
| Database | PostgreSQL | 15+ | Connected via Prisma |
| ORM | Prisma | 5.x | — |
| Deployment | Vercel | — | Auto-deploy |

4. Data Model

## Data Model

### User
- id: String (UUID) — primary key
- email: String — unique, used for login
- name: String — display name
- role: Enum(ADMIN, USER) — role
- createdAt: DateTime
- updatedAt: DateTime

### Order
- id: String (UUID) — primary key
- userId: String — foreign key, references User
- status: Enum(...) — order status
- totalAmount: Decimal — total amount
- createdAt: DateTime

5. API Contracts

## API Endpoints

### GET /api/orders
Fetch the order list.

Parameters:
- page: number (default 1)
- size: number (default 20)
- status: OrderStatus (optional, filter by status)

Response:
{
  data: Order[]
  total: number
  page: number
  size: number
}

6. Directory Structure

## Directory Structure

src/
├── app/          # Next.js App Router pages
│   ├── api/      # API routes
│   ├── orders/   # Order-related pages
│   └── ...
├── components/   # Shared components
│   ├── ui/       # Base UI components
│   └── features/ # Business components
├── lib/          # Utility functions and configuration
└── types/        # TypeScript type definitions

7. Milestone Dependency Tree

## Milestones

Phase 1: Foundation
  1.1 Project initialization → 1.2 Database setup → 1.3 User authentication

Phase 2: Core Features
  2.1 Order list (depends on 1.3)
  2.2 Create order (depends on 1.3)
  2.3 Order details (depends on 2.1)

Phase 3: Enhancement
  3.1 Order search (depends on 2.1)
  3.2 Order export (depends on 2.2)

3.3 Principles of Architecture Design

Principle One: Propose, Rather Than Ask

This looks like a simple principle, yet it's extremely hard to carry out. Because it runs against our instinct as "developers"—we're used to asking questions, gathering information, and only then making a judgment.

But in architecture design, "asking" is the most dangerous form of communication. There are two reasons.

First, the user's information asymmetry. If you ask the user to choose between "MySQL or PostgreSQL," the user may only know that MySQL is free, without realizing how much the JSONB support in PostgreSQL matters to their business. When you ask a user to make a decision they're not equipped to make, the answer you get tends to be random and unreliable.

Second, the trap of AI's "default answer." If you ask AI "what database should I use," it will give the most "common" answer—because common means high probability in the training data. But that "common" answer isn't necessarily right for your project. Take a small internal tool with a tiny data volume that needs zero maintenance: AI might recommend PostgreSQL (because it's "mainstream"), when SQLite would be the more fitting choice.

The right approach is to "propose." As the architect, you research, analyze, and weigh trade-offs based on the user's needs, then put forward a clear recommendation with its rationale and alternatives. The user only needs to do one thing: confirm or adjust.

Here's a counterintuitive insight: proposing isn't "deciding for the user"; it's "enabling the user to decide." When you say, "I recommend SQLite. Reasons: zero deployment, it handles your data volume (<100K rows), and no DBA is needed. If you expect to exceed one million rows, PostgreSQL is the better choice, but it requires additional deployment," the user can make a judgment on the spot ("my data won't exceed 100K rows") rather than randomly picking something while anxious about "what database should I use."

Principle Two: Skeleton First

Before asking for any details, produce a complete skeleton blueprint—with most fields filled in using placeholders. Let the user see the full shape of the final product, instead of interrogating them item by item against a blank page.

Why is "skeleton + placeholders" worth more than "a blank page"? Because people (and AI alike) fear emptiness and have an instinct for filling things in. Hand someone a blank page and ask them to draw a house, and they'll agonize over "how big should the house be," "what style," "what colors." But hand them a sketch whose outline is already drawn and ask them to color it in, and they can get to work immediately.

The same holds in architecture design: give the user a complete skeleton blueprint (mostly with placeholders), and they immediately understand "which pieces of information I need to supply," rather than floundering in the blanks.

A skeleton with placeholders is worth more than a blank page. Once the user sees the skeleton, what they still need to supply is clear at a glance.

Principle Three: Terminology First

Before discussing the tech stack, data model, or APIs, pin down the core domain terms first.

One common mistake: the user says "I want an order management system," and you jump straight into designing database tables. But the word "order" carries entirely different meanings across business contexts—an e-commerce order (with products, logistics, refunds), a restaurant order (with tables, dishes, kitchen printing), an enterprise procurement order (with approvals, reconciliation, payments). These three differ enormously. Designing database tables before aligning on terminology is almost guaranteed to go wrong.

The right approach is to align with the user first: what exactly is your "order"? What states does it have? Are "canceling an order" and "processing a return" the same concept?

Domain terminology is the architecture's first blueprint. Data models, API naming, and code structure all derive from the glossary.

Principle Four: Bidirectional Reasoning

A good architect can think in both directions at once:

  • Top-down: derive the system structure from requirements (user requirements → feature list → data model → API → milestones)
  • Bottom-up: derive the actual architecture from existing code (scan files → identify patterns → abstract the structure → distill the blueprint)

For new projects, go top-down—start from requirements and reason your way to the architecture. For existing projects, begin bottom-up—scan the code first, identify the "actual architecture" (not the "ideal architecture"), distill a blueprint from it, and then adjust it top-down.

Consider taking over a legacy project with 30,000 lines of code and no documentation. If you design purely top-down, the "ideal architecture" you produce may differ so wildly from the actual code that it can't be implemented. The right approach is to start bottom-up—scan the file structure, identify the module boundaries, understand the data flows—distill a blueprint of the "current architecture," and then design improvements on top of it, top-down.

3.4 Architecture Decision Records (ADRs) and Common Mistakes

ADRs are for recording those architecture decisions that are "difficult to reverse." But it's important to know when you need an ADR and when you don't.

You need an ADR only when all three of these conditions hold:

  1. Hard to reverse—the cost of changing your mind later is significant
  2. Surprising without context—future readers would wonder "why did they do this?"
  3. The result of a genuine trade-off—real alternatives existed

If any one of these is missing, skip the ADR. For instance, "choosing React as the frontend framework"—if your team has already used React for five years, this isn't a "genuine trade-off" and needs no ADR. But "choosing Prisma over Drizzle"—both are excellent ORMs, and choosing one requires weighing real trade-offs, so that is an ADR scenario.

Common Architecture Design Mistakes

Mistake one: over-engineering. Designing for "needs that might arise in the future" introduces unnecessary complexity. A microservices architecture for an internal tool with only ten users—"what if the user base grows later?" But that "later" may never come. The right approach: design for current needs, document the potential extension points, but don't add complexity just to implement those points.

Mistake two: vague terminology. Team members hold different understandings of the same term, producing inconsistent data models, API naming, and code structure. One person says "order" means a customer's purchase request; another says "order" means a paid transaction record—these two understandings lead to completely different data models and state machines. The right approach: create the glossary and confirm it in the very first step of architecture design.

Mistake three: ignoring data flow. Architecture design focuses only on "what modules there are" and not on "how data flows between modules." The result: the modules are sensibly divided, but the data flow is a mess. Modules A and B have clear boundaries, yet the data flow demands A→B; because A exposes no data interface, B reads A's database directly—and the architecture design falls apart. The right approach: draw a data-flow diagram in the architecture design, clarifying where data comes from, what processing it undergoes, where it is stored, and who consumes it.


Chapter Summary

Architecture design is the process of turning requirements into an executable blueprint. A blueprint isn't a document; it's a constraint engine that compresses AI's space of possibility from "infinite" down to "within your project's scope." The glossary is the most important part of the blueprint, because naming is architecture—data models and APIs alike derive from terminology. The four principles—propose rather than ask, skeleton first, terminology first, and bidirectional reasoning—are the core methodology of architecture design. ADRs record decisions that are hard to reverse, and the three common mistakes (over-engineering, vague terminology, and ignoring data flow) are the traps an architecture design must guard against most. In the next chapter, we'll explore the full mechanics of automated workflows.