From Idea to App with Spec Driven Development
TLDR;
- Start with an
briefing.md— just dump your idea in there, don’t overthink it. - Ask the AI to turn it into a
roadmap.mdwith goals, themes, and a tech stack. - Iterate the roadmap until it represents what you actually want to build.
- Break the roadmap into epics — each epic is a self-contained chunk of the app.
- For each epic, write a spec. Iterate the spec until it’s airtight.
- Implement one epic at a time, in a fresh agent window, commit after each.
- When something goes wrong, fix the spec first, then the code.
The Problem with Vibe Coding
As I started with Cursor, I would just type a rough idea into the chat, and hope for the best. Sometimes it worked. Many times I ended up with something that I could not understand and the AI was confused about what I wanted. It was a lot of trial and error.
The root cause? I never told it precisely what I wanted.
This is where Spec Driven Development (SDD) comes in. The idea is simple: before you write a line of code, you write a specification. You iterate on that spec until it’s solid. Like really iterating a lot. Then you let the AI build from it.
It sounds obvious. It is like writing a spec for a contractor. You really define what you want before you start building.
Step 1: Write an briefing.md
Everything starts with an briefing.md. This is your raw idea. No structure. No formality. Just write down what you want to build, who it’s for, and what problem it solves.
Here’s the briefing I used for a Planning Poker app:
# Planning Poker
Planning poker for agile teams to estimate stories.
- Voting modes: Story Points, Fibonacci, T-Shirt Sizes, Time
- Voting mode is a room setting chosen on creation
- Users can create or join rooms; creator gets an invite link
- Others join via room ID (simple number) or invite link
- Auth via passkeys (WebAuthn — registered in the browser)
- Moderator starts/ends voting; everyone sees results at the end
- Moderator sets multiple tickets per room, voted one by one
- Tickets added manually or imported from Jira
- Jira integration: list tickets, search/filter, import selected ones
- Moderator sees live voting status (who voted / pending) with colors
- All room updates real-time via WebSockets — no page reload
- End of vote: show who voted for what, average, consensus indicator
- If everyone votes the same → fireworks animation
- Voters can press a Coffee icon (no opinion) — excluded from averages
but shown in summary
That’s it. Messy. Missing tech decisions. But it captures everything that matters.
Step 2: Turn It Into a roadmap.md
Now hand your briefing.md to the AI and ask it to create a roadmap:
> Read briefing.md and write a roadmap.md for this app.
> Include: goals, key themes, a high-level feature list, out of scope items,
> and a proposed tech stack. Structure into epics which are self-contained and can be worked on step by step.
The roadmap is intentionally high-level. It’s not about requirements yet — it’s about direction. What are we building and why? What are we deliberately not building? Which tech will we use?
Here’s what the roadmap might look like for Planning Poker (partial)
# Planning Poker — Roadmap
...
## Epic 2: User Authentication (Passkeys)
**Goal:** Users can register and log in using WebAuthn passkeys stored in their browser.
**Stories:**
- Implement user registration endpoint
- Integrate WebAuthn for passkey creation on registration
- Implement passkey-based login flow
- Persist user sessions (JWT or session tokens)
- Build registration and login UI
- Handle passkey error states and browser compatibility
...
Now iterate over the roadmap until you are satisfied with the level of detail. I usually go back and forth a few times until I feel confident about the roadmap.
Step 3: Break Into Epics — and Iterate
Once the roadmap is solid, break it into epics. An epic is a self-contained, independently deliverable chunk of the app. Each epic will later get its own spec.
Now i want to clarify the requirement of epic 2 in a dedicated MD file in the
@specs/ directory. Requiremetns should be present as PRD. You will ask me
clarifying questionst until we reach confidence level 90%. For each open question provide options with [ ] (so I caneasily select my option) and one option should have a recommendation marker (as the best option based on our @specs/briefing.md ). Writedown the open questions and the
options into the requiremnts MD file, so I can answer there.
For Planning Poker, this might produce:
# User Authentication (Passkeys) — PRD
## Overview
Enable users to register and log in to the Planning Poker application using WebAuthn passkeys stored in their browser. This epic establishes the identity layer that all subsequent epics depend on — room ownership, voting attribution, and moderator permissions all require authenticated users.
## Confidence Level: 93%
---
## Requirements Extracted from Briefing
- "we want to have users with auth passkeys (a user can create a pass key in their browser on registration)"
- "any user can create or join a room" — implies registration must be lightweight so users aren't blocked from participating
- "the moderator can start the voting process" — implies role/identity is tied to the authenticated user who created the room
- Real-time room updates require a persistent identity to attribute presence and votes
---
## Directives
1. **Implement WebAuthn passkey registration and login** using the Web Authentication API. The registration flow collects only a display name and creates a passkey credential in the user's browser. *(Q2-A, Q3-C)*
2. **Issue a short-lived JWT access token (15 min) paired with a server-side refresh token (30 days)** on successful authentication. The access token is used for API and WebSocket requests; the refresh token is stored in the database and sent as an HTTP-only cookie. *(Q1-C, Q5-C)*
3. **Implement a token refresh endpoint** that silently reissues access tokens using the refresh token, so users stay logged in for up to 30 days without re-authenticating. *(Q1-C, Q5-C)*
4. **Detect WebAuthn browser support on page load** and show a clear unsupported-browser message with a list of supported browsers if the API is unavailable. Do not implement a password fallback. *(Q3-C)*
5. **Support multiple passkeys per user account.** Provide a profile UI where authenticated users can register additional passkeys and remove existing ones. *(Q4-B)*
6. **Store an extended user profile** including: ID, display name, theme preference, default voting mode, notification settings, created_at, updated_at. Passkey credentials are stored in a separate `credentials` table linked by user ID. *(Q2-A, Q6-B)*
7. **Build a minimal profile page in this epic** scoped to passkey management and display name editing only. Expose API endpoints for all preference fields (theme, default voting mode, notification settings), but defer the preferences UI to a later epic. *(Q8-B)*
8. **Build registration and login UI pages** with clear calls to action, loading states, and error handling for WebAuthn failures (user cancellation, timeout, hardware errors). *(Briefing, Q3-C)*
9. **Do not implement account recovery.** Users are responsible for registering passkeys on multiple devices. No recovery codes, no email-based recovery. *(Q7-A)*
---
## Acceptance Criteria
### Registration
- Given a new user on a supported browser, when they enter a display name and confirm passkey creation, then a user account is created and a passkey credential is stored.
...
### Login
- Given a registered user, when they initiate login and authenticate with their passkey, then they receive a JWT access token and a refresh token cookie.
...
### Session Management
- Given a valid access token, when an API request is made, then it is authorized without server-side session lookup.
...
### Passkey Management
- Given an authenticated user on their profile page, when they register an additional passkey, then the new credential is stored and both passkeys can be used for login.
...
### Profile
- Given an authenticated user, when they visit the profile page, then they can view and edit their display name and manage passkeys.
- The user preferences API endpoints (theme, default voting mode, notification settings) accept GET and PATCH requests and persist changes to the database.
---
## Deliverables
1. **User database table** — ID, display name, theme preference, default voting mode, notification settings, created_at, updated_at.
2. **Credentials database table** — credential ID, user ID, public key, sign count, transports, created_at. Supports multiple rows per user.
3. **Registration API** — `POST /auth/register` — accepts display name, initiates WebAuthn ceremony, creates user + credential.
4. **Login API** — `POST /auth/login` — initiates WebAuthn assertion, validates credential, returns JWT + sets refresh token cookie.
5. **Token refresh API** — `POST /auth/refresh` — validates refresh token cookie, issues new access JWT.
6. **Logout API** — `POST /auth/logout` — invalidates refresh token.
7. **Passkey management API** — `GET/POST/DELETE /auth/passkeys` — list, add, and remove passkeys for the authenticated user.
8. **User preferences API** — `GET/PATCH /users/me` — read and update display name and preference fields.
9. **Registration page UI** — display name input, WebAuthn passkey creation flow, unsupported browser detection.
10. **Login page UI** — WebAuthn passkey assertion flow, error handling.
11. **Profile page UI** — display name editing, passkey list with add/remove. Preferences UI deferred.
---
### Open Questions
[ ] Choice A
[ ] Choice B (**recommended**)
[ ] Choice C
---
<details>
<summary>Answered Questions (Reference)</summary>
### Q1: Session persistence strategy
**Selected: Option C — Short-lived JWT + refresh token**
...
The AI writes these questions and options into the epic’s spec file so you can answer directly in the markdown. Work through one epic at a time. You’re front-loading decisions that would otherwise blow up mid-implementation. Once every question has an answer, lock the epics and move on.
Write your own /brainstorm skill to help you with this which analyzes the epic, refines the epic requierements through structured Q&A until it reaches confidence level 90%.
Now based on this requirements design workflow I want to create a
skill that will follow this procedure: 1. analyze briefing and create
epic requirement file if not existing. 2. write down the open questions about the requirements into the file. Marking recommended option that suitas our applicaiton goals. Options should have [ ] for
easy user selection. 3. On second run the skill should reconcile the
answered questions into the PRD requiremetns and directives and acceptance criteria. 4. Once the confidence higher than 90% it should
stop and recommend writing a spec. For creation of this skill use
claude code documentaion the skill should be called brainstorm and
laying in the .claude/skills/brainstorm/SKILL.md file
You now have a nice skill which you can use on every epic to refine the requirements and answer the open questions. Once the confidence is higher than 90% it should stop and recommend writing a spec.
Step 4: Write a Spec for Each Epic
Now the real work begins. For each epic, write a proper spec before touching any code:
Based on the the @specs/epic-1-authentication.md
pleae write a detailed spec, that includes a
complete testing strategy, done definition,
architecture and tech stack decisions, that will be
possible to implement step by step incrementally to
achieve requirements and ACs stated in the epic
requirements. We apply TDD in our development
process. The spec should have -spec.md suffix and be placed in the same folder @specs/
This is a very long, detailed file now, covering Architecture Overview, Key Architectural Decisions, Tech Stack & Versions, and detailed instructions for implementation. To give you an idea of the size of my file, it is about 800 lines long and 44 KB of text.
Create your own /write-spec skill turn the epic into an implementation spec with architecture, testing strategy, acceptance criteria, incremental implementation plan, and verification checklist.
Step 5: Implement Epic by Epic
Now you’re ready to build. The rule: one epic per agent window.
implement @specs/epic-1-authentication-spec.md using this
workflow: 1. Analyze the specification. 2. Implement the tests
using TDD. 3. Implement the spec requirements. 4. Verify the
implementation by running tests. Fix implementation until the
tests are passing. 5. By the end provide a report on AC
implemented and passing test execution.
The AI has exactly the context it needs. The spec tells it precisely what to build.
Step 6: Automated Verification
We can now verify that everything was implemented. Write a verify-epic skill for that.
I want to have a new skill, verify-epic that will take an epic
# as an input, and make a report for each AC of the epic that
1. There is a test for each AC
2. There is code for each AC.
3. The tests for each AC are passing. It should return PASSED (if
all ACs are implemented)/PARTIAL (if some AC are
implemented)/FAILED (if any AC have significant problems) and
return the found gaps.
This skill will be used during
implementation to confirm the successful implementation and fix
the found gaps.
This will read the epic spec file, and for each AC it will check if there is a test for it, if there is code for it, and if the test is passing. It will then write a report to the epic spec file with the results.
When Things Go Wrong
They will. Here’s what I learned:
If the AI builds something unexpected — go back to the spec. Nine times out of ten, the spec was ambiguous, not the AI.
If a feature keeps breaking across sessions — write it out explicitly in the spec. I had a case where playback ordering logic kept getting mangled every time the AI touched it. The fix was documenting the exact sequence of steps in the spec so clearly that there was no room for interpretation.
If the AI goes in circles on a bug — close the window, open a new one, describe only the bug and the relevant spec section. Fresh context helps.
Other skills
To top that up, a architecture documentation can be created and be used by an architecture advisor agent to verify the architecture.
Results
Using this workflow,
- Fewer surprises during implementation
- Fewer frustrating “that’s not what I meant” moments
- Much easier to context-switch back in after time away — the spec brings you up to speed instantly
- The AI produces higher quality code when working from a tight spec
The first hour of writing and refining the spec feels like overhead. It isn’t. It’s the work that makes everything else go faster.
The Workflow, Summarized
briefing.md → roadmap.md → epics.md → specs/epic-N.md → implement → verify
↑ ↑ ↑ ↑
your idea iterate here iterate here iterate until
(direction) (precision) all green
The further right you go, the more precise things get. Breadth first, then depth. Each layer builds on the last.
Start vague. Get specific before you build. Keep the spec honest as you go.
That’s it.