DEV Community

Cover image for How to Create Better Apps with my 7-step Vibe Coding Workflow
Gergely Szerovay for This is Learning

Posted on • Originally published at aiboosted.dev

How to Create Better Apps with my 7-step Vibe Coding Workflow

The main problem with vibe coding

The term "vibe coding" was coined by Andrej Karpathy to describe the process of letting AI assistants generate code while you "fully give in to the vibes" - essentially delegating the details to the AI and forgetting that code even exists.

While this approach delivers initial velocity, especially for quick prototypes, it becomes problematic as the projects grow. After my initial excitement with vibe coding wore off, I noticed something troubling: my codebase was becoming increasingly difficult to maintain and understand.

If this sounds familiar, you're not alone. Vibe coding delivers remarkable speed, especially when building on a solid boilerplate. But without proper guardrails, that speed comes at a hidden cost to your codebase's long-term health.

3 Common Challenges with AI-Assisted Development

After spending many hours experimenting with vibe coding myself, I've seen three common problems emerge:

  1. Organizational chaos: Files end up in unpredictable locations, making the project structure increasingly difficult to navigate.

  2. Growing files: What starts as a reasonably-sized component gradually balloons into a 500+ line monstrosity as the AI keeps adding "just one more function" to existing files.

  3. Inconsistency: Your codebase becomes a patchwork quilt of different styles, patterns, and approaches as the AI draws from various influences or implements similar features differently across your application.

I've learned the hard way: the key to successful vibe coding isn't just about getting the AI to write code faster - it's about getting it to write structured code following simple, clean guidelines.

While this article uses TypeScript and React as primary examples, it's important to note that these principles apply broadly across different programming languages and frameworks. Whether you're building with Angular and Material, or MCP servers using Node.js, the same four pillars of maintainable vibe coding will help you maintain quality and consistency. The specific tools and configurations will differ, but the underlying approach remains effective across technology stacks.

Vibe debugging meme

Meme source

The 4 Pillars of Maintainable AI-Assisted Development

After some trial and error, I've found that maintainable AI-assisted development rests on four pillars:

  1. Choosing the right tech stack: Selecting technologies that are well-documented and well-understood by AI tools
  2. Coding guidelines: Clear, explicit rules that both humans and AI can understand and follow
  3. Enforcement tools: Linters, formatters, and validation systems that catch deviations from your guidelines
  4. Solid boilerplate: A minimal but complete starting point with all the necessary development tools pre-configured

Let's dive into each of these areas and see how they work together to keep your vibe coding maintainable over time.

1. Choosing the Right Tech Stack

The foundation of maintainable vibe coding starts with choosing the right tech stack. Some technologies work notably better with AI assistance than others, usually because they're widely used, well-documented, and the AI has seen many examples of them in its training data.

For frontend development, I often use TypeScript, React, and Shadcn UI, paired with a Supabase backend. This combination leverages technologies that AI assistants understand well.

The TypeScript/React/Shadcn/Supabase stack works exceptionally well because:

  1. TypeScript provides strong type safety that catches many issues that might otherwise slip through in AI-generated code, while ensuring data structures are cleanly defined
  2. React is widely used and most LLMs generate React components at higher quality by default compared to other frameworks
  3. Shadcn UI provides consistent, accessible components that follow predictable patterns
  4. Supabase handles authentication, database, and storage with minimal boilerplate

I've shared a boilerplate for projects with this tech stack on my GitHub that includes all the necessary configurations and enforcements to get started with maintainable vibe coding right away.

When selecting your tech stack for AI-assisted development, consider these factors:

  • Type safety: Strongly typed languages help catch errors in AI-generated code and ensure data structures are cleanly defined
  • Documentation quality: Better documented tech leads to better AI-generated implementation
  • Community size: More widely used technologies typically have better AI support
  • Technologies with clear patterns are easier for AI to follow

2. Coding Guidelines: Teaching AI How You Work

