Prompt Engineering for Vibe Coding: Techniques That Actually Work

I wrote over 500 AI coding prompts in the last 8 months. Most of them produced garbage code. I tracked what worked and what did not. Here is the exact framework I use to get production-quality code from every prompt.

What makes a good coding prompt vs a bad one?

Bad prompts are vague and optimistic. “Build me a login system.” Good prompts are specific and pessimistic. “Create a user registration endpoint with email verification, rate limiting of 5 attempts per hour, password hashing with bcrypt, and a minimum password length of 10 characters. Return 400 for invalid input, 409 for duplicate email, 201 for success.” The difference is night and day.

I tested this. I gave the same feature request to Cursor with a vague prompt and a specific prompt. The vague prompt generated 40 lines with no error handling. The specific prompt generated 120 lines with proper validation, error responses, and security checks. The vague prompt took 30 minutes of back-and-forth to fix. The specific prompt shipped in one shot. Specific prompts cost 2x tokens but save 5x debugging time.

My template now: “Create [exact feature]. Constraints: [tech stack, file structure, naming conventions]. Edge cases: [list them]. Error handling: return [status code] for [condition]. Write only the implementation code. Do not explain.”

๐Ÿง 

The SPEC Framework My method
Situation – Problem – Expected – Constraints

Free

How it works: S = “I am building a scheduling app.” P = “The current endpoint does not validate timezone input.” E = “It should accept only valid IANA timezones and return 400 for invalid ones.” C = “Use moment-timezone library, validate server-side, return JSON errors.” This framework consistently produces better code than free-form prompts. I tested both โ€” SPEC prompts pass tests 73% of the time vs 31% for free-form prompts.

๐Ÿ”ฅ Controversial take

The “prompt engineering is dead” crowd is wrong. Better models do reduce the need for prompt craftsmanship, but they do not eliminate it. Claude 4 Opus still generates insecure code with vague prompts. GPT-5 still misses edge cases. The improvement from better models is about 30% better output. The improvement from better prompting is about 200% better output. Invest in prompting, not model upgrades. I get better results from Cursor + Claude 3.5 with good prompts than from Cursor + Claude 4 with bad prompts.

How do you write prompts that include project context effectively?

Context is the secret weapon. I attach a project brief to every complex prompt. The brief states: the tech stack (Next.js 14, Prisma, Stripe), the file structure (/app/api, /components, /lib), the naming conventions (camelCase functions, PascalCase components), and the existing patterns (error format, logging approach). The AI uses this context to generate code that fits the existing architecture.

Without context, the AI generates standalone code that does not integrate. I built 3 features over 2 weeks without giving context. Each one used a different error handling pattern. One used try/catch. One used .catch(). One used a global error handler that did not exist yet. I spent a weekend harmonizing them. Now I always include a single-line context header: “This project uses Next.js 14, Prisma ORM, Stripe for payments. Existing API routes use async/await with try/catch error handlers that return {error: string} format. Follow these patterns.”

โšก Copy-Paste: Context Header Template
Project context: [Next.js 14 / Express / whatever framework]. Database: [Prisma / Drizzle / raw SQL]. Auth: [NextAuth / Clerk / custom]. Existing patterns: [error format, logging approach, naming conventions]. Now create [specific feature] following these patterns exactly. Do not introduce new dependencies or patterns.
๐Ÿ’ก Coach channel: Copy this into the beginning of every complex prompt. The “Do not introduce new dependencies” clause is critical โ€” AI loves adding packages. I once got an AI that imported 6 npm packages for a function that needed 0. Without the constraint, you get bloat.

What is the most effective technique for fixing bad AI output?

Do not iterate on the same prompt. Start fresh with better constraints. When the AI generates wrong code, I paste the output back and say “This is wrong because [specific reason]. Here is the corrected spec: [revised constraints].” The AI generates a new version. If it is still wrong, I switch to a different model or write the function by hand.

My rule: max 3 prompt iterations per feature. After 3 attempts the AI is usually making the same mistakes. At that point I either break the feature into smaller pieces or write it myself. Breaking into smaller pieces works 80% of the time โ€” “create the route handler only, no business logic” then “create the validation logic” then “create the database query.” Small prompts get better results than long ones.

I tracked this over 50 features. Features written as a single large prompt had a 40% first-pass success rate. Features broken into 3-4 small prompts had an 85% first-pass success rate. The total tokens used were about the same. But the small-prompt approach took half the time because there was less debugging.

References

  1. How to write vibe coding prompts
  2. Copy-paste AI coding prompt templates
  3. Cursor Composer modes explained
  4. Cursor and Claude Code system prompt templates
  5. Write specs not prompts for production code