Flow-Based Development
The core philosophy of devfoundry
Introduction
Flow-Based Development is an approach to software that prioritizes understanding how things work over memorizing how to write code.
Traditional programming education often starts with:
- Learn syntax (variables, loops, functions)
- Learn algorithms (sorting, searching)
- Now build something!
Flow-Based Development inverts this:
- Understand the problem as a flow (input → processing → output)
- Design the architecture (components and connections)
- Implement the design (write code)
This approach aligns naturally with:
- How software actually works
- How professional architects think
- How LLMs can assist you most effectively
Core Principles
1. Think in Flows, Not Procedures
Traditional approach:
"I need to loop through an array and calculate the sum."
Flow-based approach:
"Data flows from user input → validation → calculation → display. Where does the calculation fit in this flow?"
Example: Lemonade Stand
Procedural thinking:
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price * items[i].quantity;
}
console.log(total);
Flow-based thinking:
Then implement:
function processOrder(order) {
const validated = validateItems(order);
const total = calculateTotal(validated);
return displayTotal(total);
}
Why it's better:
- Each step is a clear, testable function
- The flow is explicit and documentable
- Easy to modify (add discount step before calculateTotal)
- Matches how you'd explain it to someone
2. Components That Collaborate
Software is not a monolithic block of code. It's a system of collaborating components.
Mental model:
Think of components like people on a team. Each has a specific role. They communicate by passing messages.
Example: Lemonade Stand SPA
Components are independent but connected. Change one without breaking others.
3. Intuition Before Abstraction
Don't introduce concepts until learners have the mental scaffolding to understand why they exist.
Traditional approach:
- "Here's how inheritance works"
- (Learner: "Why do I need this?")
Flow-based approach:
- Show duplication problem: "We have three similar components with copy-pasted code"
- Demonstrate manual solution: "We could extract common logic"
- Introduce abstraction: "React has a pattern for this called hooks"
- (Learner: "Oh! That solves the problem I was just facing")
Progression example in devfoundry:
- Stage 1 (CLI): Inline logic — no abstraction
- Stage 2 (Static web): Extracted functions — simple abstraction
- Stage 3 (SPA): React components — compositional abstraction
- Stage 4 (Fullstack): Client/server separation — distributed abstraction
Each stage introduces abstraction after you've felt the pain of not having it.
4. Start Simple, Add Complexity Deliberately
Anti-pattern: Introduce all concepts at once
"This is a React app with TypeScript, Redux, React Router, styled-components, testing library, and..."
Flow-based pattern: Introduce one new concept per stage
"Stage 2 adds the DOM. That's the only new thing. Everything else stays the same."
Example progression:
| Stage | New Concept | What Stays the Same |
|---|---|---|
| 1. CLI | Basic program flow | Order logic |
| 2. Static web | DOM, events | Order logic |
| 3. SPA | React, components | Order logic, DOM (abstracted) |
| 4. Fullstack | Client/server, API | Frontend logic |
| 5. Deployment | Hosting, environment variables | Application logic |
Result: Each step feels manageable because you're only learning one new thing.
5. Visualize Everything
If you can't draw it, you don't understand it.
Every system in devfoundry is accompanied by diagrams showing:
- Module view: Files and structure
- Component-connector view: Runtime flow
- Allocation view: Where it runs
Why diagrams matter:
- Force you to articulate structure
- Reveal gaps in understanding
- Enable communication with others (humans and AI)
- Serve as design documentation
6. Architecture First, Implementation Second
Traditional workflow:
- Start coding
- Figure out structure as you go
- End up with spaghetti code
Flow-based workflow:
- Understand the problem
- Design the flow (diagram it)
- Define components and connections
- Implement components (now it's straightforward)
Example: Adding a discount feature
Architecture-first approach:
-
Understand: "10% off orders over $50"
-
Design the flow:
-
Define components:
calculateSubtotal(items)applyDiscount(total, percentage)calculateFinalTotal(subtotal)
-
Implement (now each piece is small and clear):
function processOrder(items) {
const subtotal = calculateSubtotal(items);
const discount = subtotal > 50 ? applyDiscount(subtotal, 0.10) : 0;
return subtotal - discount;
}
Result: Clear code that matches the design. Easy to test, modify, and explain.
How Flow-Based Development Enables LLM Success
Problem: Vague Prompts Lead to Generic Code
"Build a lemonade stand app"
Result: AI generates something, but it doesn't match your mental model, architecture, or constraints.
Solution: Flow-Based Prompting
I'm building a lemonade stand app. Here's the flow:
- User inputs: item (select dropdown), quantity (number input)
- Click "Add to Order" → validates input → adds to order list (array in state)
- Order list displays below with item, quantity, line total
- Calculate and display order total
- "Submit Order" button finalizes order
Module view:
- App.jsx (main component, holds state)
- OrderForm.jsx (input form)
- OrderList.jsx (displays current order)
- utils/pricing.js (calculation logic)
Please implement OrderForm.jsx...
Result: AI generates code that fits your architecture, uses your structure, and matches your flow.
Practical Application
Exercise: Think in Flows
Pick a simple app (to-do list, calculator, weather app). Before writing any code:
- Draw the flow: User input → processing → output
- Identify components: What are the major pieces?
- Define connections: How do components communicate?
- Specify data flow: What data moves where?
Only after steps 1-4 should you start coding (or prompting an AI).
Flow-Based Development in Practice
Real-World Example: Adding Authentication
Procedural approach:
- Jump into code: install library, copy-paste example, tweak until it works
- Result: Works, but you don't understand the flow
Flow-based approach:
Step 1: Understand the flow
Step 2: Identify components
- LoginForm (UI)
- AuthService (handles API calls)
- TokenStore (manages token storage)
- ProtectedRoute (checks authentication)
Step 3: Define connections
- LoginForm → AuthService (sends credentials)
- AuthService → Server (HTTP request)
- AuthService → TokenStore (saves token)
- ProtectedRoute → TokenStore (checks token)
Step 4: Implement each component Now you can code (or prompt AI) for each piece independently.
Result: You understand the system. You can modify it confidently. You can explain it to others.
Flow-Based Development vs Traditional Approaches
| Aspect | Traditional | Flow-Based |
|---|---|---|
| Starting point | Syntax, loops | Problem as a flow |
| Focus | How to write code | How the system works |
| Mental model | Sequential instructions | Collaborating components |
| Diagram usage | Rare, after-the-fact | Central, design-time |
| Abstraction | Introduced upfront | Introduced when needed |
| Complexity | All at once | One new concept at a time |
| LLM collaboration | Vague prompts | Architecture-first prompts |
| Learning curve | Steep cliff | Gradual stairs |
Common Misconceptions
Misconception 1: "Flow-based means no code"
Reality: Flow-based development emphasizes understanding before implementing. You still write code — but with clarity.
Misconception 2: "This is only for beginners"
Reality: Professional architects think this way. Seniors draw diagrams before big features. Juniors often jump straight to code.
Misconception 3: "It's slower to design first"
Reality: Thoughtful design saves time debugging and refactoring. Quick hacks create technical debt.
Summary
Flow-Based Development means:
- Thinking in flows (input → processing → output)
- Seeing software as collaborating components
- Building intuition before introducing abstraction
- Starting simple, adding complexity deliberately
- Visualizing with diagrams
- Designing architecture before writing code
Why it matters:
- Aligns with how software actually works
- Makes systems understandable
- Enables effective LLM collaboration
- Reduces cognitive load
- Builds solid mental models
Next: See Architecture-First Thinking for how to apply this when prompting AI assistants.
Further Reading
- Architectural Views — Visualizing flows
- Architecture-First Prompts — Flow-based prompting
- What Software Is — Start learning