How I Rebuilt My Blog with Next.js, MDX, and Hashnode Integration
For the last few days, my desk looked like a battleground — tabs everywhere, logs exploding, MDX yelling at me, and Next.js refusing to cooperate.
But today, as everything finally came together, it felt worth it.
I migrated my entire blog from Vite + React to Next.js App Router, added rich MDX support, and integrated Hashnode articles into one unified platform.
It genuinely felt like building a product for myself — breaking things, fixing them, refactoring, rethinking, and ultimately enjoying the win.
Why I Needed MDX (And Why Traditional Platforms Weren’t Enough)
I’ve been writing on Hashnode for a long time — it’s great. But as I went deeper into system design and low-level concepts, I hit a wall.
Some articles needed:
- Embedded interactive demos
- Side-by-side comparisons
- Step-by-step tutorials
- Custom callouts
- File trees
- Multiple tabs for alternative approaches
- Rich explanations that feel like documentation
The Limitation
Platforms like Hashnode or Medium don’t allow custom React components or MDX-like interactivity. You write markdown — and that's it.
That restriction started hurting my ability to explain complex concepts clearly.
So I switched to MDX.
And honestly? It felt like moving from a notebook to a full developer playground.
Why MDX Was the Right Choice
Here’s how MDX transformed my writing flow:
Freedom to Use React Components
I can drop in a <Callout>, a <Demo>, or even my own custom UI directly inside the article — without hacks.
Better Technical Storytelling
MDX lets me structure articles the way developers think — with steps, tabs, comparisons, and interactive snippets.
Perfect for Deep-Dive Content
My system design and architecture explainers often need visuals, embedded diagrams, and complex examples. MDX fits that perfectly.
Complete Control Over Styling & Layout
No more fitting my content into someone else’s theme. The blog now feels like my product.
Finally
I can explain concepts exactly the way I want — richly, interactively, and without compromises.
The Migration: How I Moved from Vite + React to Next.js
I didn’t just migrate the site — I rethought its architecture.
Here’s a quick snapshot of how the migration unfolded:
- Manual routing
- Limited SEO
- No server components
- No built-in MDX pipeline
- Hard to fetch external content
Migrating felt like switching from a tool to a framework designed for content sites.
The New Folder Structure
This separation helped me maintain a clear boundary between:
- UI (app router)
- Content (MDX files)
- Integrations (Hashnode fetching utilities)
Bringing MDX to the Blog: The Real Game-Changer
Introducing MDX into the blog wasn’t just a feature upgrade — it fundamentally changed how I could communicate ideas.
But the journey wasn’t smooth.
Confession
I underestimated MDX. It looked simple… until it wasn’t.
The initial setup felt like assembling Lego pieces from three different sets. Config files didn’t agree with each other, loaders complained, and even a missing plugin or wrong file extension caused unexpected failures. But once the pieces clicked together, MDX opened a completely new dimension.
Start With the Pipeline
I defined a basic MDX pipeline that the App Router could understand — nothing fancy, just a clean extension-based setup.
Enhance It With Components
Then I connected my custom components: <Callout>, <Steps>, <Tabs>, <Demo>, and others.
This single step made the blog feel more like a developer playground than a static article renderer.
Optimize Rendering
With RSC (React Server Components), the MDX pages became lighter, faster, and more maintainable.
I could fetch metadata, inject components, and even preprocess content smoothly.
Here’s a simplified example of how I mapped MDX components:
export const mdxComponents = {
Callout,
Steps,
Step,
Tabs,
TabItem,
Demo,
FileTree,
};
Why This Matters
Bringing Hashnode Posts Into the Same Space
Even after migrating, I didn’t want to abandon the dozens of articles I had already written on Hashnode. Instead, I wanted everything — MDX posts and Hashnode posts — to live together under one unified reading experience.
Think of it like merging two libraries without changing the books inside.
To achieve this, I set up a small server function that fetches my Hashnode publication using their GraphQL API. No heavy processing — just clean data, transformed into a format my blog understands.
export async function getHashnodePosts() {
const response = await fetch(HASHNODE_GRAPHQL_URL, {
method: "POST",
body: JSON.stringify({ query: HASHNODE_QUERY }),
});
const json = await response.json();
return json.data.publication.posts;
}
Hashnode posts load dynamically and sit beside MDX posts in the same blog list.
Important
A Small Demo (Because MDX Makes It Easy)
This tiny example would’ve been very hard on any traditional blogging platform.
Finally, It All Clicked Together
After multiple resets, debugging loops, broken builds, and stubborn MDX errors… the blog is now:
- 🚀 Powered by Next.js App Router
- 🧩 Using MDX with rich components
- 🔗 Integrated with Hashnode
- 🧭 SEO-friendly
- 🎨 Fully customizable
- 🛠️ Structured like a real product
Shipped!
This rebuild gave me a platform that reflects how I explain, teach, and think.
What’s Next?
To continue improving the blog, I’m planning:
- Full-text search
- Reactions & comments
- AI summaries for each post
- A reading progress bar
- Code playgrounds via Sandpack
And of course — more long-form System Design and deep technical articles.
Thanks for reading — and welcome to the new, rebuilt version of my blog.