Ship It With Confidence: Building Features That Don't Break
Part 1 was about setting the table. Clean folders. Working commands. A prompt template that makes AI useful.
Now we build something real.
This article walks you through shipping an actual feature—from "I have an idea" to "it's live and working." We'll add tests (they're not as scary as they sound), use preview deployments (so you catch mistakes before users do), and write documentation that future-you will actually appreciate.
Still no professional experience required. If you can follow a recipe, you can follow this.
Explain it three ways
We're adding new drawings to our fridge, but first we need to make sure the magnets are strong enough and the tape won't fall off. This article shows how to hang each drawing carefully, check that it sticks, and write a little note saying what the drawing is about—so the whole fridge stays neat and nothing falls on the floor.
This is the repeatable feature delivery workflow: discovery documentation, AI-assisted implementation, automated testing, preview deploy reviews, and documentation updates. Every build passes through the same quality gates, which means fewer regressions, more reliable releases, and predictable timelines. Think of it as our internal "definition of done."
Instead of sprinting toward the shiny feature and hoping it works, I run a mini loop: understand what I'm building, build it with AI help, test that it works, preview it online, then write down what I learned. It's slower upfront but faster overall because we never have to scramble at the finish line. Like how we plan trips—research first, then book, then pack, then enjoy.
Why guardrails beat heroics
Let me show you two ways to build the same feature:
| Without quality gates | With quality gates |
| --- | --- |
| 800-line file that does everything | Small, focused files that each do one thing |
| `any` types everywhere ("it works, don't touch it") | Typed data that catches mistakes early |
| Commit messages like "fix stuff" | Clear messages like "add notes filter" |
| Deploy and pray | Preview, test, then deploy with confidence |
The second approach takes slightly longer per feature. But over a month? You ship more, with fewer emergencies.
The workflow we're learning
📍 You are here: Ship Features With Quality Gates
┌─────────────────────────────────────────────────┐
│ 1. Discovery → Understand before you code │
│ 2. Build → Collaborate with AI │
│ 3. Test → Prove it works │
│ 4. Preview → Catch issues before users │
│ 5. Document → Leave breadcrumbs │
└─────────────────────────────────────────────────┘| Step | Time | What you'll do |
| --- | --- | --- |
| Discovery | 8 min | Research and plan |
| Build | 12 min | Write code with AI |
| Test | 6 min | Add simple tests |
| Preview | 8 min | Deploy and verify |
| Document | 4 min | Update your notes |
| Total | 38 min | One complete feature |
Step 1: Discovery — Understand before you code (8 minutes)
The temptation is to jump straight into building. Resist it.
Spend 10-15 minutes understanding what you're actually making. This prevents the "wait, what was I building again?" confusion that hits mid-project.
Create a work order
Open your WORK_ORDER_TEMPLATE.md and fill it out:
# Work Order: Field Notes Section
## Goal
Add a section to the homepage that shows my recent learning notes,
organized by topic (psychology, cyber, AI).
## Deliverables
- [ ] FieldNotesSection component
- [ ] Data file with sample notes
- [ ] Basic tests
- [ ] Documentation update
## Constraints
- Mobile-friendly (single column on phones)
- Accessible (keyboard navigation works)
- Matches existing color palette
## Data shape
type FieldNote = {
id: string;
date: string;
topic: 'psychology' | 'cyber' | 'ai';
title: string;
summary: string;
};Why this matters
💡 The "data shape" trick
Writing out your data shape before coding is magic. When you paste this into Cursor later, the AI knows exactly what properties exist, what types they are, and how they relate. No more "I assumed there was a title field" surprises.
Step 2: Build — Collaborate with AI (12 minutes)
Now we build. But not by typing code from scratch—by having a conversation with Cursor.
The planning prompt
Paste this into Cursor (customize for your feature):
Context:
- Building a Field Notes section for my portfolio homepage
- Using Next.js, Tailwind CSS, and Framer Motion
- Work order attached: [paste your work order]
Observations:
- Data will live in src/data/fieldNotes.ts
- Need responsive layout (1 column mobile, 2 columns desktop)
- Should animate in when the section scrolls into view
Intention:
- Create a FieldNotesSection component that displays my learning notes
with topic badges and a clean card layout
Quality bars:
- Accessible (keyboard navigation, good contrast)
- Mobile-first design
- Matches existing Tailwind config colors
Format:
- Show me your plan first
- Then create the component
- Then show what files changed
Ask:
- Walk me through your approach before writing any codeWhat happens next
Cursor will respond with a plan. Read it. Ask questions if something seems off. Then let it generate the code.
🎯 You're the lead, AI is the assistant
If Cursor suggests something that doesn't feel right—wrong colors, weird layout, confusing names—say so. "Can you use the purple-to-cyan gradient instead?" or "Let's rename this to something clearer." You're directing the work, not just accepting whatever appears.
Sample component structure
Here's what a well-structured component looks like:
// src/components/home/FieldNotesSection.tsx
type FieldNote = {
id: string;
date: string;
topic: 'psychology' | 'cyber' | 'ai';
title: string;
summary: string;
};
type FieldNotesSectionProps = {
notes: FieldNote[];
};
export function FieldNotesSection({ notes }: FieldNotesSectionProps) {
return (
<section className="py-16 px-4">
<h2 className="text-3xl font-bold mb-8">Field Notes</h2>
<div className="grid md:grid-cols-2 gap-6">
{notes.map((note) => (
<article key={note.id} className="p-6 rounded-xl bg-slate-900/50">
<span className="text-xs uppercase text-cyan-400">{note.topic}</span>
<h3 className="text-xl font-semibold mt-2">{note.title}</h3>
<p className="text-gray-400 mt-2">{note.summary}</p>
</article>
))}
</div>
</section>
);
}Notice:
- Types at the top — so we know exactly what data we're working with
- Props are typed — catches mistakes if we pass wrong data
- Semantic HTML — `section`, `article`, `h2`, `h3` help screen readers
- Responsive grid — single column by default, two columns on medium screens
Step 3: Test — Prove it works (6 minutes)
Testing sounds intimidating. It's not.
A test is just: "When I do X, I expect Y to happen."
Write a simple spec first
Before asking AI for test code, write what you want to test in plain English:
## Tests for FieldNotesSection
1. When I give it notes, it shows each note's title
2. When I give it no notes, it shows "No notes yet"
3. The topic badges display correctlyAsk Cursor for the test
Using this spec, create a simple test file for FieldNotesSection:
- Renders each note title
- Shows empty state when no notes
- Displays topic badges
Use Vitest and React Testing Library.What a simple test looks like
// src/components/home/FieldNotesSection.test.tsx
import { render, screen } from '@testing-library/react';
import { FieldNotesSection } from './FieldNotesSection';
const sampleNotes = [
{ id: '1', date: '2025-12-01', topic: 'ai', title: 'Prompt patterns', summary: 'Learning...' },
];
describe('FieldNotesSection', () => {
it('shows each note title', () => {
render(<FieldNotesSection notes={sampleNotes} />);
expect(screen.getByText('Prompt patterns')).toBeInTheDocument();
});
it('shows empty state when no notes', () => {
render(<FieldNotesSection notes={[]} />);
expect(screen.getByText(/no notes yet/i)).toBeInTheDocument();
});
});Run your tests
npm run testYou want to see: ✓ All tests passed
😰 When tests fail (and they will)
Don't panic. Here's the survival checklist:
1. Read the error out loud — slows down the panic response
2. Check if dev server is running — some tests need it
3. Look for typos — "fieldNotes" vs "fieldnotes" matters
4. Ask Cursor — paste the error and say "What's wrong here?"
Step 4: Preview — Catch issues before users do (8 minutes)
Before merging to production, we deploy a preview. This is your safety net.
Push to a feature branch
git checkout -b feature/field-notes
git add .
git commit -m "feat: add Field Notes section"
git push origin feature/field-notesVercel automatically creates a preview
When you push, Vercel builds a preview version of your site. You'll get a URL like:
https://my-site-abc123.vercel.app
QA checklist
Open the preview and check:
- [ ] Does it look right on mobile? (Use Chrome DevTools device mode)
- [ ] Does it look right on desktop?
- [ ] Can you navigate with keyboard only?
- [ ] Do animations feel smooth?
- [ ] Any console errors? (Check DevTools → Console)
Log your results
Add a comment to your work order or PR:
## Preview QA — Field Notes Section
✅ Mobile view (iPhone 12 simulator)
✅ Desktop view (1440px)
✅ Keyboard navigation works
✅ npm run lint — passed
✅ npm run type-check — passed
✅ npm run test — passed
✅ Lighthouse Mobile: 94 / Desktop: 98
Notes: Adjusted card spacing on mobile for better thumb reach.Step 5: Document — Leave breadcrumbs (4 minutes)
The feature works. Tests pass. Preview looks good. One more step: write down what you learned.
Update your documentation
ROUTE_MAP.md — Add the new section:
- `/` — Homepage (includes Field Notes section) ✓DEVLOG.md — Add an entry:
## 2025-12-01 — Field Notes Section
- Added FieldNotesSection component
- 2 tests passing
- Preview: https://my-site-abc123.vercel.app
- Lighthouse: 94/98
Lesson: Writing the data shape first made AI suggestions much better.The error diary (optional but powerful)
If you hit any bugs, document them:
## Bug: Cards clipping on Safari
**Error:** Animation cards were getting cut off on Safari
**Cause:** Missing overflow handling on parent container
**Fix:** Added `overflow-visible` to the motion wrapper
**Prevention:** Add Safari to my testing checklistThese notes compound. After a few features, you'll have a personal playbook of solutions.
Challenge mode 🎯
Want to level up? Try this:
- Add a `pinned: boolean` property to your FieldNote type
- Update your sample data with one pinned note
- Show pinned notes at the top with a special badge
- Add a test for the pinned behavior
- Deploy preview and verify
- Time yourself—can you do it in under 20 minutes?
Your completion checklist
Before moving to Part 3:
- [ ] Work order filled out with goal, deliverables, constraints
- [ ] Component created with typed props
- [ ] At least 2 tests passing
- [ ] Preview deployed and QA'd
- [ ] Documentation updated (ROUTE_MAP, DEVLOG)
- [ ] Merged to main (or ready to merge)
What's next?
You've shipped a real feature with quality gates. Tests. Preview. Documentation. This is how professionals work—you just learned it without the years of trial and error.
Part 3 goes deeper: automation scripts that run your checks automatically, rollback procedures for when things go wrong, and AI governance practices that keep your collaboration productive.
Ready for the expert level?
Learn automation, rollback drills, and AI governance—the systems that keep everything running smoothly.
Continue to Part 3 →Interactive lab available
Practice the complete feature workflow hands-on:
- Discovery board for planning your feature
- Implementation prompts with live preview
- Test bench with pass/fail tracking
- Preview QA dashboard
<a href="/learn-ai-lab/vercel-cursor/intermediate" className="text-orange-300 hover:text-orange-100 underline">→ Try the Intermediate Lab</a>