Why I Over-Engineered My Blog (And Why You Should Too)

6 mins read

3 Mar 2026

Cover image

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:

  1. The Public Engine: The src/ folder (the code you see) is the logic. It’s public, it’s clean, and it contains zero secrets.
  2. The Private Content: My actual .md files 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?

FeatureMy Over-Engineered BlogWordPress
SpeedBlazing (Zero JS)“Wait, let me load 42 plugins first”
SecurityPrivate Repo SeparationOne bad plugin away from a data breach
CostBasically $0 (Astro + Vercel/S3)“Please pay $20/mo for a ‘Business’ plan”
WritingPure Markdown BlissA 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 #AWS or #DevOps at 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.