02. Specs & API Contract First — Vibe Coding Series
Write the API contract before coding so frontend and backend can build in parallel — using AI to generate OpenAPI specs, mock servers, and contract tests.
In TaskFlow’s first sprint, I let frontend and backend run in parallel. Two weeks later, when it was time to integrate, I found out: the backend returned assignee_id (snake_case), the frontend expected assigneeId (camelCase). The backend used POST /tasks, the frontend was calling POST /api/tasks. Response format was different too — backend wrapped everything in { data: ... }, frontend expected a flat object.
Not a bug. Not a logic error. Just two people (and two AI agents) making different assumptions about the same contract.
Two days fixing integration. Two days that were entirely avoidable.
Context
In article 01, I covered Phase 1: analyzing requirements with AI, creating user stories, and locking in architecture. This article moves into Phase 2: before writing a single line of code, we need a shared contract — an API spec that frontend, backend, and AI agents all agree on.
Why Contract First?
The reason is simple: without a contract, everyone assumes.
Parallel development that’s actually parallel. With a locked OpenAPI spec, frontend can mock the server and build UI while backend implements. No waiting. No “backend needs to finish before frontend can start.”
Early validation. The spec is the cheapest place to catch problems. Adding an endpoint to a YAML file takes 5 minutes. Refactoring already-implemented code takes 5 hours.
AI has clearer context. When you feed an OpenAPI spec to an AI agent, it knows exactly: which endpoints exist, what the request/response shapes are, what the authentication scheme is. No more AI inventing endpoints or assuming response formats.
Writing the Spec with AI
From requirements → OpenAPI spec
After having user stories from article 01, I used this prompt to generate the initial spec:
Prompt:
"Here are my user stories: [list]. Create an OpenAPI 3.0 spec
for the required endpoints. Include: request/response schemas,
error codes, authentication scheme (Bearer token), and example
request/response for each endpoint."
AI will produce a draft spec. Here’s an example for the create task endpoint in TaskFlow:
openapi: "3.0.3"
info:
title: TaskFlow API
version: "1.0.0"
paths:
/tasks:
post:
summary: Create a new task
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title, teamId]
properties:
title:
type: string
minLength: 1
maxLength: 255
description:
type: string
teamId:
type: string
format: uuid
assigneeId:
type: string
format: uuid
dueDate:
type: string
format: date-time
responses:
"201":
description: Task created
content:
application/json:
schema:
$ref: "#/components/schemas/Task"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
components:
schemas:
Task:
type: object
properties:
id:
type: string
format: uuid
title:
type: string
description:
type: string
teamId:
type: string
format: uuid
assigneeId:
type: string
format: uuid
createdBy:
type: string
format: uuid
status:
type: string
enum: [todo, in_progress, done]
dueDate:
type: string
format: date-time
createdAt:
type: string
format: date-time
securitySchemes:
bearerAuth:
type: http
scheme: bearer
AI reviewing the spec: finding gaps
Once I had a draft, I used AI to review the spec itself:
Prompt:
"Review this OpenAPI spec and find:
1. Missing endpoints (any user story without a corresponding endpoint?)
2. Inconsistent naming (camelCase vs snake_case, plural vs singular)
3. Missing error cases (scenarios without an error response?)
4. Security issues (endpoints that need auth but don't have it?)"
With TaskFlow, AI caught: I had POST /tasks but was missing GET /tasks (list tasks for a team), and the assign task endpoint was absent — even though the user story existed from article 01.
A simple versioning strategy
For MVP, I use URL versioning: /api/v1/tasks. Simple, easy to debug, easy to deprecate later. No need for header versioning or content negotiation at this stage.
Mock Server and Contract Testing
Using AI to generate mock data
With the spec in place, I asked AI to generate mock data:
Prompt:
"Based on this OpenAPI spec, create mock data for 5 tasks with
different statuses (todo, in_progress, done), 3 users, and 2 teams.
JSON format, realistic data."
Then I used Prism to spin up a mock server from the spec:
npx @stoplight/prism-cli mock openapi.yaml
# Mock server running at http://localhost:4010
Frontend can call http://localhost:4010/api/v1/tasks immediately — no need to wait for backend to finish.
Contract testing with Dredd
Dredd runs real requests against your API and validates that responses match the spec:
npx dredd openapi.yaml http://localhost:3000
Once backend is implemented, run Dredd to verify the contract. If the response shape changes but the spec isn’t updated — Dredd fails. Automatic safety net.
For small teams, Dredd is enough. If you need consumer-driven contract testing (multiple services, multiple consumers), Pact is more powerful — but significantly more complex to set up.
AI_CONTEXT.md: Context File for AI Agents
This is something I added to my workflow after the first “integration hell” experience. AI_CONTEXT.md is a summary context file for AI agents — placed at the project root, fed into every working session.
# TaskFlow — AI Context
## Project Overview
Task management SaaS for indie teams. Multi-tenant, role-based access.
Stack: Next.js 15, Supabase (PostgreSQL + Auth), Resend, Vercel.
## API Contract
- Base URL: /api/v1
- Auth: Bearer token (Supabase JWT)
- Response format: { data: T } for success, { error: string, code: string } for errors
- Naming: camelCase for all JSON fields
- See: /docs/openapi.yaml for full spec
## Data Models (simplified)
- User: { id, email, name, avatarUrl }
- Team: { id, name, ownerId }
- Task: { id, title, description, teamId, assigneeId, createdBy, status, dueDate }
- Status enum: todo | in_progress | done
## Key Constraints
- Users can only access tasks in their teams (enforced by RLS)
- Only task creator or team lead can assign/reassign
- Soft delete for tasks (deletedAt field, not physical delete)
- All timestamps in UTC, ISO 8601 format
## Current Phase
Phase 2 — API spec locked, mock server running.
Backend: implementing endpoints.
Frontend: building UI against mock server.
Short, specific, always up-to-date. Every time I start a new session with an AI agent, I paste this file into context. The AI doesn’t need to guess — it knows exactly where the project stands.
Real-World Example: TaskFlow API Spec
The three main endpoints for TaskFlow MVP:
1. Create task — POST /api/v1/tasks
- Auth required, user must be a team member
teamIdrequired,assigneeIdoptional- Response: task object with generated
id
2. Assign task — PATCH /api/v1/tasks/{taskId}/assign
- Only task creator or team lead can assign
- Body:
{ assigneeId: string } - Assignee must be a member of the same team
- Response: updated task object
3. List tasks — GET /api/v1/tasks?teamId={teamId}
- Filter by team (required), status (optional), assigneeId (optional)
- Pagination:
?page=1&limit=20 - Response:
{ data: Task[], total: number, page: number }
After writing the spec for these three endpoints, I ran Prism to get a mock server. Frontend started building the task list UI and create task form that same day — while backend was still setting up the database schema.
Pitfalls
Over-speccing slows down iteration. At the MVP stage, don’t spec every field validation, every error message. The spec should be enough for both sides to agree on shape and contract — implementation details can live in the code. Over-speccing early is a form of premature optimization.
Not updating the spec when code changes. This is the most common pitfall. Backend adds a new field, renames a field, changes response format — but the spec stays at the old version. After a few weeks, spec and code diverge completely. The fix: treat the spec like code — every API change requires updating the spec first, then implementing.
Summary
- Contract First lets frontend and backend truly build in parallel — no waiting on each other
- Use AI to generate an OpenAPI spec from user stories, then use AI to review that same spec
- Mock server (Prism) lets frontend develop immediately while backend isn’t done yet
- Contract testing (Dredd) is an automatic safety net when backend implements
AI_CONTEXT.mdis a short, focused context file — feed it to AI agents every session so they don’t assume
What’s Next
Phase 2.5 tackles UI consistency: when you let AI decide styles freely, every component comes out looking different. The next article covers building a design system before writing UI code — and how to feed that design system into AI context to ensure consistency.