sightful.
Guide

From PRD to Production: My Spec-Driven Claude Code Workflow

A behind-the-scenes look at how I use spec-driven development with Claude Code to go from requirements to working software.

Matthias Walter

From PRD to Production: My Spec-Driven Claude Code Workflow

Every project I build with Claude Code follows the same workflow. It's not fancy. It's not revolutionary. But it works consistently, and consistency is what matters when you're delivering software for clients.

Here's the exact process I use, from initial requirements to deployed code.

Phase 1: Discovery

Before I write a single line of spec, I need to understand what we're building and why.

The Discovery Call

Every project starts with a conversation. I ask:

  • What problem are you solving?
  • Who will use this software?
  • What does success look like?
  • What are your constraints (timeline, budget, existing systems)?
  • What have you tried before?

I take detailed notes. Not because I'll hand them to Claude Code verbatim, but because I need to translate business language into technical requirements.

The Output

By the end of discovery, I have:

  1. A clear problem statement
  2. User personas (who uses this and how)
  3. Success criteria (measurable outcomes)
  4. Technical constraints (must integrate with X, must run on Y)
  5. Out-of-scope items (equally important as in-scope)

Phase 2: Spec Writing

This is where the real work happens. The spec is the contract between me and the AI.

My Spec Template

Every feature spec follows this structure:

# Feature: [Name]

## Overview
[2-3 sentences describing what this feature does and why it matters]

## User Stories
- As a [user type], I want to [action] so that [benefit]
- As a [user type], I want to [action] so that [benefit]

## Requirements

### Functional Requirements
- [ ] FR-001: [Specific, testable requirement]
- [ ] FR-002: [Specific, testable requirement]
...

### Non-Functional Requirements
- [ ] NFR-001: Response time < 200ms for all API calls
- [ ] NFR-002: Support 100 concurrent users
...

## Data Model
[Schema definitions, relationships, constraints]

## API Endpoints
### [METHOD] [Path]
**Description**: [What this endpoint does]
**Request**: [Body schema]
**Response**: [Success and error schemas]
**Authorization**: [Who can call this]

## Business Rules
- BR-001: [Rule description]
- BR-002: [Rule description]

## Edge Cases
- EC-001: [What happens when X]
- EC-002: [What happens when Y]

## Out of Scope
- [Things explicitly NOT included]

## Test Plan
- Unit tests for: [list]
- Integration tests for: [list]
- E2E tests for: [list]

Writing Good Requirements

Every requirement must be:

Specific: Not "handle errors" but "return HTTP 400 with error message when email format is invalid"

Testable: I should be able to write a test that passes when this requirement is met

Independent: Where possible, requirements shouldn't depend on each other

Atomic: One requirement = one thing. If it has "and" in it, it's probably two requirements.

Example: Authentication Spec

Here's a real example from a recent project:

# Feature: User Authentication

## Overview
Users can register, login, and manage their sessions. Authentication uses JWT tokens with refresh token rotation.

## User Stories
- As a new user, I want to register with email/password so that I can access the system
- As a registered user, I want to login so that I can access my data
- As a logged-in user, I want to logout so that my session is terminated

## Requirements

### Registration
- [ ] FR-001: Accept POST /api/auth/register with {email, password, name}
- [ ] FR-002: Validate email format (RFC 5322)
- [ ] FR-003: Require password minimum 8 characters, 1 uppercase, 1 number
- [ ] FR-004: Hash password with bcrypt (cost factor 12)
- [ ] FR-005: Check email uniqueness before creating user
- [ ] FR-006: Return 201 with {userId, email} on success
- [ ] FR-007: Return 400 with validation errors on invalid input
- [ ] FR-008: Return 409 if email already exists

### Login
- [ ] FR-009: Accept POST /api/auth/login with {email, password}
- [ ] FR-010: Verify password against stored hash
- [ ] FR-011: Generate JWT access token (15min expiry)
- [ ] FR-012: Generate refresh token (7 day expiry)
- [ ] FR-013: Store refresh token hash in database
- [ ] FR-014: Return 200 with {accessToken, refreshToken, expiresAt}
- [ ] FR-015: Return 401 for invalid credentials (same message for wrong email/password)
- [ ] FR-016: Rate limit: 5 attempts per email per 15 minutes

### Token Refresh
- [ ] FR-017: Accept POST /api/auth/refresh with {refreshToken}
- [ ] FR-018: Validate refresh token against stored hash
- [ ] FR-019: Implement refresh token rotation (invalidate old, issue new)
- [ ] FR-020: Return 200 with new {accessToken, refreshToken, expiresAt}
- [ ] FR-021: Return 401 if refresh token invalid or expired

### Logout
- [ ] FR-022: Accept POST /api/auth/logout with Authorization header
- [ ] FR-023: Invalidate refresh token in database
- [ ] FR-024: Return 204 on success

## API Endpoints

