Vibe Coding in Practice
Vibe Coding can shorten the path from idea to first version, but “the page opens” is not completion. Production practice uses natural language to state the goal, repository rules to constrain the solution, and tests plus the real user flow to decide whether it can ship.
Match autonomy to blast radius
| Task | Mode | Reason |
|---|---|---|
| UI, form, or CRUD with an existing pattern | Agent implementation plus human review | Fast feedback and easy comparison |
| Small prototype | Agent-led with rapid validation | Validate demand before production hardening |
| Local fix for a clear error | Hybrid | Agent finds candidates; human confirms cause |
| Auth, access, or payment | Human-led design plus agent assistance | Failure affects accounts, data, or money |
| Migration or bulk mutation | Dry run plus explicit approval | Side effects may be hard to recover |
| Distributed concurrency or performance | Human-led with benchmarks | A single-process result can be misleading |
The question is not whether AI can write the code. Ask about blast radius, automated verifiability, rollback, and external side effects.
One iteration
outcome
→ give goal, context, constraints, and acceptance
→ let the agent read rules and nearby implementation
→ generate the smallest patch
→ run the narrow test
→ human reviews diff and risk boundaries
→ run the actual user flow
→ save evidence or continue
One loop should solve one verifiable behaviour. Do not let “also refactor, upgrade dependencies, and redesign the UI” enter the same iteration.
A reusable prompt contract
Outcome:
[What can the user do?]
Current behaviour:
[Reproduction with URL, input, and error]
Relevant scope:
[Directories that may be read or changed, existing pattern]
Do not change:
[URLs, API contracts, database fields, other people's edits]
Technical constraints:
[Framework, design system, test commands, security rules]
Acceptance:
- [Observable result 1]
- [Boundary condition 2]
- [Test and real flow 3]
Start with read-only analysis and evidence. Edit only after proposing the smallest approach.
This is more useful than “make it prettier” because it turns a subjective request into observable layout hierarchy, mobile behaviour, feedback states, and visual constraints.
Four gates from prototype to production
Behaviour gate
- Happy path completes.
- Empty data, invalid input, timeout, and repeated click have defined results.
- Refresh, back, and re-entry preserve required state.
Code gate
- Typecheck, lint, and relevant tests pass.
- No invented imports, duplicate utilities, or unnecessary abstractions.
- The diff stays inside task scope.
Risk gate
- Server-side code enforces access.
- Mutations are idempotent and risky actions require approval.
- Secrets, PII, and internal paths do not appear in logs or UI.
User gate
- The flow completes in a real viewport, browser, or client.
- Copy is natural for the persona and hides internal jargon.
- The user knows the next action, success state, and recovery path.
Quality gates should not copy arbitrary numbers
“Coverage must be 80%” and “a PR must stay below 400 lines” may suit one team but are not universal. Set thresholds from repository risk and historical evidence.
# Example: use the project's real commands and thresholds
steps:
- name: Format and lint
run: bun run lint
- name: Narrow tests
run: bun test src/path/to/changed-feature.test.ts
- name: Build
run: bun run build
- name: Contract check
run: bun run test:contracts
CI proves its assertions. Payment, publication, and installation may still require provider read-back or real-device verification.
Seven review questions for AI code
- Does it reference a function, option, or package that does not exist?
- Did it bypass an existing helper, component, or error pattern?
- Did it change a URL, API contract, or data relationship?
- Did it add a hidden network request, mutation, or logged field?
- Did a client-side check replace server-side authorisation?
- Did it create a complex abstraction for a small problem?
- Do tests cover user behaviour and failure modes?
A second model can suggest review questions. It does not replace the accountable engineer reading the diff and running the code.
Give the agent diagnostic input
Poor input:
It errors. Please fix it.
Diagnostic input:
Command: bun test src/auth/login.test.ts
Expected: invalid password maps to INVALID_CREDENTIALS
Actual: response becomes UNKNOWN_ERROR
First failing assertion: login.test.ts:84
Relevant call path: LoginForm → request.ts → mapApiError
Last known good commit: 1a2b3c4
Constraint: do not change the API response shape
Include the first meaningful failure and relevant call path, not the entire terminal history, .env, or tokens.
Three reproducible failure drills
These are exercises, not fabricated “real incidents.”
Drill A: invented API
Ask the agent to introduce a hook that does not exist. Use rg, typecheck, and package docs to prove it is absent, then reuse the repository pattern.
Drill B: wrong concurrency primitive
Add a process-local mutex to a multi-instance order service. Unit tests pass, but two processes still create duplicates. Fix with a database invariant, distributed coordination, or provider idempotency.
Drill C: dangerous migration
Generate a migration that removes a legacy field, but allow only a fixture dry run. Require proof that no read path remains, plus backup and rollback. Stop without production authority.
UI work requires viewport QA
| State | Desktop | Mobile |
|---|---|---|
| Default | Clear hierarchy and primary action | No horizontal overflow; action reachable |
| Loading | Stable layout | Skeleton fits the small screen |
| Empty | Explains why and what to do | Copy does not truncate |
| Error | Recovery, retry, or return path | Keyboard does not hide the action |
| Success | Save or submit result is explicit | Return path is clear |
Component rendering is not proof that a page is usable. Real viewport QA catches wrapping, overlap, invisible cards, and wrong interaction order.
A safe Git rhythm
git status --short
git diff -- path/to/files
git diff --check
git add -- path/to/exact-files
git diff --cached --name-only
git commit -m "fix(scope): describe user outcome"
Other changes in a dirty worktree belong to the user or teammates. Do not stash, reset, restore, or broad-stage them to make your task look clean.
Practice: a list page with all states
- Define the persona, outcome, frozen URL, and API contract.
- Find the closest list-page pattern in the repository.
- Implement only default and loading states, then test.
- Add empty and error states with recovery.
- Complete the flow at desktop and mobile viewports.
- Review the scoped diff and commit only the task files and evidence.
Definition of done
- The prompt includes outcome, context, constraints, and acceptance.
- Each loop handles one verifiable behaviour.
- Automated checks and the real user flow were both executed.
- A prompt did not replace approval for risky side effects.
- Exercises are labelled; no internal incidents or metrics are fabricated.
Related reading
Official references
📚 Related resources
❓ Common questions
Open a question to review the practical answer.
Is Vibe Coding "press a button and AI ships the whole product"?
No. Vibe Coding is a collaboration style: you describe goals, constraints, and acceptance criteria in natural language; AI generates / edits / explains / iterates the code. Direction-setting and sign-off stay with you. AI replaces the mechanical translation from requirement to code — not the judgment around priority, architecture trade-offs, and production accountability.
Which tasks suit Vibe Coding, and which need caution?
Good fit: UI tweaks, component completion, CRUD + forms + types, error triage, fresh prototypes — fast feedback, easy validation, clear rules. Be careful with: payments, auth, permissions, core architecture upgrades — high blast radius, you must own the plan. Do not hand over entirely: compliance and security-sensitive logic require human review.
What must an effective Vibe Coding prompt contain?
Specify the outcome, current behaviour, relevant scope, frozen boundaries, technical constraints, and acceptance evidence. Ask the agent to explore read-only and cite repository patterns before editing. Better context reduces guessing but does not guarantee a first-pass result; narrow tests, diff review, and the real user flow are still required.
What are the most common Vibe Coding pitfalls for beginners?
Five frequent pitfalls: (1) vague requirements → AI ships plausible-but-wrong code, fix by spelling out input / output / boundary; (2) too many files at once → impossible to triage, slice into 1–2 small tasks; (3) no error context → AI can only guess, paste logs + screenshots + stack traces; (4) reading code without running it → "looks right" ≠ runs, validate every round; (5) treating AI as the final owner → no one to catch failures, sign-off stays with the human.
Is throwing an error message at AI "being lazy"?
Errors are diagnostic input, but do not dump the entire terminal. Provide the command, expected and actual behaviour, first meaningful failure, relevant call path, last known-good version, and frozen contract. Remove `.env`, tokens, PII, and irrelevant logs. The agent offers root-cause candidates; reproduce and verify them through code paths and tests.