You want a blog. Free. No servers to babysit. No databases to patch. No WordPress drama.
As an Indian I love to save money — and hosting bills are the first thing I optimise.
So I did what any cheap developer does. I built a markdown blog with Next.js, dumped it on Vercel, and called it a day. Write a .md file, git push, Vercel builds it, the world reads it. Zero hosting cost, full git history, no CMS to manage. Life was good.
Then it got boring.
The problem with too static
Static is great until it isn't.
I didn't want a headless CMS — that's just another service to host and pay for. I didn't want WordPress — ISR on every run, managing a separate instance, and all the vulnerabilities that come free with it. I wanted to keep the simplicity of markdown and git. But I also wanted the blog to do things. Embed widgets. Run demos. Let readers play with ideas inline instead of reading about them.
So this post is the proof of concept. The canary in the coal mine. The thing I built to see if I could have my cake and eat it too.
How I made markdown less boring
The trick is stupidly simple. Blog posts are still plain .md files. No MDX. No build-time compilation. But with rehype-raw and a tiny component registry, I can drop any React component directly into markdown using standard HTML-ish tag syntax.
The tag below in this file is literally just:
::counter-demo{initial=0 label="Interactions"}
And here it is, alive and clickable:
Interactions
0
Props are just attributes. Start at a different number:
Starting from 10
10
That's it. One line in a markdown file. No MDX wrangler. No special build step.
Adding your own components
Three steps. That's the whole system.
- ›Create
components/mdx/interactive/YourComponent.tsxwith'use client'at the top - ›Add one line to
components/mdx/interactive/registry.ts:TS'your-component': YourComponent, - ›Use it in any post:
TEXT
::your-component{prop="value"}
Props always arrive as strings — cast inside the component as needed. The registry does the rest.
What this unlocks
This isn't just about buttons and counters. Once a post can run code, the ceiling disappears.
- ›Code playgrounds — run snippets inline, let readers tweak and see
- ›Algorithm visualizers — step through sorting, pathfinding, whatever you're explaining
- ›Config builders — generate config files with live preview as you toggle options
- ›Polls / reactions — lightweight engagement without a backend
- ›Data charts — recharts is already in the project, drop a chart anywhere
- ›Quizzes — test reader understanding mid-article, make learning sticky
I haven't built all of these yet. But the plumbing is there. The markdown file stays simple. The components do the heavy lifting.
Why this matters
For me this is about keeping the workflow I love — git, markdown, free hosting — without accepting a dead page as the price. The web was supposed to be interactive. My blog should be too.
If you want this exact markdown-based blog setup for Next.js, send me a DM on my socials and I'll open-source it on GitHub. It's nothing fancy, but it might save you an afternoon of yak shaving.
Feel free to connect/reach out if you have questions or want to argue about static vs dynamic blogs.