Think of coding guidelines as creating a shared language between you and your AI assistant. With clear guidelines, you can simply tell the AI to "follow our project's architectural patterns" instead of explaining your code organization philosophy from scratch every time.

One important practice I've discovered is to continuously remind the AI about your coding guidelines throughout the development session. AI assistants can sometimes drift away from your guidelines as the conversation progresses, especially during complex implementations. Simple reminders like "Remember to follow our AIBD guidelines" can dramatically improve consistency and prevent architectural drift.

Creating a unique abbreviation for your coding guidelines (like AIBD in my case) adds significant value to your workflow. When you use this abbreviation consistently throughout your guidelines and development process, it creates a clear reference point that you can use in your prompts. Simply mentioning "follow our AIBD guidelines" instantly communicates to the AI which specific rule set you're referring to.

I've shared my AIBD (AI Boosted Development) guidelines for TypeScript-based development on my GitHub. These guidelines have evolved through months of experimentation and have proven effective across multiple vibe coding projects, and I continuously improve and extend them. You're welcome to use them as a starting point and adapt them to your needs.

Once you've established your guidelines, you need a way to efficiently share them with your AI tools. Different AI-powered development environments offer various approaches:

  • Cursor has "Cursor Rules" that provide system-level guidance.

  • Cline and Roo Code offers "Custom instructions" that can be applied to your development sessions.

  • For chat-based interfaces with filesystem access like Claude, you can ask the AI to read and follow your guidelines stored in project files.

Regardless of which AI tool you're using, after you've shared your guidelines once, you can simply tell any AI assistant to "follow our AIBD guidelines" without explaining them from scratch each time.

Cursor rules

Our guidelines should cover several key areas:

Architecture

A well-defined architecture provides the structural foundation for your codebase. It should clearly specify:

  • How code is organized (folders, files, modules)
  • Boundaries between different parts of the application
  • Dependency rules (what can import what)
  • Shared code organization

My AIBD (AI Boosted Development) guidelines use features as the building blocks of your app. A feature is simply a chunk of related functionality packaged together. Each feature gets its own folder, follows a standard structure, and keeps its internal code separate from what other features can access.

Instead of organizing by technical layers (models, components, services), we organize by features that map to business capabilities. This approach makes it much easier to describe what you want to the AI and ensures generated code fits naturally into your architecture. Example of a feature directory:

src/
├── features/            # Feature-based organization
│   ├── user-management/ # Each feature is self-contained
│   │   ├── prd.md       # Feature requirements
│   │   ├── UserProfile.ts  # Public exports
│   │   ├── UserSettings.ts
│   │   └── internal/    # Private implementation details
│   │       ├── Theme.ts
│   │       └── validateEmail.ts
│   └── payment-processing/
└── shared/              # Shared utilities and types
    ├── types/
    ├── utils/
    └── http/
        └── internal/    # Private implementation details
Enter fullscreen mode Exit fullscreen mode

Another crucial aspect of my AIBD architecture is using many small files, each containing a single declaration or definition. This approach offers several benefits:

  • The import graph directly represents connections between types, functions, and classes, making dependencies visually clear
  • Reduces token usage with AI tools - the LLM processes multiple small files focused specifically on what it needs, rather than loading huge files with thousands of lines. Tools like Cursor have line number limits (e.g., reading only 200 lines from a file at once). By staying below these limits, the AI agent can be more efficient
  • Improves focus - both you and the AI can concentrate on one specific piece of functionality at a time, rather than getting lost in a large file

AIBD intentionally avoids using barrel files (index.ts exports), as they make it easier to inadvertently introduce circular imports and make it harder for LLMs to track and understand import relationships. Direct imports from specific files create a clearer dependency graph that both humans and AI assistants can follow more easily.

Coding Style Guidelines

Beyond architecture, you need guidelines for the code itself. Your coding style guidelines should cover how to define and document types, structure function parameters, handle errors consistently, and follow appropriate naming conventions for different kinds of variables. These seemingly small decisions, when applied consistently, create a codebase that feels cohesive rather than cobbled together from different sources.

