SDD - Spec Driven Development
Spec-Driven Development (SDD) for AI-Assisted App Building
Purpose
When building apps with AI assistance, use Spec-Driven Development (SDD) to avoid letting the AI make implicit architecture decisions.
SDD means: define how the feature should work and how it should be implemented (at a high level) before generating code.
Why this matters
If you only describe the UI outcome ("build this screen") without defining implementation details, the AI will fill in the gaps—often inconsistently from screen to screen.
This can lead to:
Components that do too much
Mixed concerns (UI + data fetching + business logic everywhere)
Random patterns per feature
Low reuse and hard scaling
Difficult maintenance and refactors
Anti-pattern: “Vibe Coding” (Frontend example)
Prompt:
“Create a dashboard screen showing user stats and recent activity using this Figma design.”
What’s usually undefined
Data fetching: on load? pagination? caching?
Loading behavior: spinner vs skeleton? partial loading?
Error handling: retries? blocking UI or non-blocking?
Empty states: what to show with no data?
Component boundaries: where does logic live?
State strategy: local vs global vs cached/server state?
Refresh behavior: pull-to-refresh? auto refresh interval?
Outcome
The AI decides these things for you—often differently each time.
Recommended approach: Spec-Driven Development (Frontend example)
Use a structured spec per feature so the implementation is consistent.
Feature: Dashboard Screen
1) Scope
Display user stats (e.g., total posts, followers)
Display recent activity list (last 10 items)
2) Data layer
Data source: Supabase (REST or RPC)
Fetch timing: on screen load
Cache strategy: in-memory (e.g., React Query or equivalent)
Refetch triggers: pull-to-refresh
3) State management
Server state: handled by React Query (or equivalent)
UI state: local UI flags (loading, error, refreshing)
4) UI states
Loading
Show skeleton for stats cards
Show 5 placeholder items for activity list
Error
Show error message + retry button
Empty
Show “No activity yet” message
Success
Render stats cards
Render activity list
5) Component structure (example)
DashboardScreen
StatsCards
ActivityList
ActivityItem
Rule: child components should be pure UI (no data fetching inside children).
6) Data fetching rules
Fetching happens only in DashboardScreen
Pass data down as props
7) UX details
Pull-to-refresh triggers refetch
Smooth loading transitions (avoid layout shift)
Errors do not break layout
Key difference: SDD vs vibe coding
With Spec-Driven Development
You define how data flows
You control component boundaries
You enforce consistency across screens
With vibe coding
Each screen is built differently
Logic gets duplicated
Small changes become large refactors
Even with tools like Supabase handling auth and backend, frontend complexity is often where apps break if implementation details aren’t specified.
“Grill-me” skill (ask clarifying questions first)
Before building, use a step where the AI is instructed to:
Ask all necessary questions
Avoid assumptions
Confirm missing decisions (data fetching, states, boundaries, refresh, caching)
This prevents rushing into implementation and reduces future rework.
Do not delegate engineering decisions to AI
AI can help write code, but the team must:
Make the implementation decisions
Understand what is being built
Review architecture before generating or merging code
SDD is not the same as a PRD
SDD is not (only) a business requirements document. It focuses on software implementation details, such as:
data flow
component boundaries
state management approach
error/loading/empty UX
layering and reuse rules
Treat it as a distinct step in the process.
Suggested workflow: Ask → Plan → Build
Use a staged workflow to improve consistency.
Ask mode (clarify)
Define what you want
Ask the AI to list questions and identify missing decisions
Do not allow assumptions
Plan mode (design + tasks)
Have the AI propose an execution plan and architecture
Review, correct, and refine the plan before coding
Build mode (implementation)
Generate code based on the agreed spec + plan
Keep the AI constrained to the defined decisions
Optional guidance from the thread:
Use higher-intelligence models for the Ask/Plan phases
Use a more cost-balanced model for Build/Execution
Invest time upfront in team rules, guardrails, and agents aligned to your stack
Baseline engineering knowledge recommended (especially for low-code devs)
To make good decisions while using AI, study core software concepts:
Software layers (UI, service layer, data layer)
Design patterns (when/why, not necessarily how to implement)
Service layer vs UI components
Model classes
Interfaces and why to use them
Code reuse principles
Functions and separation of concerns
Why this matters:
AI may duplicate code unnecessarily
AI may over-engineer with layers you don’t need
Humans must enforce simplicity and maintainability
Common AI issue: duplicated functions
It’s common for AI-generated code to recreate the same logic multiple times.
Rule of thumb: identify repeated logic and extract shared utilities/modules early.
Project note: shared code for Supabase Edge Functions
If using Supabase Edge Functions, the team reported success using a shared folder for reused code across functions (used in the LOOP project).
Document internally:
Where the shared folder lives
What belongs there (shared utilities, types, helpers)
Team conventions for imports and reuse
Summary
To build scalable AI-assisted apps:
Define first (spec + decisions)
Plan next (architecture + tasks)
Generate/build last (constrained code output)
This keeps architecture intentional, reduces duplication, and improves long-term maintainability.