A practical guide to vibe coding: rapidly building products using AI-assisted tools like Cursor or Windsurf. This approach focuses on quick iteration and shipping functional prototypes. While I've primarily used Cursor and Windsurf, similar principles may apply to other AI coding tools like Replit or Bolt
You can find most of my vibe coded products on /projects
🚀 The Vibe
The vibe is simple: ship fast. Prioritize functionality first, design second.
This mindset helps you stay focused on solving problems rather than perfecting things too early.
🛠Tech Stack
Stick to popular tech stacks — they usually perform better with LLMs.
- I typically use NuxtJS and Python
- All things JavaScript work great
- I’ve had good results with Go and Elixir too
If your project involves a database, go with:
- Nuxt / Next + Supabase
- Supabase handles auth, database, and security out of the box
If you don't need auth just go with a JSON Database, SQLITE, Google Sheets or Airtable
Getting Started
Your first prompt is crucial because the LLM has zero context about what you're building. Here’s the an example structure I usually follow:
Context
---
I’m building [project name]. My ideal user is [target user],
and the problem I’m solving is [problem].
Tech Stack
---
I’m using a NuxtJS starter template generated via <command>.
Package manager: bun
Use Supabase for database and authentication.
This is just context, don’t generate code yet.
This helps the LLM build context of your project before diving into implementation.
Building Your Project
Have a Product Requirement Document (PRD). It can be just a list of features and ideas for what libraries you'll use.
Example Feature Prompt
Create a WYSIWYG markdown editor.
The user types in markdown, and the editor renders live HTML.
Use TipTap for the editor.
The Workflow
- Prompt the feature.
- Debug.
- Copy-paste terminal errors into Cursor and ask for a fix.
- Tweak and iterate.
Fix errors and warnings as they appear, don’t wait till the end of your project to fix it.
Git
Use version control. Manually commit after each feature or major change. Simple, but critical.
Use Code Samples
LLMs don’t always know the latest packages or external APIs. Help out the LLM by:
- Pasting your own working snippets
- Snippents from documentation
- Reusing code from older projects or OSS projects
Be Specific About Files
As your codebase gets complicated you need to specify what changes to make to which files
Implement user authentication with Supabase,
I want the user to be able to sign in via Google Auth on @login.vue
Use the below code as reference for @login.vue:
<code sample>
And use the below code as reference or @callback.vue to
create a callback function
<code sample>
Debugging
The Lazy Way (Still Works)
Copy and paste the error → Ask the LLM to fix it (repeat)
The Better Way (More Reliable)
- Identify the function or file causing the error.
- Add logging.
- Understand the error, read StackOverflow, GitHub issues, or docs.
- Paste reference code and ask for fixes with context.
Designing
- Use TailwindCSS, skip custom CSS.
- Before design prompts, always say: "Do not change any functionality. Only update HTML and Tailwind classes"
- Use existing products as design inspiration
Base Design Prompt Example
Do not change any functionality.
Only update HTML and Tailwind classes.
Make the page look like Notion.
Use #28282B for primary buttons and borders.
Add icons from lucide-vue-next.
Design Iteration Example
Add a light gray border (gray-100)
around @editor.vue to visually distinguish it from other elements.
This is a strutured approach on how I code with LLMs. I'm always trying out new ways to improve my workflow and this is a work in progress.