How To Get The Most Out Of Vibe Coding | Startup School

Y CombinatorAbout 6 min readApr 25, 2025Watch original
THE SUMMARYAI-generated

Vibe Coding with LLMs: Best Practices and Tips

Key Concepts: Vibe coding, LLMs (Large Language Models), AI coding agents, prompt engineering, version control (Git), testing (unit, integration), refactoring, modularity, code architecture, context provision, error handling, documentation, model selection.

1. Founder Insights on Using AI Coding Tools

  • Using Multiple Tools: Founders recommend using multiple AI coding tools like Cursor and Windsurf simultaneously. Cursor is faster for front-end tasks, while Windsurf is better for complex back-end logic. Running both with the same context can generate different iterations, allowing developers to choose the best one.
    • Example: Updating the front-end by styling it in the style of that file and pressing enter for both Cursor and Windsurf.
  • AI as a Programming Language: Think of AI as a new programming language where you program with language. Provide detailed context and information for better results.
  • Test-Driven Vibe Coding: Start with handcrafted test cases (without LLMs) to create strong guardrails for LLM-generated code. Focus on modularity and overview rather than micromanaging the code.
  • Architecture First: Spend time in a pure LLM environment to define the scope and architecture before using coding tools like Cursor. This prevents the AI from generating random, non-functional code.
  • Monitoring for Rabbit Holes: Watch for LLMs getting stuck in loops or regenerating code without progress. If frequent copy-pasting of error messages is needed, reassess the context or try a different approach.

2. Where to Start with Vibe Coding

  • Beginner-Friendly Tools: For those new to coding, Replet or Lovable offer easy-to-use visual interfaces for trying out UIs directly in code.
  • Experienced Coders: Developers with coding experience can use tools like Windsurf, Cursor, or Claude Code.
  • Comprehensive Planning: Before writing code, create a detailed plan in a markdown file within the project folder. Develop this plan with the AI, step-by-step, rather than attempting to "one-shot" the entire project.
    • Process:
      1. Create a first draft of the plan with the LLM.
      2. Remove unwanted elements and mark features as "won't do" if too complicated.
      3. Keep a section for ideas to consider later.
      4. Implement the plan section by section, explicitly stating which section to work on.
      5. Check the implementation, run tests, and commit to Git.
      6. Mark the section as complete in the plan.
  • Incremental Implementation: Implement projects piece by piece, ensuring each step is working and committed to Git before moving on.

3. Version Control and Testing

  • Git Religiously: Use Git for version control. Start with a clean Git slate before starting a new feature to easily revert to a known working version.
    • "Get reset head hard": Use this command to revert to a clean state if the AI generates non-functional code.
  • Avoid Accumulating Bad Code: If multiple prompts are needed to get something working, take the solution, reset the codebase, and feed the solution into the AI on a clean codebase.
  • Write High-Level Integration Tests: Focus on simulating user interactions (clicking through the site/app) to ensure features work end-to-end, rather than low-level unit tests.
  • Catch Regressions: Test suites help identify unnecessary changes made by LLMs to unrelated logic.

4. Expanding AI's Role Beyond Coding

  • DevOps Automation: Use LLMs for tasks like configuring DNS servers and setting up hosting via command-line tools.
    • Example: Using Claude Sonet 3.7 to configure DNS servers and set up Heroku hosting.
  • Design and Image Manipulation: Use LLMs for design tasks like creating favicons and resizing images for different platforms.
    • Example: Using ChatGPT to create a favicon image and Claude to write a script to resize it.

5. Bug Fixing Strategies

  • Error Message Analysis: Copy and paste error messages directly into the LLM. Often, the error message alone is enough for the AI to identify and fix the problem.
  • Future Automation: Expect coding tools to automatically ingest errors without manual copy-pasting.
  • Complex Bug Analysis: For complex bugs, ask the LLM to think through possible causes before writing code.
  • Reset and Retry: After each failed attempt at fixing a bug, "get reset" and start again to avoid accumulating layers of bad code.
  • Logging: Add logging to help diagnose issues.
  • Model Switching: Try different LLMs (Claude, OpenAI, Gemini) as some models may succeed where others fail.
  • Precise Instructions: Once the source of a bug is found, reset all changes and give the LLM specific instructions on how to fix it on a clean codebase.

6. Instructions and Documentation

  • Detailed Instructions: Write detailed instructions for the LLM and store them in a file (e.g., cursor rules, windsurf rules, markdown file).
  • Local Documentation: Download documentation for APIs and store it locally in a subdirectory of the working folder. Instruct the LLM to read the docs before implementing anything.
  • LLM as a Teacher: Use the LLM to explain code implementations line by line, especially for learning new technologies.

7. Complex Functionality and Code Architecture

  • Standalone Implementation: For complex features, create a standalone project with a clean codebase or download a reference implementation.
  • Reference Implementation: Point the LLM to the reference implementation and instruct it to follow that while reimplementing the feature in the larger codebase.
  • Modularity and Small Files: Maintain small, modular files and a service-based architecture with clear API boundaries. This makes it easier for both humans and LLMs to understand and work with the code.

8. Choosing the Right Tech Stack

  • Framework Familiarity: Choose a tech stack with well-established conventions and ample training data.
    • Example: Ruby on Rails is a good choice due to its 20-year history and consistent codebases.
  • Training Data Availability: Languages with less training data online (e.g., Rust, Elixir) may yield less successful results.

9. Leveraging Visual and Audio Inputs

  • Screenshots: Use screenshots to demonstrate UI bugs or provide design inspiration.
  • Voice Input: Use voice input tools like Aqua to input instructions at a faster rate (e.g., 140 words per minute).

10. Refactoring and Experimentation

  • Frequent Refactoring: Refactor code frequently after implementing tests to catch regressions.
  • LLM-Assisted Refactoring: Ask the LLM to identify repetitive code or potential refactoring candidates.
  • Continuous Experimentation: Stay updated with the latest model releases and experiment to find the best model for each task (debugging, planning, implementation, refactoring).
    • Current Model Preferences: Gemini for whole codebase indexing and implementation plans; Sonet 3.7 for implementing code changes.

Synthesis/Conclusion

Vibe coding with LLMs is a rapidly evolving field where best practices are constantly emerging. By combining the power of AI with established software engineering principles like version control, testing, and modularity, developers can significantly accelerate their workflow and achieve impressive results. Key takeaways include the importance of detailed planning, providing ample context to the LLM, leveraging different models for specific tasks, and continuously experimenting with new tools and techniques. The future of software development will likely involve a collaborative approach where humans and AI work together to build and maintain complex systems.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.