### POST /api/auth/register
**Request**:
```json
{
  "email": "user@example.com",
  "password": "SecurePass123",
  "name": "John Doe"
}

Response 201:

{
  "userId": "uuid",
  "email": "user@example.com"
}

Response 400:

{
  "error": "Validation failed",
  "details": [
    {"field": "password", "message": "Must contain at least 1 uppercase letter"}
  ]
}

[... additional endpoints ...]

Edge Cases

  • EC-001: What if user tries to register with email that has different casing? → Normalize to lowercase
  • EC-002: What if refresh token is used twice (replay attack)? → Invalidate all user sessions
  • EC-003: What if user changes password while sessions active? → Invalidate all existing sessions

This spec is 3 pages long for a simple auth system. That's intentional. Every question Claude Code might have is answered in the spec.

## Phase 3: Spec Validation

Before I give the spec to Claude Code, I validate it:

### Completeness Check

- Does every requirement have acceptance criteria?
- Are all edge cases covered?
- Are error conditions specified?
- Is the test plan sufficient?

### Consistency Check

- Do requirements conflict with each other?
- Are data types consistent across endpoints?
- Do business rules align with requirements?

### Technical Review

- Is this actually implementable?
- Are there missing dependencies?
- Are performance requirements realistic?

### Client Review

For client projects, I share the spec before implementation. "This is what I understand you need. Is this correct?"

Better to catch misunderstandings now than after code is written.

## Phase 4: Implementation with Claude Code

Now the fun part. With a validated spec, implementation is almost mechanical.

### Initial Setup

I create the project structure and configure Claude Code:

```bash
# Create project
mkdir project-name && cd project-name
git init

# Set up Claude Code with the spec
mkdir docs
cp ~/specs/feature-spec.md docs/spec.md

# Create CLAUDE.md with project context
cat > CLAUDE.md << 'EOF'
# Project: [Name]

## Tech Stack
- Node.js 20
- TypeScript 5.x
- PostgreSQL 16
- Express.js

## Development Commands
- npm run dev: Start development server
- npm run test: Run test suite
- npm run lint: Check code style

## Conventions
- Use async/await, not callbacks
- All functions must have JSDoc comments
- Error responses use RFC 7807 format
EOF

The Implementation Loop

I use a modified Ralph Loop for implementation:

claude --print "
Read docs/spec.md for the feature specification.

Find the first unchecked requirement (- [ ]).

1. Understand what this requirement needs
2. Check if any dependencies need to be implemented first
3. Read existing code in the relevant files
4. Implement the requirement
5. Write tests for the requirement
6. Run tests with 'npm test'
7. If tests pass:
   - Mark the requirement done (- [x])
   - Commit with message referencing the requirement ID
8. If tests fail:
   - Fix the issue
   - Re-run tests
   - Only mark done when tests pass

Be thorough. One requirement at a time.
"

Monitoring Progress

I check in periodically:

  • Are requirements being completed in a sensible order?
  • Is the code quality acceptable?
  • Are tests actually testing what they claim?
  • Is the AI stuck on anything?

Human Intervention Points

Some things always need human attention:

  • Database migrations (I review before running)
  • External API integrations (need real credentials/config)
  • Security-sensitive code (authentication, authorization)
  • Performance optimization (need real-world data patterns)

Phase 5: Review and Refinement

Once all requirements are marked complete, the work isn't done.

Code Review

I review all generated code for:

  • Security issues (injection, authentication bypass, etc.)
  • Performance problems (N+1 queries, missing indexes)
  • Maintainability (naming, structure, documentation)
  • Test coverage (are edge cases actually tested?)

Integration Testing

Individual requirements passing doesn't mean the system works. I run:

  • Full user flow tests
  • Load testing (if performance requirements exist)
  • Security scanning

Client Demo

For client projects, I demo the feature before marking it complete. "Here's what we built. Does it match your expectations?"

Phase 6: Documentation and Handoff

The final phase is often overlooked but critical.

Update Documentation

  • API documentation (auto-generated from code where possible)
  • User guides (if applicable)
  • Deployment instructions
  • Known limitations

Create Runbook

For operations teams:

  • How to deploy
  • How to monitor
  • How to troubleshoot common issues
  • How to rollback

Knowledge Transfer

If someone else will maintain this code:

  • Architecture overview
  • Key design decisions and why
  • Where the bodies are buried (known issues, technical debt)

The Complete Timeline

For a medium-complexity feature (like the auth example):

PhaseTime
Discovery2-4 hours
Spec writing4-8 hours
Spec validation1-2 hours
Implementation4-8 hours (mostly autonomous)
Review and refinement2-4 hours
Documentation2-4 hours
Total15-30 hours

Traditional approach for the same feature? 40-80 hours.

The time savings come from:

  1. Spec writing catches issues before coding (no rework)
  2. AI handles implementation (fast, consistent)
  3. Clear requirements mean fewer iterations

Common Mistakes to Avoid

Skipping Discovery

"Just build a login system" → three iterations of rework because requirements weren't clear.

Vague Specs

"Handle errors appropriately" → AI makes reasonable-sounding decisions that don't match what you wanted.

Skipping Review

Generated code that "works" but has security holes, performance issues, or unmaintainable structure.

Underestimating Documentation

"I'll remember how this works" → you won't, and neither will the next person.

Why This Works

This workflow works because it plays to AI strengths while compensating for AI weaknesses.

AI Strengths:

  • Fast implementation of well-defined requirements
  • Consistent code quality
  • Thorough test coverage
  • Doesn't get bored with repetitive tasks

AI Weaknesses:

  • Understanding vague requirements
  • Making business judgment calls
  • Anticipating edge cases you didn't mention
  • Knowing what "good" looks like without examples

The spec bridges the gap. It translates human intent into AI-executable instructions.


Want to see this workflow in action on your project? Book a free consultation and let's discuss how spec-driven development can work for you.

Weekly Insights on Building with Claude Code

Get practical tips on AI-assisted development, Claude Code patterns, and building software faster.

No spam. Unsubscribe anytime.

Ready to implement this?

Let's discuss how we can help your team adopt AI-assisted development.