Prompting for Vibe Coding – How to Steer AI Coding Tools
You have tried vibe coding and noticed something: the quality of your results depends entirely on how you communicate with the AI. A good prompt delivers a working app in seconds. A bad prompt delivers garbage that you then get to debug for hours.
This guide shows you concrete prompting techniques built specifically for vibe coding and AI coding tools. No generic ChatGPT tips, but recipes you can drop straight into Cursor, Bolt, Claude Code or Lovable. With before/after comparisons and copy-paste templates.
The core principle: context is everything
The quality of the AI output is directly proportional to the context you provide. That is the single most important rule in prompting, no matter which tool you use. Garbage in, garbage out. Or put the other way around: precise context in, usable result out.
What does that mean in practice? The AI knows nothing about your project beyond what you give it. It does not know your architecture, your design system or your database. Every piece of information you leave out, the AI has to guess, and it often guesses wrong.
# What good context includes:
# 1. Relevant code files and snippets
# 2. Database schemas or API specifications
# 3. Error messages (complete, not truncated)
# 4. Examples of the desired behavior
# 5. Constraints and requirements
# 6. Which technologies/libraries you use (including versions!)
# Why versions matter:
# Many models only know older versions.
# Ask up front: "Which version of Tailwind do you know?"
# If the AI knows v3 but you are on v4:
# -> Paste the relevant docs directly into the context.
Technique 1: Plan first, code second
The most common mistake: you tell the AI to start coding immediately. The problem? Nine times out of ten it proposes an unnecessarily complicated approach. Have it produce a plan first instead.
# BAD - start building immediately:
"Build me a todo app with React, Supabase and auth."
# -> The AI starts coding right away, picks its own architecture,
# and you only notice later that everything needs rebuilding.
# GOOD - request a plan first:
"I want a todo app with React and Supabase.
Before you write any code: give me 2-3 architecture options.
Start with the simplest one. Explain the pros and cons.
Then I will decide which direction we take."
# -> You understand the options and make a deliberate choice.
# EVEN BETTER - a mini spec up front:
"Here is my specification for a todo app:
Goal: personal task management
Features: create, check off, delete and filter tasks
Tech: React + Tailwind + Supabase
Auth: magic link (no password)
Design: minimalist, dark
First create a plan: which files, which components,
which database structure. No code yet."
Many tools ship with a built-in planning mode. In Claude Code you can say explicitly “Create a plan first”. Cursor has a plan mode. Bolt has the Enhance button, which turns your rough prompt into a structured spec. Use these features.
Technique 2: Specific beats vague
Vague prompts are the mortal enemy of good output. The AI cannot read minds. The more specific you are, the fewer iterations you need.
# BEFORE (vague - leads to guesswork):
"Make the page look nicer."
"The button does not work."
"Optimize the code."
# AFTER (specific - leads to solutions):
"Replace the default font with Inter.
Set the background color to #1a1a2e.
Make the buttons 48px tall with 16px padding
and rounded corners (border-radius: 12px)."
"Change the save button so that it:
1. Validates the form data (all required fields filled)
2. Sends the data to /api/save via POST
3. Shows a green success message on success
4. Displays the API error message on failure
Right now nothing happens at all when I click it."
"Refactor the fetchData function:
- Extract the URL construction into its own function
- Add try/catch with specific error messages
- Replace the nested .then() calls with async/await
- Keep the existing caching logic."
Rule of thumb: if your prompt is shorter than two sentences, it is probably too vague. Always describe: What is the current state? What should the target state be? Which constraints apply?
Technique 3: Break tasks down
Large, complex assignments overwhelm the AI. The result: half-finished solutions, forgotten edge cases, chaotic code. The fix is simple: break big tasks into small, digestible pieces.
# BAD - everything at once:
"Build me a user authentication system with login, registration,
password reset, JWT tokens, email verification and
role-based access control."
# -> The AI produces 500 lines of code with guaranteed gaps.
# GOOD - step by step:
# Step 1:
"Create the database schema for user authentication.
Tables: users, sessions. Define the fields and types."
# Step 2 (after reviewing step 1):
"Create the registration function.
Input: email + password.
Hash the password with bcrypt. Store the user in the DB.
Return: the user object without the password."
# Step 3:
"Create the login function.
Verify email/password, generate a JWT token.
Token lifetime: 7 days."
# Step 4:
"Create a middleware that verifies the JWT token
and protects the secured routes."
Each step is small enough that you can review the result before moving on. That prevents mistakes from spreading through the entire codebase.
Technique 4: Assign roles
AI models respond strongly to role assignments. When you tell the AI to take on a specific kind of expertise, it dramatically changes the quality, style and depth of the answer.
# Role prompts for different scenarios:
# Code review:
"You are an experienced senior developer doing a code review.
Check this code for: bugs, performance problems,
security vulnerabilities and code quality. Be critical."
# Performance:
"You are a JavaScript performance expert.
This function is slow with 10,000+ entries.
Optimize it and explain every change."
# Security audit:
"You are a security auditor. Check this
authentication code for weaknesses.
Think about: SQL injection, XSS, CSRF, insecure
password storage, missing rate limits."
# Mentoring (for the learning effect):
"You are an experienced Python developer mentoring a
junior developer. Explain this code to me
step by step. Show me what could be improved
and why."
Pro tip: in Claude Code you can store roles like these permanently in your CLAUDE.md file. The role then applies to your entire project without you having to retype it every time.
Technique 5: Provide examples (few-shot prompting)
One of the most powerful techniques there is: show the AI an example of what you want. That instantly reduces ambiguity to zero, and the AI understands your style, your pattern and your format.
# Example: generating API client functions
"Create API client functions following this pattern:
// Example (this is what it should look like):
async function getUser(id) {
try {
// API call with error handling
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error('Failed to load');
return await response.json();
} catch (error) {
// Consistent error logging
console.error('getUser failed:', error);
throw error;
}
}
Now create the following using exactly this pattern:
- getPosts()
- createPost(data)
- updatePost(id, data)
- deletePost(id)"
# The AI automatically picks up:
# - The try/catch structure
# - The error logging format
# - The naming convention
# - The coding style
This works exactly the same way for components, tests, database queries or any other kind of code. One concrete example says more than a thousand words of description.
Technique 6: Chain of thought, or forcing the AI to think
For complex problems, the AI delivers better results when you explicitly ask it to reason step by step. Instead of a direct answer, you get a worked-out solution path.
# Chain-of-thought prompting:
"Optimize this database query step by step:
1. Analyze the current query and identify bottlenecks
2. Suggest specific index optimizations
3. Rewrite the query with more efficient JOINs
4. Explain the expected performance improvement
Current query:
SELECT u.*, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2025-01-01'
GROUP BY u.id
ORDER BY order_count DESC
LIMIT 100;"
# Without chain of thought:
# -> The AI hands you a new query immediately (which may be wrong)
#
# With chain of thought:
# -> The AI explains step by step why each change is made
# -> You understand the logic and can spot mistakes
Technique 7: Set constraints
Without constraints, the AI does whatever it wants. It pulls in libraries you have never heard of, over-engineers everything and produces 500 lines where 50 would do. Constraints keep it on course.
# Effective constraints:
"Create a dark mode toggle with these constraints:
- Plain HTML/CSS/JavaScript, no libraries
- Maximum 50 lines of code
- Store the preference in localStorage
- Use CSS custom properties for the colors
- Accessible button with an aria-label"
# More useful constraints:
# - "No external dependencies"
# - "Must work in IE11" (if you really need it)
# - "Maximum 200 lines"
# - "Follow the Google JavaScript Style Guide"
# - "Use TypeScript only, no any"
# - "Write all code comments in English"
Technique 8: Use visual context
Screenshots are one of the most underrated prompt boosters. Most modern AI tools can process images, and one image often carries more context than three paragraphs of text.
# Visual context in practice:
# Implementing a design:
# -> Attach a screenshot from Dribbble/Figma/a website
# -> "Build a component that looks like the screenshot.
# Use React + Tailwind. Responsive for mobile and desktop."
# Fixing a bug:
# -> Attach a screenshot of the broken UI
# -> "Do you see how the modal dialog disappears behind
# the header? The z-index is wrong. Fix it."
# Figma to code:
# -> Attach a Figma export or screenshot
# -> "Here is my Figma design. Implement it as a React
# component. Use the exact colors and spacing from
# the design. Font: Inter, colors: see screenshot."
# Browser console:
# -> Attach a screenshot of the error message
# -> "Here is the console error. The app crashes while
# loading the user data. What is the problem?"
In tools like Bolt and Lovable you can drag images straight into the chat. In Cursor you can paste screenshots. Use this, it saves you an enormous amount of explanatory text.
Prompt recipes for typical situations
Here are copy-paste-ready prompt templates for the most common vibe coding situations. Adapt them to your project.
Starting a new project
# Template: project kickoff
"Create a [app type] based on this spec:
Goal: [What should the app do?]
Audience: [Who is it for?]
Features:
- [Feature 1]
- [Feature 2]
- [Feature 3]
Tech stack: [e.g. React + Tailwind + Supabase]
Design: [e.g. minimalist, dark mode]
Language: English UI labels
Deliberately NOT included:
- [What you explicitly do not want]
Create a plan first, then the code."
Debugging
# Template: fixing a bug
"I am getting the following error:
[Paste the complete error message]
Expected: [What should happen?]
Actual: [What happens instead?]
Relevant code:
[Paste the code snippet]
Please:
1. Explain why the error occurs
2. Show me the fix
3. Explain how I can avoid this in the future"
# Pro tip for stubborn bugs:
"Walk through the code line by line and trace
the value of the variable 'total'. Where exactly
does it become undefined?"
Refactoring
# Template: improving code
"Refactor this function with the following goals:
1. Improve readability (shorter functions)
2. Remove code duplication
3. Add error handling
4. Add TypeScript types
Constraints:
- Keep the existing API/interface unchanged
- No new dependencies
- Briefly explain every change
[Paste the code]"
Having tests written
# Template: test generation
"Write unit tests for this function:
[Paste the function]
Test the following scenarios:
- Valid input (happy path)
- Invalid input (empty strings, null, undefined)
- Edge cases (very large numbers, special characters)
- Failure cases (network errors, timeouts)
Use [Jest/Vitest/Playwright]. Follow the existing
test pattern from [specify file/folder]."
Adding a feature
# Template: new feature
"Add the following feature to the existing app:
What: [Feature description]
Where: [In which file/component]
Behavior: [What exactly should happen?]
Example usage:
- The user clicks [button]
- [Action] happens
- The user sees [result]
Keep in mind:
- [Preserve existing patterns]
- [Stay consistent with the current design]
- [No breaking changes to existing features]"
Iterate like a pro
Prompting is not a one-shot affair. The best results come from deliberate iteration. Here are phrasings that make your follow-up prompts considerably more effective:
# Iterating - useful follow-up prompts:
# Correcting the direction:
"Good approach, but try again without recursion."
"This is too complex. Show me the simplest solution."
# Building deeper understanding:
"Why did you choose this approach instead of [alternative]?"
"Explain the trade-off between the two solutions."
# Improving quality:
"Add error handling and input validation."
"Make this more performant for large data sets."
"Add comments that explain WHY, not WHAT."
# When the AI digs itself into a hole:
"Stop. Forget the last approach. Let us start over
with a completely different approach.
Requirement: [state it clearly one more time]"
Set global rules once, apply them forever
Instead of repeating the same instructions over and over, many tools let you define global rules. That saves an enormous amount of time and keeps the output consistent.
# Global rules - configure once:
# In Claude Code -> CLAUDE.md file:
# (applies automatically to the entire project)
"Always follow these guidelines:
1. Define the data model before you write code
2. Start with mock data instead of a real database
3. Create reusable components
4. Centralize the state management
5. Implement in small steps
6. Double-check that you are editing the right file
7. Ask when requirements are unclear
8. Write tests for every new function
9. Comment complex logic in English
10. Use TypeScript instead of JavaScript"
# In Cursor -> .cursorrules file
# In Windsurf -> .windsurfrules file
# In Bolt -> project settings
If you want to dig deeper into project-wide configuration, read my CLAUDE.md guide. There I go into detail on how to set up your project so the AI knows what you want from the very first prompt.
The most common prompting mistakes
Avoid these typical traps:
Too little context. Not just the problematic line, but the whole file. Not just the error, but also what you expected to happen. The more relevant context, the better.
“Make it better” without saying how. The AI needs concrete criteria. “Improve the performance” is useless. “Reduce the API calls from 12 to a maximum of 3 per page load” is helpful.
No examples. If you want a specific format or pattern, show it. One example saves ten sentences of explanation.
Forgetting constraints. Without constraints, the AI builds over-engineered solutions with libraries you do not need. State clearly what you do not want.
Too much at once. One prompt per feature. Not three features in one prompt. Split the work up, iterate, and review after every step.
Conclusion: prompting is a skill, not a talent
Good prompting can be learned. It is not magic and it is not a gift. It is a craft that you improve with every project. The techniques in this guide are your starter kit. Apply them, experiment with them, and you will quickly notice how dramatically the quality of your AI-generated results improves.
The key takeaways once more, in compact form: provide maximum context. Plan first, code second. Be specific. Break large tasks down. Give examples. Set constraints. Iterate deliberately. And when it does not work out: start over, with a better prompt.
If you want to get started right now: grab the Vibe Coding Beginner’s Guide for the big picture, the Claude Code Cheat Sheet as your tool reference, and the guide to Claude Code hooks once you are ready for advanced automation workflows.
Further reading
- AI Glossary – key AI terminology explained in plain language
- Vibe Coding – The Beginner’s Guide
- Claude Code Cheat Sheet
