Requirements docs for the WHAT. Design docs for the HOW. Code for the implementation. Tests for the proof.
The Four-Layer Documentation Stack
Every non-trivial feature needs four layers of documentation. Each layer serves a distinct purpose and audience.
┌─────────────────────────────────────────────────────────┐
│ PRD (Product Requirements Document) │
│ ───────────────────────────────────────────────────── │
│ WHAT we're building and WHY │
│ Audience: Product, Engineering, Stakeholders │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Design Doc │
│ ───────────────────────────────────────────────────── │
│ HOW we're building it │
│ Audience: Engineers │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Code │
│ ───────────────────────────────────────────────────── │
│ The implementation │
│ Audience: Engineers, Agents │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Tests │
│ ───────────────────────────────────────────────────── │
│ Proof that it works │
│ Audience: Engineers, CI, Agents │
└─────────────────────────────────────────────────────────┘
Why This Structure Matters
1. Separation of Concerns
Each document answers ONE question:
| Document | Question Answered |
|---|---|
| PRD | What problem are we solving? |
| Design Doc | How will we solve it technically? |
| Code | What does the solution look like? |
| Tests | Does it actually work? |
When these get conflated, documents become bloated and unfocused. A PRD that includes implementation details is doing two jobs poorly.
2. Decision Traceability
Six months from now, when someone asks “why is this built this way?”, the trail is clear:
- PRD explains the business requirement
- Design doc explains the technical approach
- Code shows the implementation
- Tests prove the behavior
3. Agent Compatibility
LLM agents work best with clear, focused context. A well-structured documentation stack allows agents to:
- Read the PRD to understand the goal
- Read the design doc to understand constraints
- Generate code that fits the design
- Write tests that validate requirements
Layer 1: PRD (Requirements)
Purpose: Define WHAT we’re building and WHY.
Template:
# PRD: [Feature Name]
## Problem Statement
[What problem does this solve? Who has this problem?]
## Goals
- [Measurable goal 1]
- [Measurable goal 2]
## Non-Goals
- [What we're explicitly NOT doing]
## User Stories
- As a [role], I want [capability] so that [benefit]
## Requirements
### Functional Requirements
| ID | Requirement | Priority |
|----|-------------|----------|
| FR-1 | System shall... | P0 |
| FR-2 | System shall... | P1 |
### Non-Functional Requirements
| ID | Requirement | Target |
|----|-------------|--------|
| NFR-1 | Response time | < 200ms |
| NFR-2 | Availability | 99.9% |
## Success Metrics
- [How will we know this succeeded?]
## Dependencies
- [What does this depend on?]
## Timeline
- Target: [Date]
Key Principles:
- No implementation details
- Measurable requirements
- Clear scope boundaries (goals AND non-goals)
- Stakeholder-readable language
Layer 2: Design Doc
Purpose: Define HOW we’ll build it technically.
Template:
# Design Doc: [Feature Name]
## Overview
[1-2 paragraph summary linking to PRD]
**PRD Reference**: <a href="/posts/prd-001-feature-name/">PRD 001 feature name</a>
## Architecture
### System Context
[How does this fit into the existing system?]
### Component Design
[Diagrams and descriptions of new/modified components]
### Data Model
[Schema changes, new entities]
### API Design
[Endpoints, contracts, protocols]
## Technical Decisions
### Decision 1: [Title]
**Options Considered**:
1. Option A: [pros/cons]
2. Option B: [pros/cons]
**Decision**: Option A because [reasoning]
## Implementation Plan
### Phase 1: [Name]
| Task | Dependencies | Notes |
|------|--------------|-------|
| Task 1 | - | |
| Task 2 | Task 1 | |
### Phase 2: [Name]
...
## Testing Strategy
- Unit tests: [approach]
- Integration tests: [approach]
- E2E tests: [approach]
## Risks & Mitigations
| Risk | Likelihood | Impact | Mitigation |
|------|------------|--------|------------|
| Risk 1 | Medium | High | [strategy] |
## Open Questions
- [ ] [Unresolved question 1]
- [ ] [Unresolved question 2]
Key Principles:
- References the PRD, never duplicates it
- Focuses on technical decisions
- Includes alternatives considered (for future archaeology)
- Phased implementation with dependencies
Layer 3: Code
The code itself is documentation when structured properly.
Principles for Self-Documenting Code:
- Directory structure reflects architecture
src/
services/ # Business logic layer
TaskService.ts
repositories/ # Data access layer
TaskRepository.ts
schemas/ # Data models
task.ts
cli/ # Interface layer
commands/
- File names match concepts from design doc
- Types as documentation – TypeScript interfaces document contracts
- Minimal comments – Code explains HOW, comments explain WHY
Layer 4: Tests
Tests serve as executable documentation of behavior.
Test Structure Mirrors Requirements:
describe('TaskService', () => {
// Maps to FR-1: System shall create tasks
describe('create', () => {
it('creates a task with valid input', async () => {...});
it('rejects tasks with empty titles', async () => {...});
});
// Maps to FR-2: System shall track dependencies
describe('block', () => {
it('creates a blocking relationship', async () => {...});
it('prevents circular dependencies', async () => {...});
});
});
Test Types and Their Role:
| Test Type | Documents | Runs |
|---|---|---|
| Unit tests | Component behavior | Fast, local |
| Integration tests | Component interactions | CI |
| E2E tests | User journeys | CI, staging |
| Property tests | Invariants | CI |
File Organization
A clean separation of concerns in the filesystem:
project/
├── docs/
│ ├── index.md # Navigation hub
│ ├── prds/
│ │ ├── index.md # PRD listing
│ │ ├── PRD-001-feature.md
│ │ └── PRD-002-feature.md
│ └── design/
│ ├── index.md # Design doc listing
│ ├── DESIGN-001-feature.md
│ └── DESIGN-002-feature.md
├── src/
│ └── ... # Code
└── tests/
└── ... # Tests
Index Files
Each folder needs an index.md that provides navigation:
docs/prds/index.md:
# Product Requirements Documents
| ID | Title | Status | Design Doc |
|----|-------|--------|------------|
| PRD-001 | <a href="/posts/prd-001-task-management/">PRD 001 task management</a> | Approved | <a href="/posts/design-001-task-management/">DESIGN 001 task management</a> |
| PRD-002 | <a href="/posts/prd-002-mcp-integration/">PRD 002 mcp integration</a> | Draft | - |
docs/design/index.md:
# Design Documents
| ID | Title | PRD | Status |
|----|-------|-----|--------|
| DESIGN-001 | <a href="/posts/design-001-task-management/">DESIGN 001 task management</a> | <a href="/posts/prd-001-task-management/">PRD 001 task management</a> | Implemented |
Document Lifecycle
PRD Draft → PRD Review → PRD Approved
↓
Design Draft → Design Review → Design Approved
↓
Implementation → Tests → Merge
Status Values:
Draft– In progress, not ready for reviewReview– Ready for feedbackApproved– Signed off, ready for next phaseImplemented– Code completeDeprecated– No longer relevant
Anti-Patterns
1. The Mega-Doc
One document that contains requirements, design, implementation notes, and meeting minutes. Impossible to navigate, impossible to maintain.
Fix: Split into PRD + Design Doc + ADRs.
2. The Orphan Code
Code with no PRD or design doc. No one knows why it exists or what problem it solves.
Fix: Every feature needs at least a brief PRD. If it’s too small for a design doc, document the approach in the PR.
3. The Stale Design Doc
Design doc written once, never updated as implementation diverged.
Fix: Update design doc during implementation OR mark sections as “implemented differently, see code”. Dead docs are worse than no docs.
4. Tests Without Context
Tests that verify behavior but don’t explain why that behavior matters.
Fix: Organize tests to mirror requirements. Use descriptive test names that reference user stories.
Agent Integration
This structure is particularly effective for LLM agents:
- Context Loading: Agent reads PRD to understand goals, design doc to understand constraints
- Scoped Implementation: Agent implements one phase at a time per design doc
- Verification: Agent runs tests to verify implementation matches requirements
- Traceability: Agent can reference specific PRD requirements in commit messages
Example Agent Workflow
1. Load PRD: "Understand what we're building"
2. Load Design Doc: "Understand how to build it"
3. Implement Phase 1 tasks in order
4. Run tests after each task
5. Mark tasks complete
6. Proceed to Phase 2
Related
- ADRs for Agent Context – Architecture decisions as guardrails
- Constraint-Based Prompting – WHAT vs HOW in prompts
- Incremental Development Pattern – Small validated steps
- Highest Leverage: Plans & Validation – Where human review matters most

