In this guide

  1. Why most AI coding specs fail
  2. What AI tools actually need in a spec
  3. The full spec template (copy-ready)
  4. Section-by-section breakdown
  5. Real example: a complete filled spec
  6. Common mistakes that waste sessions

Why Most AI Coding Specs Fail

Here is what most developers actually send to Cursor or Claude Code:

Typical prompt (the bad version)
Build me a task management app. Users can create tasks, 
mark them complete, and organize them into projects.
Use React and Node.js.

This isn't a spec — it's a wishlist. And the AI will fill every gap with its own assumptions. When the output doesn't match what you imagined, it feels like the AI failed. But the AI just solved a different problem than the one in your head.

The fundamental issue: AI coding tools are translators, not mind-readers. They translate written specification into code. The quality of the translation is bounded by the quality of the input.

What "vague" actually costs you

The key insight: A spec is not documentation written after the fact. It is a briefing written before the session — a transfer of your mental model into a format the AI can execute against without guessing.

What AI Tools Actually Need in a Spec

AI coding assistants process your spec from top to bottom. They are looking for five things:

  1. What problem are we solving — the context that makes all subsequent decisions make sense
  2. What the output should do — behavior, not appearance
  3. What is explicitly out of scope — what to not build (as important as what to build)
  4. What technical decisions are already made — so it doesn't re-decide them
  5. What "done" looks like — acceptance criteria the AI can check its own work against

Notice what's not on the list: "make it look nice," "be intuitive," "good UX." These are signals without meaning to an AI. Include them if you must, but they will not drive behavior the way concrete criteria do.

The Full Spec Template (Copy-Ready)

Copy this entire block. Fill in the bracketed sections. Paste it at the start of a new Cursor session, Claude Code conversation, or into your CLAUDE.md file.

ai-spec-template.md — copy this
# PROJECT SPEC

## Problem Statement
# Who has this problem:
[Specific user type — be narrow. "Solo developers" not "developers"]