For example, instead of using both interfaces and type aliases randomly throughout your codebase, set a clear guideline like:

// Don't use interfaces
interface User {
  id: number;
  name: string;
}

// Do use type aliases
type User = {
  id: number;
  name: string;
};
Enter fullscreen mode Exit fullscreen mode

When the AI knows your preference, it can consistently apply it without you having to correct it repeatedly.

Tech Stack-Specific Guidelines

Different frameworks and libraries have their own best practices. Create specific guidelines for each major technology in your stack.

For example, my React and Shadcn UI guidelines specify how to properly structure React components, separate smart and UI components, and correctly import Shadcn UI components from the appropriate paths. These guidelines ensure that our components follow consistent patterns, maintain proper separation of concerns, and correctly utilize the UI library's built-in accessibility features.

Feature Blueprints

Blueprints provide templates for common types of features. They're incredibly valuable for AI assistance because they give the AI a starting point that already follows your patterns.

A feature blueprint might include:

  • Required files and their purpose
  • Component structure
  • Testing requirements
  • Documentation format

Documentation Guidelines

Documentation is often overlooked, but it's crucial for long-term maintenance. Guidelines should specify:

  • What needs documentation (functions, types, components)
  • Documentation format (TSDoc, Markdown)
  • Required sections and information

I use a three-level documentation approach that keeps different concerns properly separated:

1. Project-level documentation - Our guidelines contain high-level project rules, patterns, and architecture decisions. Additional project-level documentation lives in Markdown files at the repository root or in dedicated documentation directories.

2. Feature-level documentation - Each feature includes a prd.md file in its root directory that specifies business requirements, user stories, acceptance criteria, and scope boundaries. This serves as the single source of truth for what the feature should do. We call these "PRD" files (Product Requirements Document), though we're using this term for feature-level specifications rather than for entire product documentation.

A well-structured PRD file should include:

  • Title and Feature Name: Clear identification of the feature
  • Objective: A concise statement describing the purpose and business value
  • User Stories: Written as "As a [role], I want [goal] so that [reason]"
  • Requirements: Functional and non-functional requirements
  • Acceptance Criteria: Specific, testable criteria that define when the feature is complete
  • Out of Scope: Explicitly listing what's not included to prevent scope creep

3. Code-level documentation - We use TSDoc comments for all public functions, types, and components. This documentation focuses on implementation details, usage patterns, and technical considerations.

This multi-level approach ensures that developers (and AI assistants!) can find the right information at the right level of abstraction.

Code Formatting Guidelines

One especially important aspect of coding guidelines involves consistent code formatting. Tools like Prettier and EditorConfig help automatically format both human-written and AI-generated code to maintain consistency across your codebase. By defining these standards in configuration files, you eliminate formatting debates and ensure all code follows the same conventions regardless of its source.

3. Enforcement Tools

Guidelines are only effective if they're followed. This is where enforcement tools come in - they provide an objective way to ensure your codebase remains consistent even as it grows through AI assistance.

Linting Rules

ESLint is your best friend for enforcing coding standards. Configure it to catch violations of your guidelines, like the file organization rules.

The magic of linters in AI-assisted development is that you can simply ask the AI to "fix the linting errors" after generating code, and it will refactor its own work to match your standards.

Enforcing Module Boundaries

One of the most powerful tools in our linting arsenal is Sheriff, which enforces module boundaries and dependency rules. This is absolutely crucial for maintaining a clean architecture in AI-assisted development, as it prevents the AI from creating inappropriate dependencies that would violate your architectural principles.

In my boilerplate, I've set up these specific Sheriff rules:

  • Features in the features/ directory can import from each other and from the shared/ directory
  • Shared modules in the shared/ directory are forbidden from importing anything from the features/ directory
  • Imports from features are only allowed from their root directory, not from their internal/ directory

