Building a Complete Project with Claude Code

Every topic in this course was preparation for this one. Building a complete project with Claude Code brings together context management, advanced prompting, code review, testing, Git workflows, security practices, and team collaboration into a single end-to-end process. This topic walks through the entire lifecycle of a real software project — from blank screen to deployed application — with Claude Code as your development partner at every stage.

The Project We Will Build

To make this concrete, the examples in this topic follow the construction of a Task Management API — a backend service where users can create accounts, log in, and manage their to-do lists. It is simple enough to understand quickly and complex enough to demonstrate every concept.

Task Management API
───────────────────────────────────────────
Features:
  ● User registration and login (JWT auth)
  ● Create, read, update, delete tasks
  ● Filter tasks by status (todo/done)
  ● Assign due dates to tasks

Stack:
  ● Node.js + Express
  ● PostgreSQL + Prisma ORM
  ● JWT for authentication
  ● Vitest for testing

Phase 1 — Project Setup and Planning

Before writing a single line of code, use Claude to think through the project structure. This planning session prevents costly mistakes that require large refactors later.

Step 1 — Define the Architecture

Prompt:
"I'm building a Task Management REST API with Node.js,
Express, PostgreSQL, and Prisma. It has user auth and CRUD
for tasks. Design the folder structure and explain what
goes in each folder. I want separation of concerns:
routes, services, and data access in separate layers."

Claude returns a folder structure with explanations. You review it, ask questions about decisions you disagree with, and confirm the layout before creating any files.

Folder Structure Output

/task-api
  /src
    /routes        ← HTTP route handlers (thin layer)
    /services      ← Business logic
    /repositories  ← Database queries (Prisma calls)
    /middleware    ← Auth, error handling, validation
    /types         ← TypeScript interfaces and types
    /utils         ← Shared helper functions
  /prisma
    schema.prisma  ← Database schema
    /migrations    ← Migration files
  /tests           ← Test files
  CLAUDE.md        ← Project standards for Claude
  .env.example     ← Environment variable template

Step 2 — Create the CLAUDE.md File

Prompt:
"Create a CLAUDE.md file for this project.
Include: tech stack, coding conventions (TypeScript strict,
no any, async/await only), security rules (parameterized
queries, env vars for secrets, auth on all private routes),
and testing requirements (every route needs a test)."

This file now travels with the project. Every Claude Code session reads it automatically.

Phase 2 — Database Schema Design

Step 3 — Design the Schema

Prompt:
"Write a Prisma schema for the Task Management API.
Tables needed:
- User: id, email, passwordHash, createdAt
- Task: id, title, description (optional), status
  (todo/in_progress/done), dueDate (optional),
  userId (foreign key), createdAt, updatedAt

Add proper indexes for query performance.
Use UUIDs for all IDs."

Database Relationship Diagram

User
─────────────────────
id (UUID, PK)
email (unique)
passwordHash
createdAt
      │
      │ 1-to-many
      ▼
Task
─────────────────────
id (UUID, PK)
title
description (nullable)
status (enum)
dueDate (nullable)
userId (FK → User.id)
createdAt
updatedAt

Step 4 — Run the Migration

After Claude generates the schema, you create the migration and apply it:

npx prisma migrate dev --name init-schema
npx prisma generate

If any error occurs, paste the error output into Claude and ask what went wrong.

Phase 3 — Building the Authentication Layer

Step 5 — User Registration Route

Prompt:
"Write the user registration endpoint: POST /auth/register.
Requirements:
- Validate email format and password minimum 8 chars
- Hash the password with bcrypt (salt rounds: 10)
- Check for duplicate email — return 409 if exists
- Return a JWT token on success (expires in 7 days)
- Never return the passwordHash in the response
Follow our CLAUDE.md conventions."

Step 6 — Immediately Review for Security

Prompt (right after):
"Now audit what you just wrote for security vulnerabilities.
Check: password storage, JWT secret handling, input validation,
error messages that could leak information, and any SQL
injection risk."

Fix any issues Claude identifies before moving forward. Security problems are cheapest to fix at the moment the code is written.

Step 7 — Write Tests for Auth Routes

Prompt:
"Write Vitest tests for the /auth/register endpoint.
Test cases needed:
- Successful registration returns 201 and a JWT
- Duplicate email returns 409
- Invalid email format returns 400
- Password under 8 characters returns 400
- Missing fields return 400
Mock the database calls with vi.mock."

Phase 4 — Building the Task CRUD Layer

With authentication in place, you build the task management features. Use the iterative prompting technique — build one endpoint at a time, test it, then move to the next.

Step 8 — Build Endpoints in Sequence

Sequence:
────────────────────────────────────────────────
1. POST /tasks       — Create a task
2. GET /tasks        — List user's tasks (with filter)
3. GET /tasks/:id    — Get one task
4. PUT /tasks/:id    — Update a task
5. DELETE /tasks/:id — Delete a task
────────────────────────────────────────────────