# What is the exact pain:
[The specific moment of frustration. What are they doing right now 
that's broken or missing?]

# Why current solutions fail:
[What do they use today? What's wrong with it?]

## Solution
# One sentence: what does this product do and for whom?
[Product name] is a [type of thing] that lets [target user] [core action] 
without [the thing they hate doing].

## MVP Scope
# Core features (maximum 5 for MVP):
1. [Feature 1 — describe behavior, not UI. "Users can X" not "a page with Y"]
2. [Feature 2]
3. [Feature 3]
4. [Feature 4 — if needed]
5. [Feature 5 — if needed]

# Explicitly NOT building in MVP:
- [Thing you might think should be here but isn't]
- [Another thing that seems obvious but is scope creep]
- [Authentication/payments/etc if not needed for MVP]

## Technical Architecture
# Stack (decisions already made — do not change these):
- Language: [Python / JavaScript / TypeScript / etc]
- Framework: [Flask / FastAPI / Next.js / Express / etc]
- Database: [SQLite / PostgreSQL / MongoDB / etc]
- Hosting: [Fly.io / Vercel / Railway / etc]
- Auth: [None / Clerk / Auth0 / custom JWT / etc]

# Data models:
[Model 1 name]: [field: type, field: type, ...]
[Model 2 name]: [field: type, field: type, ...]

# Key API routes (for web apps):
GET  /[route]  — [what it returns]
POST /[route]  — [what it accepts and does]
[etc]

# External services/APIs (if any):
- [Service name]: [what it's used for]

## File Structure
# Expected project structure:
/[root]
  [file/folder]: [purpose]
  [file/folder]: [purpose]

## Conventions
# Naming and patterns (AI should follow these without being asked):
- [Convention 1: e.g., "snake_case for Python files, camelCase for JS"]
- [Convention 2: e.g., "All API responses include {success: bool, data: ...}"]
- [Convention 3: e.g., "No external CSS frameworks — vanilla CSS only"]

## Success Criteria
# What does "done" look like? (Make these testable):
- [ ] [Criterion 1: something the AI can verify — "POST /generate returns JSON with keys X, Y, Z"]
- [ ] [Criterion 2: a user can do X in fewer than Y steps]
- [ ] [Criterion 3: the app runs locally with a single command]

## What NOT To Do
# Common AI mistakes to prevent on this project:
- Do NOT add [thing that AI commonly adds but you don't want]
- Do NOT use [library/pattern to avoid]
- Do NOT add authentication unless explicitly asked
- Do NOT change the tech stack decisions above

Section-by-Section Breakdown

Problem Statement — why it needs three parts

Most specs skip the problem and jump to the solution. This is the single biggest mistake. The problem statement exists to give the AI the context it needs to make judgment calls when your spec doesn't cover a specific situation.

When Claude Code hits an ambiguous decision — "should this field be nullable?" — it looks back at the problem statement to infer the right answer. Without it, it guesses based on its training data defaults, which may not match your context.

❌ Too vague

"A tool for developers to manage their projects."

✅ Specific enough

"Solo developers using Cursor who start sessions with a rough idea and end up with code that doesn't match what they needed — because they never forced themselves to be specific before coding."

MVP Scope — the NOT list is as important as the list

AI coding tools have absorbed millions of apps. When you say "task manager," they have a default schema for what a task manager includes: user accounts, teams, comments, tags, due dates, priority levels. Most of those aren't in your MVP.

The NOT list prevents scope creep before it starts. It tells the AI: "I know this exists. We are deliberately not building it."

❌ Missing NOT list

"Features: task creation, completion, project grouping."

✅ With NOT list

"Features: task creation, completion, project grouping.

NOT building: user accounts, team collaboration, due dates, email notifications, mobile app, tags/labels."

Technical Architecture — lock in your decisions

The stack section is a lock, not a suggestion. If you write "Flask" and the AI decides to use FastAPI because it's more modern, you now have a refactoring problem. Mark your tech decisions as decisions, not preferences.

The data models section is one of the highest-value parts of a spec. Getting your models right before coding starts prevents entire refactoring cycles. Spend extra time here.

Data model tip: Write your models in pseudo-code, not actual code. The AI will translate them into your chosen language. Focus on the relationships and field types, not the syntax.

Conventions — the invisible rules

Every codebase has implicit rules: what you call things, how you structure responses, what you consider a dependency worth adding. Without the conventions section, the AI invents its own conventions, which may be perfectly valid but inconsistent with the 50 files you already have.

Three to five conventions is enough. More than that becomes noise. Focus on the ones where inconsistency would genuinely bother you.

Success Criteria — give the AI a way to check its own work

Write your success criteria as testable checkboxes. "The user experience is good" is not testable. "A user can generate a spec in under 90 seconds from the landing page" is testable.

These criteria also serve as your session goal-setting. When you paste this spec and the AI says "I've implemented that," you can check against this list instead of just eyeballing the output.

What NOT To Do — prevent the patterns you hate

Every developer has learned which AI behaviors frustrate them. Use this section to codify those. Common ones:

Real Example: A Complete Filled Spec

Here's the template filled in for a real project — a simple URL shortener:

Example: URL shortener spec
# PROJECT SPEC — QuickLink URL Shortener

## Problem Statement
Who has this problem: Solo developers and indie makers who need to share 
links in demos, blog posts, and social media.

What is the exact pain: Long URLs in blog posts look ugly and break in 
email clients. Existing shorteners (bit.ly) require accounts, track clicks 
for surveillance purposes, and are overkill for personal use.

Why current solutions fail: bit.ly requires signup and their free tier limits 
customization. Building your own feels complex. No self-hosted option is 
simple enough to deploy in under an hour.

## Solution
QuickLink is a self-hosted URL shortener that lets indie developers create 
short links without accounts, paywalls, or surveillance tracking.

## MVP Scope
Core features:
1. Paste a long URL, get a short URL back (no account required)
2. Short links redirect to the original URL
3. Admin page (password-protected) to see all links
4. Click count tracking per link
5. Custom slug support (optional, 3-30 chars)

NOT building in MVP:
- User accounts or authentication for link creators
- Link expiration or deletion
- QR codes
- UTM parameter injection
- Team features
- API

## Technical Architecture
Stack:
- Language: Python
- Framework: Flask
- Database: SQLite (single file at ./links.db)
- Hosting: Fly.io (free tier)
- Auth: None for creating links; ADMIN_SECRET env var for admin page

Data models:
Link: id (int), slug (text unique), target_url (text), 
      created_at (text), click_count (int default 0)

API routes:
GET  /              — returns index.html (the form)
POST /shorten       — accepts {url, slug?}, returns {short_url}
GET  /{slug}        — redirects to target_url, increments click_count
GET  /admin         — returns admin page (requires ?secret=ADMIN_SECRET)

## File Structure
/quicklink
  app.py              — Flask routes and SQLite logic
  templates/
    index.html        — the shortener form
    admin.html        — admin link list
  fly.toml            — Fly.io config
  requirements.txt    — flask, gunicorn

## Conventions
- No external Python packages beyond Flask and gunicorn
- Vanilla CSS in <style> tags — no external CSS frameworks
- All responses from /shorten return JSON: {success: bool, short_url?: str, error?: str}
- Admin secret read from environment variable ADMIN_SECRET

## Success Criteria
- [ ] Paste a URL into the form, get a short link back in < 2 seconds
- [ ] Short link redirects correctly 100% of the time
- [ ] Click counts increment on each redirect
- [ ] Admin page shows all links when correct secret is passed
- [ ] App runs locally with: pip install -r requirements.txt && flask run

## What NOT To Do
- Do NOT add user authentication for creating links
- Do NOT use SQLAlchemy — raw sqlite3 only
- Do NOT add Bootstrap or Tailwind — vanilla CSS
- Do NOT add email sending
- Do NOT create separate services/blueprints — keep everything in app.py

Common Mistakes That Waste Sessions

Mistake 1: Describing the UI instead of the behavior

AI tools build behavior from specs. When you describe the UI, they have to infer the behavior — and they often infer a more complex version than you meant.

❌ UI description

"A sidebar with a list of projects on the left, a main panel showing tasks on the right, and a top bar with filter buttons."

✅ Behavior description

"Users can switch between projects. The selected project shows its tasks. Users can filter tasks by status (all/active/done)."

Mistake 2: Leaving the stack implicit

If you don't specify your stack, the AI will use what it would use. That might be TypeScript instead of JavaScript, PostgreSQL instead of SQLite, or a component library you've never used. Always be explicit.

Mistake 3: Saying "simple" or "lightweight"

These words mean different things to different developers. To an AI, "simple" might mean "no TypeScript" or it might mean "fewer than 10 routes." Replace these adjectives with constraints:

❌ Adjective

"Keep the architecture simple and lightweight."

✅ Constraint

"Everything in a single app.py. No services layer. No separate modules for MVP."

Mistake 4: Not reading the output before the next prompt

The most common session drift pattern: you give a spec, the AI produces code, you ask for the next feature without checking what it built. The AI assumes its previous output was correct and builds on top of it. Small mismatches compound.

After every significant generation, verify the output against your success criteria before asking for the next thing.

Mistake 5: Updating the spec mid-session without acknowledging it

Requirements change — that's fine. But when you change a requirement mid-session, explicitly tell the AI: "Changed requirement: X. Previous implementation of X should be replaced with Y." Don't just ask for the new thing and hope it infers the replacement.

Generate Your Spec in 30 Seconds

Paste your rough idea. SpecForge outputs a complete spec package — PRD, GitHub tickets, and a CLAUDE.md file — structured exactly for AI coding tools.

Generate My Spec →