Why I Over-Engineered My Blog (And Why You Should Too)
Let’s be real - as developers, we have a chronic illness. We can’t just “write a blog post” on Medium or Dev.to. No, we look at those platforms—with their easy setup and built-in audiences—and think, “Damn, I could build a custom, strictly-typed, high-performance content pipeline in weeks that does exactly the same thing.”
So, I did.
This is the technical post-mortem of blog.itskushal.com. It’s fast, over-engineered, and it’s arguably the most disturbingly scalable way to host a few hundred words about AWS.
1. The Framework Wars: Why I Ghosted Next.js
Choosing a framework for a blog is like choosing a car for a 2-minute drive to the grocery store.
- Next.js is a heavy-duty semi-truck. It’s powerful, it can haul a whole enterprise-grade e-commerce site, but it’s overkill for a blog. Why am I forcing my readers to download a 70kb React runtime just to read a paragraph? That’s like making someone install an engine just to open a door.
- Hugo is like a vintage motorcycle. It’s terrifyingly fast because it’s written in Go, but if you want to change the headlight (add a custom React component), you’re going to spend three hours reading obscure documentation and questioning your life choices.
The Winner: Astro. Astro is the “Zero-JS by default” king. It ships plain HTML. If I want a fancy interactive component, I drop it in as an “Island,” and only then does the JavaScript ship. It’s the “lazy person’s optimization”—it’s fast because it literally does nothing until you tell it to.
2. The “Strict Schema” Obsession
I have trust issues. Specifically, I don’t trust “Past Kushal” to remember to add metadata to his Markdown files.
In my content/config.ts, I use Zod to create a strict schema. If I forget a pubDate, a wordCount, or a seoDescription, the build doesn’t just “look weird”—it explodes. It fails the build.
// If I mess this up, the CI/CD pipeline starts screaming at me.
const blog = defineCollection({
schema: z.object({
title: z.string(),
wordCount: z.number(), // No guessing allowed.
seoTitle: z.string(),
keywords: z.array(z.string()),
})
})
This is Plug n’ Play logic. The “engine” is separate from the “data.” I can swap out the whole UI, and as long as my Markdown matches this schema, everything just works. It’s like LEGO, but for people who like types.
3. Security: The “Ghost” Repository
Here’s a fun game: “Did I accidentally commit my private AWS architectural drafts to a public repo?”
To avoid playing this game, I separated my concerns like a surgeon:
- The Public Engine: The
src/folder (the code you see) is the logic. It’s public, it’s clean, and it contains zero secrets. - The Private Content: My actual
.mdfiles live in a completely separate, non-git-tracked repository.
During deployment, my CI/CD pipeline clones the private repo into the content/ folder. This means I can show off my clever code without accidentally leaking my “Draft: Why My Last Deployment Broke Everything” post. My vars.ts even keeps my CloudFront CDN domain (d12z4wd89i7ka.cloudfront.net) separate. It’s a “Look but don’t touch” architecture.
4. Subdomains vs. Subdirectories: The DevOps Flex
Why blog.itskushal.com and not itskushal.com/blog?
SEO nerds will tell you subdirectories are better for “link juice.” I told them to be quiet because Infrastructure Independence is cooler.
- Decoupling: My main site and my blog are two different apps. If I accidentally delete the CSS on my main portfolio, the blog stays beautiful.
- CDN Magic: I can set totally different caching rules for my blog assets on CloudFront without worrying about how it affects my main site’s API calls.
- Maintenance: I can upgrade Astro on the blog without checking if it breaks the React version on my main site. It’s basically microservices for people who like to sleep at night.
5. Clever (or Over-Engineered) Details
I couldn’t just have a list of posts. That’s boring.
The Zig-Zag Logic
In index.astro, I used a bitwise check (i & 1) to alternate the layout.
- Even post? Border on the right.
- Odd post? Extra padding on the left. It creates a visual rhythm that says, “I care about UI/UX,” even if I’m secretly just a backend engineer who likes math.
The SEO Machine
I’m obsessed with JSON-LD. Most people just use meta tags. I built ArticleJsonLD.astro to inject a massive JSON blob that tells Google exactly how many words are in the post and where my LinkedIn is. I’m essentially spoon-feeding the Google bot so it doesn’t have to work for a living.
<ArticleJsonLD
wordCount={post.data.wordCount}
tags={post.data.keywords}
/>
6. Comparison: Is this better than WordPress?
| Feature | My Over-Engineered Blog | WordPress |
|---|---|---|
| Speed | Blazing (Zero JS) | “Wait, let me load 42 plugins first” |
| Security | Private Repo Separation | One bad plugin away from a data breach |
| Cost | Basically $0 (Astro + Vercel/S3) | “Please pay $20/mo for a ‘Business’ plan” |
| Writing | Pure Markdown Bliss | A block editor that hates you |
Future-Plans: When the “Shelf” Gets Full
Right now, the blog is cozy. But eventually, the home page is going to look like a hoarder’s basement if I don’t add some organization.
I’m planning the next architectural phase:
- Hashtags: Totally seeing
#AWSor#DevOpsat the bottom of Dev.to and Medium posts isn’t my source of inspiration, trust. - Categorization: When I have 50+ posts, I don’t want someone hunting for an AWS post through 20 AI rants. I’ll be implementing dynamic routing for categories so you can filter the noise.
- Comments and Likes: I’m looking at a “Zero-JS” compatible interaction layer — likely Giscus (using GitHub Discussions as the backend) or a custom serverless function. I would like readers to engage without the site.
In Summary
Is this architecture overkill for a blog with two posts about Astro and AWS? Yes. But is it easy to maintain? Absolutely. It’s a “set it and forget it” system. The code is secure, the types are strict, the SEO is automated, and I never have to worry about a WordPress update breaking my site while I’m on vacation.
Now, if you’ll excuse me, I have to go spend 2 hours refactoring a CSS variable that no one will ever notice.