Prompt for each step:
"Write the [METHOD] /tasks[/:id] endpoint.
[Specific requirements for this endpoint].
Ensure the user can only access their own tasks.
Follow CLAUDE.md conventions."

Task Ownership Check Pattern

Every task endpoint must verify ownership:

WRONG — fetches task, skips ownership check:
const task = await db.task.findUnique({ where: { id } });

RIGHT — fetches task, verifies it belongs to logged-in user:
const task = await db.task.findFirst({
  where: {
    id: taskId,
    userId: req.user.id   ← Must match the logged-in user
  }
});
if (!task) return res.status(404).json({ error: 'Task not found' });

Ask Claude to check every task route for this pattern before you consider the CRUD layer complete.

Phase 5 — Error Handling and Middleware

Step 9 — Global Error Handler

Prompt:
"Write a global Express error handling middleware for this API.
It should:
- Catch all unhandled errors from route handlers
- Return consistent JSON error responses (status, message, code)
- In development, include stack traces
- In production, hide internal error details
- Handle Prisma-specific errors (unique constraint, not found)
- Log all 5xx errors to the console"

Consistent Error Response Structure

Every error from the API looks the same:
────────────────────────────────────────
{
  "status": "error",
  "code": "DUPLICATE_EMAIL",
  "message": "An account with this email already exists"
}

Clients know exactly what to expect.
Frontend developers never need to guess the error format.

Phase 6 — Full Test Suite

Step 10 — Integration Tests

Unit tests check individual functions. Integration tests check entire request flows — from HTTP request through the middleware, through the service layer, and into the database (or a test database).

Prompt:
"Write integration tests for the complete task creation flow.
Use a test database configured via environment variables.
Test the full cycle:
1. Register a user
2. Log in, capture the JWT
3. Create a task with the JWT
4. Fetch the task list and verify the task appears
5. Update the task status to 'done'
6. Delete the task and verify it no longer appears"

Test Coverage Target

Coverage Map Before Testing:
─────────────────────────────────────────
Route               Coverage
POST /auth/register  ████████████  100%
POST /auth/login     ████████████  100%
POST /tasks          ████░░░░░░░░   30%
GET  /tasks          ░░░░░░░░░░░░    0%
PUT  /tasks/:id      ░░░░░░░░░░░░    0%
DELETE /tasks/:id    ░░░░░░░░░░░░    0%
─────────────────────────────────────────
Ask Claude to write tests for every uncovered route.

Phase 7 — Code Review Pass

Step 11 — Final Review Before Deployment

Prompt:
"Do a full code review of this project. Check:
1. All routes validate their inputs
2. Auth middleware is on every private route
3. Users can only access their own tasks
4. No secrets are hardcoded
5. All database queries are parameterized
6. Error messages do not expose internal details
7. All exported functions have tests

List issues by severity: High / Medium / Low."

Fix every HIGH severity issue. Address MEDIUM issues where time permits. Schedule LOW issues for the next sprint.

Phase 8 — Preparing for Deployment

Step 12 — Environment Configuration

Prompt:
"Create a .env.example file listing every environment
variable this API needs. For each one, add a comment
explaining what it is and where to get the value."

Step 13 — Deployment Checklist

Prompt:
"Create a deployment checklist for this Node.js API.
Include: environment variables to set, database migration
command, build command, health check endpoint to verify,
and common deployment errors for this stack."

Reflecting on the Development Process

Building this project with Claude Code follows a clear pattern you can apply to any project of any size:

PLAN → SCHEMA → AUTH → FEATURES → ERROR HANDLING
  → TESTS → REVIEW → DEPLOY
      ↑                      ↑
      └── Claude at every step ──┘

At each step:
  1. Give Claude precise context (stack, conventions, task)
  2. Review what Claude produces before using it
  3. Ask Claude to audit security-sensitive code
  4. Test before moving to the next step
  5. Commit working code to Git with Claude's commit messages

What Claude Code Cannot Do for You

Even after building an entire project with Claude's help, some responsibilities always stay yours:

  • Understanding your users and what they actually need
  • Making architectural trade-off decisions that affect the business
  • Reviewing Claude's output — you are the final check before code goes live
  • Deciding when something works well enough versus when to keep improving
  • Taking responsibility for security incidents caused by unreviewed code

Claude Code accelerates the implementation. The judgment, the ownership, and the final decisions belong to you.

Key Points

  • Start every project with a planning session — architecture decisions made early prevent expensive refactors later
  • Create CLAUDE.md before writing the first line of code — it aligns Claude with your project standards from session one
  • Build features in a fixed sequence: database first, auth second, business logic third, tests fourth, review fifth
  • After Claude writes security-sensitive code, immediately ask it to audit that same code for vulnerabilities
  • Verify task and user ownership checks on every data access route — Claude sometimes omits these in initial drafts
  • The full cycle is: Plan → Schema → Auth → Features → Error Handling → Tests → Review → Deploy — Claude assists at every stage, you decide at every stage

Leave a Comment