Vibe Code to codebykarun.com: What I Learned (Part 6)
Part 1 of 5 in Evolution & Growth • Previously: Design System & Theming (Part 1: Foundation)
After completing the foundation of Code by Karun in the first series, I deployed to production and lived with it. This second series covers the evolution—the lessons, optimizations, and growth of a live project. Let me start with what I learned.
Lesson 1: AI Amplifies Your Skills, Not Replaces Them
What I Expected
I thought AI would write code while I sat back and watched.
What Actually Happened
The best results came when I stayed deeply engaged:
- Asking "why?" after implementations
- Suggesting alternatives
- Pushing back on solutions that didn't feel right
- Adding context from my experience
The Moment It Clicked
AI suggested this for article loading:
// Initial suggestion
export async function getArticles() {
const files = fs.readdirSync(contentDir);
return files.map(file => {
const content = fs.readFileSync(file);
return parseArticle(content);
});
}
Me: "This reads files synchronously. Won't that block the event loop?"
The Response: "You're absolutely right. Let's use async file operations..."
// Refined version
export async function getArticles() {
const files = await fs.readdir(contentDir);
return Promise.all(
files.map(async file => {
const content = await fs.readFile(file, 'utf8');
return parseArticle(content);
})
);
}
The lesson: Your experience and intuition matter. Vibe coding works best when you're an active participant, not a passive consumer.
Lesson 2: Specificity Gets Better Results
Bad Prompt
Make the site look better.
Result: Generic changes that didn't match my vision.
Good Prompt
The article cards feel cramped. Increase the vertical spacing between them
to at least 2rem. Add subtle hover effects—maybe a slight lift and shadow.
The excerpt text should be slightly muted (use text-muted-foreground) to
create visual hierarchy. I want a clean, airy feel like Apple's design
language.
Result: Exactly what I wanted.
The Pattern
Be specific about:
- What you want
- Why you want it
- How it should feel
- Examples to reference
- Constraints to respect
Think of it like explaining to a talented junior developer—clear, specific, with context and constraints.
Lesson 3: Iterate in Small Steps
The Mistake I Made
My Bad Prompt:
Build the complete article system with MDX processing, syntax highlighting,
SEO metadata, reading time, tags, and category filtering. Make it work with
Server Components and include proper TypeScript types.
Result: Overwhelming. Hard to review. Bugs in multiple places.
What Works Better
Breaking it down:
Step 1:
First, let's get basic MDX file loading working. Read files from the content
directory and return their raw content.
Step 2:
Now add frontmatter parsing using gray-matter. Extract title, excerpt, date,
and tags from the frontmatter.
Step 3:
Add syntax highlighting to code blocks using sugar-high. Apply it only to
code elements within the MDX content.
Each step was reviewable, testable, and understandable.
The lesson: Vibe coding is like pair programming. You wouldn't ask your pair to "build the entire feature while I get coffee." You'd work together, step by step.
Lesson 4: Understanding the Code Matters
The Temptation
When AI generates working code, it's tempting to just accept it and move on.
Why That's Dangerous
I made this mistake with the MDX rendering pipeline. It worked, but I didn't fully understand the component customization system.
Later, when I wanted to add custom components for callouts, I was lost.
The Solution
Always ask: "Can you explain how this works?"
Example:
const components = {
code: ({ children, ...props }: any) => {
const codeHTML = highlight(children);
return <code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} />;
},
};
My Follow-up Prompt:
Why are we using dangerouslySetInnerHTML here? Isn't that usually a security
risk? And why is the code prop typed as 'any' instead of having proper types?
Now I understood it. I could modify it. I could debug it. I owned it.
Questions to Ask
- "What happens if [edge case]?"
- "Why did you choose this approach over [alternative]?"
- "What are the performance implications?"
- "Could you add comments explaining the key parts?"
Lesson 5: Test As You Go
The Problem
I built several features in quick succession without testing. When I finally ran the dev server, multiple things were broken, and I couldn't isolate the issues.
The Better Approach
After each feature:
- Run the dev server
- Test the functionality
- Check in the browser
- Verify in different scenarios
Vibe coding is fast, but that speed can create a false sense of completion. Just because code is generated doesn't mean it works in your specific setup.
Lesson 6: The AI Doesn't Know Your Preferences
The Pattern I Noticed
AI would sometimes use patterns I don't prefer:
- Default exports vs named exports
- Certain naming conventions
- File organization approaches
The Solution
Be explicit about preferences:
For this project, I prefer:
- Named exports over default exports
- Arrow functions for components
- Descriptive variable names
- Utility files in a lib/ directory
Please follow these conventions consistently.
After that, consistency improved dramatically.
What Surprised Me Most
Three things stood out:
1. Speed Without Sacrificing Quality
What would normally take days took hours. And the code was cleaner than what I'd write alone because I could focus on architecture while AI handled boilerplate.
2. Learning Acceleration
Every interaction was a learning opportunity. "Why did you structure it that way?" led to insights about React Server Components, TypeScript patterns, and Next.js optimizations.
I didn't just build faster—I learned faster.
3. Design Confidence
As a non-designer, I expected design to be painful. Instead, through the right prompts and iteration, I created something I'm proud of.
The secret wasn't AI doing the design—it was AI helping me articulate and execute my vision.
The Reality Check
Vibe coding isn't magic:
- You still need to understand software engineering
- You still make the architectural decisions
- You still need to test and debug
- You still own the code
But it multiplies your effectiveness by handling:
- Boilerplate
- Documentation lookups
- Pattern implementations
- Best practices application
Coming Up Next
In the final part, I'll share the best practices that emerged, common pitfalls to avoid, and give you ready-to-use prompt templates for your own vibe coding journey.
Next in the Series
👉 Continue to Part 7: Best Practices & Templates
Get practical advice, prompt templates, and a framework for successful vibe coding.
More in this series: Part 1: What is Vibe Coding? • Part 2: Tech Stack • Part 3: First Hour • Part 4: MDX Pipeline • Part 5: Design System • Part 7: Best Practices