Architecture-First Prompting
Build features by describing structure, not just functionality
Overview
Architecture-first prompting means giving AI assistants the context they need to generate code that fits your system, not generic code that might work.
This template is for:
- Building new features
- Adding components to existing projects
- Implementing requirements with architectural clarity
Time investment: 5-10 minutes to write a good prompt (saves hours of refactoring)
Why Architecture-First?
The Problem
❌ Vague prompt:
"Add a shopping cart to my app"
AI generates:
- Redux store (but you're using useState)
- Class components (but you're using functional)
- Inline styles (but you're using CSS modules)
Result: Code that doesn't fit. Hours spent adapting.
The Solution
✅ Architecture-first prompt:
**System**: Lemonade stand SPA, React with hooks, no state library
**Architecture**:
- App.jsx holds state: {orders: [], total: 0}
- Components: OrderForm.jsx, OrderList.jsx
**Requirement**: Add shopping cart functionality
- Display all orders
- Allow removing items
- Show running total
**Constraints**:
- Use existing state structure
- Follow functional component pattern
- Match existing naming conventions
Please implement.
AI generates: Code that drops right in.
The Architecture-First Template
**Context**: [Brief system description]
**Tech Stack**: [Languages, frameworks, libraries]
**Architecture** ([View Type]):
[Describe structure — files, components, data flow]
**Current State**: [What exists now]
**Requirement**: [What you need to add]
**Constraints**: [Requirements, limitations, patterns to follow]
**Expected Behavior**: [User flow or data flow]
Please implement [SPECIFIC THING].
Template Deep Dive
Section 1: Context
Purpose: Orient the AI to your project
What to include:
- Project name or description
- Stage of development (prototype, production, learning example)
- Relevant devfoundry example if applicable
Example:
**Context**:
I'm building the lemonade stand fullstack app from devfoundry
(examples/04-lemonade-fullstack). It's a learning project demonstrating
client/server architecture.
Section 2: Tech Stack
Purpose: Specify exact technologies
What to include:
- Language and version (if relevant)
- Frameworks and libraries
- Build tools
Example:
**Tech Stack**:
- Frontend: React 18, Vite, TypeScript
- Backend: Node.js 18, Express 4.x
- Database: SQLite (better-sqlite3)
- No state management library (using useState + Context)
Section 3: Architecture
Purpose: Show structure using architectural views
What to include:
- Specify which view (Module, Component-Connector, or Allocation)
- File/folder structure OR data flow OR deployment structure
Module View Example:
**Architecture** (Module View):
src/
components/
OrderForm.tsx
OrderList.tsx
utils/
pricing.ts
App.tsx
Component-Connector View Example:
**Architecture** (Component-Connector View):
User → OrderForm → App state → OrderList → Display
Allocation View Example:
**Architecture** (Allocation View):
Browser (React) ←HTTP→ Server (Express) ← SQLite
Section 4: Current State
Purpose: Show what already exists
What to include:
- Existing code (relevant snippets)
- Current state shape
- Existing functions or components
Example:
**Current State**:
App.tsx holds this state:
```tsx
const [orders, setOrders] = useState<Order[]>([]);
const [total, setTotal] = useState<number>(0);
OrderForm.tsx accepts props:
interface OrderFormProps {
onAddOrder: (order: Order) => void;
}
---
### Section 5: Requirement
**Purpose**: Specify what you need
**What to include**:
- Feature description
- User-facing behavior
- Data changes needed
**Example**:
Requirement: Add a "Remove Item" button to each order in OrderList.
Behavior:
- Each order row shows a "Remove" button
- Clicking removes that order from the state
- Total recalculates automatically
---
### Section 6: Constraints
**Purpose**: Specify limitations and patterns
**What to include**:
- Style guidelines (functional components, naming conventions)
- Performance requirements
- Compatibility needs
- Patterns to follow or avoid
**Example**:
Constraints:
- Must use functional components (no classes)
- Follow existing naming: camelCase for functions, PascalCase for components
- Keep components under 100 lines
- Reuse existing
calculateTotalfunction from utils/pricing.ts - No external libraries (use built-in React only)
---
### Section 7: Expected Behavior
**Purpose**: Describe the flow clearly
**What to include**:
- User interaction sequence
- Data transformations
- Visual updates
**Example**:
Expected Behavior:
- User clicks "Remove" button on order #3
- App state updates (removes order with id=3)
- calculateTotal is called with new orders array
- Total updates
- OrderList re-renders without removed item
---
## Complete Example
### Scenario: Add Discount Feature
Context: I'm building the lemonade stand SPA (devfoundry examples/03-lemonade-spa). This is a learning project teaching React state management.
Tech Stack:
- React 18 (functional components with hooks)
- Vite (build tool)
- TypeScript
- No state library (plain useState)
Architecture (Module View): src/ components/ OrderForm.tsx (user input) OrderList.tsx (displays orders) Summary.tsx (displays totals) utils/ pricing.ts (has calculateTotal function) App.tsx (holds state)
Architecture (Component-Connector View): OrderForm → App.updateOrders() → calculateTotal → Summary.display()
Current State:
App.tsx:
const [orders, setOrders] = useState<Order[]>([]);
const [subtotal, setSubtotal] = useState<number>(0);
utils/pricing.ts:
export function calculateTotal(orders: Order[]): number {
return orders.reduce((sum, order) => sum + (order.price * order.quantity), 0);
}
Requirement: Add a discount system:
- If subtotal > $50, apply 10% discount
- Display subtotal, discount amount, and final total in Summary.tsx
Constraints:
- Create new function: calculateDiscount(subtotal: number): number in pricing.ts
- Modify App.tsx to store discount and finalTotal in state
- Update Summary.tsx to display all three values
- Must use existing calculateTotal function (don't modify it)
- Follow TypeScript best practices (explicit types)
Expected Behavior:
- User adds orders until subtotal > $50
- App calculates: discount = subtotal * 0.10
- App calculates: finalTotal = subtotal - discount
- Summary displays:
- Subtotal: $52.00
- Discount: $5.20
- Final Total: $46.80
Please implement:
- calculateDiscount function in utils/pricing.ts
- Updated state management in App.tsx
- Updated Summary component to display all values
---
## What Makes This Effective
✓ **AI knows the exact tech stack** (no wrong libraries)
✓ **AI sees the existing structure** (generates fitting code)
✓ **AI understands constraints** (follows patterns)
✓ **AI knows expected flow** (implements correctly)
✓ **Request is specific** (clear deliverables)
---
## Common Variations
### Variation 1: Referencing ADRs
If you have Architecture Decision Records:
Context: Per ADR-0001, we use React functional components with hooks (no classes). Per ADR-0002, we use Node + Express for backend.
[rest of prompt...]
---
### Variation 2: Referencing Diagrams
If you've drawn diagrams:
Architecture (Component-Connector View):
I want to add a ConfirmationModal between OrderForm and App:
User → OrderForm → ConfirmationModal → App
Please implement ConfirmationModal.tsx.
---
### Variation 3: Multi-File Changes
When changes span multiple files:
Requirement: Add user authentication
Files to modify:
- server/routes/auth.js (new file — login/signup endpoints)
- server/middleware/auth.js (new file — JWT verification)
- client/src/App.tsx (add login check, redirect if not authenticated)
- client/src/components/Login.tsx (new file — login form)
Please implement each file with clear comments. Show me the files one at a time, starting with server/routes/auth.js.
---
## Iteration Pattern
Architecture-first prompting enables clean iteration:
### Round 1: Core Implementation
[Full prompt as above] Please implement the discount feature.
### Round 2: Refinement
Thanks! The discount logic works. Now I want to:
- Only apply discount to orders of "Lemonade" (not other items)
- Add a message: "You saved $X!"
Update the calculateDiscount function and Summary component.
### Round 3: Edge Cases
What happens if:
- User removes items and subtotal drops below $50?
- All items are removed?
Please handle these edge cases in App.tsx.
---
## Troubleshooting
### AI Generates Wrong Framework
**Problem**: You said React, but AI used Vue
**Fix**: Add to tech stack:
Tech Stack:
- React 18 (NOT Vue, NOT Angular)
---
### AI Ignores Existing Code
**Problem**: AI rewrites code you wanted to keep
**Fix**: Be explicit:
Constraints:
- DO NOT modify calculateTotal function
- DO NOT change existing state structure
- ONLY add new functionality
---
### AI Uses Wrong Patterns
**Problem**: AI uses class components when you wanted functional
**Fix**: Add to constraints:
Constraints:
- Functional components ONLY (no class components)
- Hooks for state (useState, useEffect)
- TypeScript with explicit types
---
## Checklist: Before Sending Prompt
- [ ] Specified tech stack clearly
- [ ] Described architecture (module/component/allocation view)
- [ ] Showed existing code (relevant snippets)
- [ ] Stated requirement clearly
- [ ] Listed constraints (patterns, conventions, limitations)
- [ ] Described expected behavior (user flow or data flow)
- [ ] Asked for specific deliverables
---
## Next Steps
### Practice
Use this template for:
- Exercises in devfoundry curriculum
- Your own projects
- Features in the lemonade stand examples
### Related Templates
- Debugging — When things don't work (to be created)
- Designing Features — Planning before building (to be created)
- Iterative Refinement — Improving code (to be created)
---
## Summary
**Architecture-first prompting**:
1. ✓ Provide system context
2. ✓ Specify tech stack precisely
3. ✓ Show architecture (use views)
4. ✓ Describe current state (paste code)
5. ✓ State requirement clearly
6. ✓ List constraints explicitly
7. ✓ Describe expected behavior
**Result**: AI generates code that fits your system perfectly.
**Time saved**: Hours of refactoring → Minutes of clear prompting
---
**Ready to try?** Pick a feature from your current example and use this template!