7.1 The "scaffold → implement → refine" pattern
Overview and links for this section of the guide.
On this page
The core idea
This pattern is how you go from “idea” to “working software” without letting the model decide the architecture for you.
The sequence is deliberate:
- Scaffold: create a project shape you can build into (folders, files, entrypoints, thin stubs).
- Implement: make one end-to-end path work (the “walking skeleton”).
- Refine: clean up structure, add edge-case handling, strengthen tests, improve UX.
The pattern’s benefit is that it separates structure decisions from behavior decisions. That keeps you in control.
LLMs can generate lots of plausible code quickly, but “plausible” is not “correct” and not “maintainable.” This pattern forces a stable structure first, then demands runnable reality, then upgrades quality.
When to use it (and when not to)
Use it when:
- you’re starting a new project or a new feature area,
- you’re unsure about the best structure,
- you want fast progress without committing to details too early,
- you want a stable base for future iterations.
Avoid it when:
- you’re making a tiny change in an existing codebase (use diff-only instead),
- you already have a solid structure and just need correctness (use tests-first),
- you’re debugging (use the debugging loop in Section 8).
Step 1: scaffold (structure first)
Scaffolding is about making decisions that reduce future confusion:
- Where does the entrypoint live?
- Where does core logic live?
- Where do tests live?
- What does the public API look like?
- How do you run the thing locally?
What scaffold output should contain
- a file tree (folders + filenames),
- minimal runnable entrypoint wiring,
- stubs with clear TODOs (not full implementations),
- a README with run/test commands,
- an initial test skeleton (even if it’s small).
If you let the model implement everything during scaffolding, you lose the benefits of the pattern. Your scaffold step should be intentionally thin.
Step 2: implement (make it run)
Implementation in this pattern means: pick one end-to-end path and make it work. Not all features. Not all edge cases.
The walking skeleton concept
A walking skeleton is the smallest slice that proves the system’s shape is correct:
- you can run it,
- data flows through the intended layers,
- the output is minimally correct for a few examples,
- tests (even tiny ones) pass.
This is where vibe coding becomes powerful: you now have a runnable base you can iterate on with evidence.
Pick a slice that is easy to verify and hard to fake. For a CLI tool, it’s “parse args → run core function → print output.”
Step 3: refine (make it clean and correct)
Refinement is where you move from “it works once” to “it keeps working.” Typical refinement tasks:
- add edge-case tests and fix what breaks,
- improve error handling and UX,
- simplify code (remove cleverness),
- reduce coupling (clear boundaries),
- document usage and constraints,
- add safety rules (no unsafe evals, no secrets in logs, etc.).
If you refine too early, you polish the wrong structure. Make it run, then make it good.
Ship points for this pattern
Ship points are where you pause and lock in progress. For this pattern:
- SP1 (scaffold): file tree exists, entrypoint runs (even if it’s stubbed), tests harness exists.
- SP2 (implement): one end-to-end path works with a few examples; tests pass.
- SP3 (refine): edge cases covered; code cleaned; behavior stable; commit created.
Commit at each ship point. That’s how you keep iteration fearless and reversible.
Copy-paste prompt sequence
Here is a reliable prompt sequence you can reuse.
Prompt A: scaffold only
We are using the “scaffold → implement → refine” pattern.
Task: scaffold a small project for: [your goal in 1 sentence].
Constraints:
- Language/runtime: [...]
- Dependencies: [...]
- Provide a runnable entrypoint (even if it just prints "TODO")
- Provide a minimal test harness (even if it has a placeholder test)
Output format:
1) Print the file tree.
2) Output each file in a fenced code block labeled with the file path.
Important:
- Do NOT implement full business logic yet.
- Keep functions stubbed with clear TODOs.
Now output the scaffold only.
Prompt B: implement one walking skeleton
Now implement the smallest end-to-end “walking skeleton” for this project.
Constraints:
- Keep changes minimal and focused on making one path run
- Add/adjust tests for the walking skeleton
- Do not add extra features beyond the minimum slice
Output:
- Diff-only changes
Prompt C: refine without adding features
Refine the current implementation for clarity and correctness.
Hard constraints:
- Do not add new features
- Preserve existing behavior
- Keep diffs small and reviewable
- Add edge-case tests only where they expose real bugs
Output:
1) Propose a short plan (3–6 steps) and wait for confirmation.
2) Then output diff-only changes step-by-step.
Common pitfalls (and fixes)
Pitfall: scaffold step turns into full implementation
Fix: restate: “Stop. Only stubs + file tree. No business logic.” Ask it to rewrite the scaffold as stubs.
Pitfall: you don’t run code until it’s “finished”
Fix: force SP2 early. Even if output is ugly, run it. Fast feedback beats polished wrongness.
Pitfall: refine becomes a rewrite
Fix: switch to the diff-only pattern and apply one refactor step at a time.