This post contains affiliate links.
For about six months, I was that developer. The one who kept insisting AI code completion was just a fancy autocomplete that wrote mediocre code. I’d tab-accept a suggestion, watch it go sideways, spend 10 minutes debugging something I’d have written correctly in 2 minutes, and then complain loudly in Slack about it.
I was wrong. Not about the mediocre code part — that’s still real — but about how to use these tools. I was treating AI completion like a junior developer who should just write code for me. That’s not what it is. Once I figured out what it actually is, everything changed.
The Mental Model Shift That Changed Everything
Here’s the reframe: AI code completion isn’t a developer. It’s a very fast typist who has read every Stack Overflow post ever written and has excellent pattern recognition. You’re still the architect. You’re still making decisions. The AI is just reducing the mechanical overhead of translating decisions into keystrokes.
With that in mind, I stopped evaluating suggestions by asking “is this exactly what I would have written?” and started asking “does this get me 70% of the way there in 5 seconds?” That’s a completely different bar, and most AI suggestions clear it easily.
The Workflow That Actually Works
I’ve landed on a three-layer approach after months of iteration:
Layer 1: Boilerplate Annihilation
Let the AI handle everything that’s just typing. CRUD endpoints, test scaffolding, type definitions from an existing schema, repetitive transformations. I don’t even review these carefully — I review them the same way I’d review my own boilerplate: quickly and with low scrutiny.
Example — I needed to write a series of Zod validators for an API I was building. Old me would have typed these out manually:
// I typed this comment and the first validator
// Validators for user profile endpoints
const updateProfileSchema = z.object({
displayName: z.string().min(2).max(50),
bio: z.string().max(500).optional(),
});
// AI completed the remaining 8 validators based on the pattern
// Each took about 0.5 seconds to accept or lightly edit
const updateAvatarSchema = z.object({
avatarUrl: z.string().url(),
cropData: z.object({
x: z.number(),
y: z.number(),
width: z.number(),
height: z.number(),
}).optional(),
});
Time saved: probably 15 minutes on a task that used to feel like a chore.
Layer 2: Logic Drafting
For actual business logic, I’ve learned to write detailed comments first, then let the AI draft the implementation. I review this more carefully — it’s where mistakes hide — but the draft is almost always a better starting point than a blank function.
// Calculate subscription renewal date
// - If annual plan: add 1 year, adjust for leap years
// - If monthly: add 1 month, handle month-end edge cases
// - If trial: use trial end date as base, not signup date
// Returns ISO string, always in UTC
function calculateRenewalDate(
currentDate: Date,
plan: 'annual' | 'monthly' | 'trial',
trialEndDate?: Date
): string {
// AI drafts this implementation
// I review and usually tweak 1-2 edge case conditions
}
The comment isn’t just for the AI — it’s forcing me to think through the logic before I write a single line. That thinking process is where I used to make most of my bugs anyway.
Layer 3: The Hard Stuff Stays Mine
Architecture decisions, security-sensitive code, anything touching payments or auth flows — I write this myself with AI off or used only for syntax assistance. Not because AI can’t generate it, but because I need to understand every line deeply. AI-generated auth code that I don’t fully understand is a liability, not an asset.
The Tools I’m Actually Using
I switched to Cursor about four months ago and haven’t looked back. What makes it different from a plugin isn’t just the quality of completions — it’s the ability to have a conversation about your codebase. I can select a function and ask “what are the edge cases I’m not handling here?” and get useful answers because Cursor understands the surrounding context, not just the selected lines.
The composer feature is where I spend most of my productivity gains. I’ll describe what I want to build at a high level, let it scaffold the structure, and then work through each piece with my own hands. It’s less “AI writes my code” and more “AI gives me a populated template to react to.” Reacting to something is almost always faster than creating from nothing.
For my side projects, I’m hosting everything on Hostinger — the VPS plans have been solid and the deploy workflow fits nicely with how I’ve been shipping smaller AI-assisted projects faster. When you’re moving quicker with these tools, you want infrastructure that doesn’t slow you down with complexity.
The Honesty Section: Where AI Still Fails Me
I’d be doing you a disservice if I made this sound perfect. Here’s where I still get burned:
Hallucinated APIs: AI will confidently write code using methods that don’t exist, especially for newer libraries or niche packages. I’ve learned to always verify method signatures against actual docs for anything I don’t immediately recognize.
Subtly wrong business logic: The code looks right. It passes obvious tests. And then two weeks later a user finds the edge case that the AI didn’t think about because it doesn’t know your users or your domain. More unit tests, not fewer, when using AI-assisted code.
Over-engineering: AI has read a lot of enterprise code and it loves patterns. Sometimes I ask for a simple helper function and get back a factory with three abstractions. You have to push back: “make this simpler” is a prompt I use constantly.
The context limit trap: In longer sessions, AI starts to lose coherence with decisions made early in the conversation. I’ve started keeping a small markdown file with key architectural decisions and pasting it as context at the start of each session. Crude but effective.
Measuring the Actual Impact
I track my shipped features roughly, and the difference over the past four months compared to the four months before is meaningful. I’m shipping about 40% more features per sprint on my solo projects. More importantly, I’m spending less time on the parts I hate (boilerplate, repetitive transformations, test scaffolding) and more time on the parts I actually enjoy (architecture, interesting logic problems, talking to users).
Code review scores from teammates haven’t dropped. If anything they’ve improved slightly, probably because the comment-first approach I described above is producing better documented code as a side effect.
Getting Started If You’re Still Skeptical
If you’re where I was six months ago, here’s the minimal experiment I’d suggest: pick the most tedious, repetitive task in your current project. Something you’re dreading. Let the AI handle it completely, review it carefully, fix whatever needs fixing. Track how long that took compared to doing it yourself.
Don’t start with the hard stuff. Don’t try to use it for your most critical code. Start with the stuff that’s draining your energy and see what that feels like. I’d bet you’ll find the same thing I did: the time I was spending on low-value mechanical work was silently killing my momentum on the high-value creative work.
Once you’ve made peace with that layer, the other layers become obvious.
The Bigger Picture
The developers who are going to struggle with these tools are the ones who see them as either magic (fully trust everything) or threat (fully resist everything). The practical middle ground is treating AI as infrastructure — useful, fallible, requiring oversight, but genuinely worth integrating into your stack.
I still write code. I still make all the decisions that matter. I just spend a lot less time typing the decisions I’ve already made.
That’s a trade I’ll take every time.
If you found this useful, I write about AI tools and developer workflow regularly at WithStack. Subscribe to get new posts in your inbox — no spam, just the stuff worth reading.