This simple set of rules helps prevent circular dependencies and maintains proper encapsulation of internal implementation details. When the AI generates code that violates these boundaries, Sheriff will immediately flag the issue, allowing you to ask the AI to fix the architectural violation.

For larger projects, you can customize and refine these basic rules to match your specific architectural needs. You might define more granular boundaries between feature groups, create specialized rules for certain critical modules, or establish stricter constraints on how shared utilities can be used. The key is to start with these fundamental rules and then evolve them as your project's architecture matures.

These boundary rules are particularly effective because they're simple enough to explain to an AI assistant, yet powerful enough to maintain the structural integrity of your codebase as it grows.

Pre-commit Hooks

Git's pre-commit hooks provide a built-in mechanism to run checks before code is committed, creating a safety net that prevents guideline violations from making it into your repository.

A typical pre-commit configuration might:

  • Run the linter
  • Run the code formatter
  • Run the unit tests
  • Run madge to detect circular references before they cause issues

Automated Testing

One practice I've found particularly effective is directly mapping your test cases to the acceptance criteria in your PRD files. This creates a clear traceability between what was required and what was delivered. You can ask the AI to generate test cases based on the acceptance criteria, giving you a head start on comprehensive test coverage.

For example, if your acceptance criteria includes "On submit, disable all controls and show a loading spinner in the button" you'd have a corresponding test that verifies exactly that behavior. This approach ensures that your tests are focused on business requirements rather than implementation details.

4. Solid Boilerplate: Start Off on the Right Foot

The final piece of the puzzle is a well-crafted boilerplate - a minimal but complete starting point with all the necessary development tools pre-configured.

Your boilerplate should include:

  • Project structure following your architectural guidelines
  • Development tools (linters, formatters, etc.) with pre-configured rules
  • Testing framework setup
  • UI component library integration
  • Authentication skeleton (if applicable)
  • API client structure
  • Build and deployment configurations

Example: AIBD React Template

To demonstrate how these concepts work in practice, I've created an AIBD React Template available on GitHub. This boilerplate implements all the principles we've discussed and provides a solid foundation for AI-assisted development.

Technical Stack

The template uses a modern, well-supported stack that AI tools understand well:

  • React 19: The latest version with improved performance features
  • TypeScript: For type safety and better AI assistance
  • Vite: Fast, modern build tooling
  • TailwindCSS: Utility-first CSS that AI excels at generating
  • Shadcn UI: Pre-built components based on Radix UI
  • React Router v7: Declarative routing
  • React Hook Form: Flexible and extensible forms with validation
  • Zod: TypeScript-first schema validation
  • Supabase Client: Authentication and backend services

Project Structure

The boilerplate implements a feature-based architecture that maps directly to the AIBD guidelines.

The boilerplate comes pre-configured with a comprehensive set of enforcement tools:

  • ESLint: Configured with strict TypeScript and React rules
  • Sheriff: Enforces module boundaries between features and shared code, preventing inappropriate dependencies.
  • Husky and lint-staged: Run validation before each commit:
    • Linting of staged TypeScript files
    • Automatic code formatting with Prettier
    • Checking for circular dependencies
    • Running unit tests to ensure nothing is broken

This enforcement setup creates guardrails that keep AI-generated code on track, even when you're moving quickly.

Putting It All Together: A 7-step Vibe Coding Workflow

Now that we've covered the four pillars, let's look at a practical workflow that brings them all together.

After each step in this workflow, always review and validate the AI's modifications. Remember that AI assistance should augment your judgment, not replace it. If you spot issues:

  • Ask the AI to fix specific problems: "This component is missing error handling. Please add proper error states."
  • Fix things manually when the AI struggles with complex corrections
  • Use the AI to explain confusing generated code before making changes

At the end of the workflow, you'll have a clean import graph (generated by Madge) - a visual representation of your feature dependencies and module boundaries. While you can analyze these graphs in detail, a simple "squint test" is surprisingly helpful: a healthy codebase will have a tree-like structure rather than a chaotic, tangled web of dependencies, and should never contain red lines or nodes (which indicate circular dependencies that can cause runtime issues):

