Vibe Code to codebykarun.com: Evolving with Series Support (Part 8)
Part 3 of 5 in Evolution & Growth • Previously: Your Guide to Vibe Coding
After launching Code by Karun with the foundation complete, I had multiple articles that formed a series. But they were just listed chronologically like any other posts. I wanted to make series more discoverable with a special card deck design that would stand out on the home page.
This article documents that conversation—showing how vibe coding works for iterating on an existing project, not just building from scratch.
The Initial Request
My starting point was simple:
"Let's make category for series type articles which should a card deck type tile keep this state maintainable"
Notice what I didn't specify:
- How the data structure should work
- Where to store series metadata
- What "card deck" should look like exactly
- How to make it maintainable
I just expressed the goal. Let's see how the conversation unfolded.
Step 1: Understanding the Current System
The AI started by examining the existing code:
- How articles are structured (
Article
type) - How MDX frontmatter is parsed
- What files exist in the series
This is a key vibe coding practice: Start by understanding what exists before building anything new.
Step 2: Designing the Data Model
The AI proposed changes to the type system:
export interface Article {
// ... existing fields
series?: string; // Series identifier (e.g., "vibe-coding-journey")
seriesOrder?: number; // Order within the series (e.g., 1, 2, 3)
}
export interface Series {
id: string;
title: string;
description: string;
category: ArticleCategory;
articles: Article[];
totalArticles: number;
firstPublished: string;
lastPublished: string;
}
Why this worked:
- Extends existing structure without breaking changes
- Optional fields mean old articles still work
- Clear, self-documenting field names
Step 3: The Maintainability Solution
Here's where it got clever. The AI created a single source of truth:
const SERIES_CONFIG: Record<string, { title: string; description: string }> = {
"vibe-coding-journey": {
title: "Building codebykarun.com: The Vibe Coding Journey",
description: "A 7-part series documenting how I built my blog...",
},
// Add more series here as needed
};
Then articles just reference this:
---
title: "Your Article Title"
series: "vibe-coding-journey"
seriesOrder: 1
---
Why this is maintainable:
- Series metadata in one place
- Articles use simple references
- System automatically groups and sorts
- Adding new series = two simple steps
This is better than I initially imagined. I said "keep this state maintainable" and got a genuinely maintainable solution.
Step 4: The Card Deck Design
I asked for a "card deck type tile." The AI created a design with:
- Layered background cards (the deck effect)
- Series badge with icon
- First 3 articles preview with numbered badges
- "+N more articles" indicator
- Hover effects
{/* Deck effect - layered cards in background */}
<div className="absolute top-1.5 left-1.5 right-1.5 h-full
bg-[var(--warm-100)] dark:bg-[var(--warm-100)]
rounded-xl -z-10 opacity-50" />
<div className="absolute top-3 left-3 right-3 h-full
bg-[var(--warm-50)] dark:bg-[var(--warm-50)]
rounded-xl -z-20 opacity-30" />
The layered absolute
positioned divs create the stacked card effect without JavaScript or complex CSS.
Step 5: Iterating on Design
After seeing the result, I had feedback:
"It's too big make it smaller"
The AI reduced all spacing, font sizes, and padding:
p-6
→p-4 sm:p-5
var(--text-xl)
→var(--text-lg)
w-6 h-6
badges →w-5 h-5
Then another issue:
"Series episodes are not readable update text color to a lighter color"
First attempt used darker text. I clarified:
"Text visibility is still a challenge go lighter color not darker go towards white"
The AI adjusted to pure white for dark mode:
className="text-[var(--warm-900)] dark:text-white"
The lesson: Don't expect perfection on the first try. Vibe coding is a conversation. Quick iterations get you to the right solution faster than trying to specify everything upfront.
Step 6: Updating All Content
The AI then:
- Updated all 7 existing articles with series metadata
- Modified the MDX parser to read the new fields
- Created helper functions to query series
- Added the series section to the home page
- Updated documentation
All automatically, in one flow.
The Implementation Details
Here's what got built:
Data Layer (app/lib/articles.ts)
export function getAllSeries(): Series[] {
const allArticles = getAllArticlesFromAllCategories();
const seriesMap = new Map<string, Article[]>();
// Group articles by series
allArticles.forEach((article) => {
if (article.series) {
if (!seriesMap.has(article.series)) {
seriesMap.set(article.series, []);
}
seriesMap.get(article.series)?.push(article);
}
});
// Convert to Series objects with sorting
// ...
}
Clean, functional approach. Groups articles, sorts them, builds the Series objects.
UI Component (app/components/SeriesCard.tsx)
The component is self-contained:
- Handles category-specific colors
- Shows deck effect
- Responsive spacing
- Hover states
- Dark mode support
Home Page Integration
const allSeries = getAllSeries();
{allSeries.length > 0 && (
<section>
<h2>Featured Series</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{allSeries.map((series) => (
<SeriesCard key={series.id} {...series} />
))}
</div>
</section>
)}
Only shows if series exist. Responsive grid. Simple and clean.
Documenting the Feature
I asked: "Add this to Blog authoring md"
The AI updated BLOG_AUTHORING.md
with:
- New frontmatter field documentation
- Step-by-step series creation guide
- Best practices
- Real examples from the codebase
- Troubleshooting tips
Now future me (or contributors) can easily create series.
What Made This Effective
1. High-Level Goals
I didn't specify implementation details. I said what I wanted, not how to build it.
Bad: "Create a React component called SeriesCard that takes props title, description, articles array..."
Good: "Make a card deck type tile for series that's maintainable"
2. Incremental Feedback
Each iteration was quick:
- "Too big" → Smaller
- "Not readable" → Lighter text
- "Add to docs" → Documentation added
No need to get it perfect first try.
3. Context Awareness
The AI examined:
- Existing article structure
- Current MDX parsing
- Design system variables
- File locations
It integrated seamlessly with existing code instead of creating something separate.
4. Maintainability Focus
The SERIES_CONFIG
pattern emerged from my requirement to "keep this state maintainable." It's genuinely easier to maintain than alternatives like:
- Hardcoding series data in components
- Duplicating metadata across articles
- Complex database schemas
The Complete Feature Set
What we built in one conversation:
✅ Type system extensions (Article + Series interfaces)
✅ MDX parser updates
✅ Series configuration system
✅ Helper functions (getAllSeries, getSeriesById, etc.)
✅ SeriesCard component with card deck design
✅ Home page integration
✅ Responsive layouts
✅ Dark mode support
✅ Hover interactions
✅ Metadata for all 7 existing articles
✅ Complete documentation
Total time: About 15-20 minutes of back-and-forth conversation.
Lessons for Iterating on Existing Projects
Start Broad, Then Narrow
Begin with exploratory questions:
- "How are articles structured?"
- "Where is content parsed?"
Then get specific:
- "Add series field to Article type"
- "Update the parser"
Trust the Context
When working with an existing codebase, the AI can:
- Match your existing patterns
- Use your design system
- Follow your naming conventions
- Integrate with your structure
You don't have to specify these things.
Iterate Quickly
Don't try to get the design perfect in your first request:
- Get something working
- See what needs adjustment
- Make targeted changes
- Repeat until satisfied
This is faster than trying to specify everything upfront.
Think in Features, Not Files
I didn't say:
- "Create a file called SeriesCard.tsx"
- "Update articles.ts with these functions"
- "Modify the home page like this"
I said:
- "Make series discoverable"
- "Use a card deck design"
- "Keep it maintainable"
The AI figured out which files to create/modify.
The Maintainability Payoff
Adding a new series now takes two steps:
1. Add to config:
"new-series-id": {
title: "Series Title",
description: "Brief description",
}
2. Add to articles:
series: "new-series-id"
seriesOrder: 1
That's it. The system handles everything else:
- Grouping articles
- Sorting by order
- Calculating counts
- Displaying the card
- All styling and interactions
When Vibe Coding Shines
This feature demonstrates when vibe coding is most powerful:
✅ Good Fit: Adding Features to Existing Projects
- Clear existing patterns to follow
- Well-defined component structure
- Need to integrate seamlessly
✅ Good Fit: UI/UX Iterations
- Quick visual adjustments
- Responsive design tweaks
- Color and spacing refinements
✅ Good Fit: Data Structure Extensions
- Adding optional fields
- Creating new types
- Building helper functions
❌ Less Ideal: Complex Algorithms
- Advanced data structures
- Performance-critical code
- Domain-specific logic
❌ Less Ideal: Architecture Decisions
- Choosing state management
- Database schema design
- Security implementations
Reflections on the Process
What Surprised Me
The SERIES_CONFIG
pattern was more elegant than what I had in mind. I was thinking about where to store series metadata, and the AI found a solution that's:
- Simple (just a TypeScript object)
- Maintainable (single source of truth)
- Flexible (easy to extend)
- Type-safe (TypeScript validates it)
What Required Iteration
The visual design took a few rounds:
- Initial version was too large
- Text contrast needed adjustment
- Needed to go lighter, not darker, for dark mode
This is normal. Visual preferences are subjective and hard to specify perfectly upfront.
What Worked Immediately
- Type system extensions
- Data parsing
- Helper functions
- Documentation
The "code" parts worked first try. The "visual" parts needed iteration.
Key Takeaways
-
Vibe coding works for iteration, not just creation
- You can evolve existing projects
- Context helps AI match your patterns
- Integration is often seamless
-
Maintainability can be conversational
- Express the goal ("keep it maintainable")
- Don't prescribe the solution
- You might get something better than imagined
-
Design is iterative by nature
- First version rarely perfect
- Quick adjustments are fine
- Feedback loop is fast
-
Documentation matters
- Ask for docs to be updated
- Makes features usable long-term
- Helps future you understand decisions
-
High-level goals > detailed specs
- "Card deck design" was enough
- Implementation details emerged
- Results matched intent
Try It Yourself
If you have an existing project, try adding a feature through conversation:
- Describe the goal without specifying implementation
- Let the AI explore your existing code
- Review the proposal and give feedback
- Iterate on details until it's right
- Don't forget docs for future reference
The code from this conversation is live on Code by Karun. The series cards you see on the home page? That's exactly what emerged from this collaborative process.
Conclusion
Building codebykarun.com wasn't just about the initial launch. It's about continuing to evolve it through the same conversational approach.
This series feature—from concept to documentation—took one conversation. The resulting code is maintainable, the design is polished, and adding future series is trivial.
That's the power of vibe coding applied to real-world iteration.
👀 Sneak Peek: What's Next
After building the series feature, I realized we had a perfect opportunity to enhance SEO. With dedicated series pages showcasing multiple articles, we could implement rich structured data that would give search engines a complete understanding of the content hierarchy.
Coming in Part 9: I'll show you how I transformed the blog's SEO with JSON-LD structured data, dynamic metadata generation, and crawler-friendly markup—all through conversational development. You'll see how to make your content not just visible, but fully understood by search engines.
Continue to: SEO Enhancement with Structured Data