Import graph

Here are the steps of the workflow:

7 step

  1. Start with the AIBD React Template or similar boilerplate that already includes the right tech stack and all necessary enforcement tools.

  2. Share your coding guidelines at the beginning of each session. With tools like Cursor, you can add these as persistent rules the AI will follow automatically.

  3. Request features in architectural terms rather than implementation details. Start by asking the AI to create the directory structure and PRD documentation before implementation.

🧑: I'd like to design three features for our application using Supabase 
for authentication:

1\. A sign-in feature
2\. A dashboard with sidebar that displays the user's email and has a 
   sign-out button
3\. A sign-out feature

Please follow our AIBD guidelines.

Could you please first create the directory structure for these features 
following our feature-based architecture, and draft the prd.md files for 
each one?
Enter fullscreen mode Exit fullscreen mode

This approach ensures your AI assistant establishes the right foundation before diving into implementation details. The PRD files will serve as the blueprint for implementation while maintaining architectural consistency.

4. Let the AI generate the initial implementation based on your guidelines and existing patterns in the codebase:

🧑: Now please implement all the features based on their PRDs, 
following our AIBD guidelines.
Enter fullscreen mode Exit fullscreen mode

5. Ask the AI to implement tests for the Acceptance Criteria listed in the PRDs:

🧑: Now let's make sure we have test coverage for our business 
requirements. Please implement unit tests for all the acceptance 
criteria in our sign-in feature's PRD.
Enter fullscreen mode Exit fullscreen mode

6. Commit and trigger pre-commit hooks with AI to validate your code and fix any issues that arise:

🧑: Generate a conventional commit message from uncommitted changes. 
It should reference the directory structure: 
include (feature/user-management) or (shared/utils) based on which 
features or shared modules were modified. Commit the changes.
Enter fullscreen mode Exit fullscreen mode

This approach ties your commit messages directly to your codebase's architecture, making it easier to track which features or shared modules are changing over time.

If your pre-commit hook catches any issues, use a separate prompt to get help fixing them:

🧑: The pre-commit hook failed with these errors.
Please help me fix them while maintaining our AIBD guidelines.
Enter fullscreen mode Exit fullscreen mode

Having the AI fix linting or testing errors helps it learn from mistakes and reinforces your code standards.

7. Repeat for each feature or component, letting the AI build on its previous work.

Conclusion: Maintainable Vibe Coding

Vibe coding with AI assistance isn't just about writing code faster - it's about maintaining quality and consistency while accelerating development. By choosing the right tech stack, establishing clear guidelines, implementing enforcement tools, and starting with a solid boilerplate, you can benefit from the power of AI without sacrificing the long-term health of your codebase.

Remember:

  • Choosing the right tech stack provides a solid foundation for AI-assisted development
  • Guidelines communicate your standards to the AI
  • Enforcement tools verify adherence to those standards
  • Boilerplate encodes your best practices from the start
  • Properly sharing guidelines with AI tools keeps everything consistent

With this framework in place, AI becomes more than just a speed boost - it helps you consistently produce maintainable, structured code that remains comprehensible as your project evolves.

Have you established guidelines for your AI-assisted development? What challenges have you faced with vibe coding? I'd love to hear about your experiences and what's worked for you.

About the Author

My name is Gergely Szerovay. I've worked as a data scientist and full-stack developer for many years, and I've been a frontend tech lead focusing on Angular development for the past three years. To closely follow the evolution of AI-assisted software development, I've decided to start building AI tools in public and publish my progress on AIBoosted.dev.

Follow me on Substack (Angular Addicts), Substack (AIBoosted.dev), Medium, Dev.to, X or LinkedIn to learn more about Angular and how to build AI apps with AI, TypeScript, React, and Angular!

Top comments (0)

OSZAR »