How this blog was built

How this blog was built

A series on the technical and design decisions behind Sourcier

By Roger Rajaratnam 30 March 2026

When I launched this blog last week I wrote a post called I Should Start a Blog — the short version of why I’d stopped putting it off. Part of what I mentioned there was that building the site itself had been an enjoyable project: a proper excuse to use Astro in earnest, deploy serverless functions on Netlify, wire up email delivery through Resend.

What I didn’t write about was how any of that actually works.

The series

I’ve decided to fix that. Starting today, I’m publishing a series of posts that document how this blog was built — the technical decisions, the design choices, the problems that needed solving and how I solved them.

It is, admittedly, a slightly self-referential thing to write a blog about the blog. But I think there’s genuine value in it. These are patterns and decisions that come up on almost any content-driven site. The answers I landed on aren’t unique to this project — they’re worth writing up properly.

The series covers:

  • Choosing the tech stackLive — the full stack decision: Astro for static output and content collections, Bulma for a no-runtime CSS foundation, Netlify for hosting and serverless functions, Font Awesome, Resend, and the other tools that hold it together.
  • Typed content collectionsLive — Zod schemas, build-time validation, the draft flag pattern, and what typed frontmatter actually buys you.
  • Dark/light theme toggle7 April — CSS custom properties, localStorage persistence, and why not getting this right causes the flash of wrong theme.
  • Blog card and post hero design9 April — typography hierarchy, cover image pipeline, the draft overlay.
  • A tag system with weighted clouds14 April — slug normalisation, the three-tier cloud, a concentric ring layout, paginated tag pages.
  • OpenGraph and SEO metadata16 April — OG tags, Twitter Cards, canonical URLs, article metadata — all centralised in one place.
  • RSS in Astro21 April — the @astrojs/rss package, draft filtering, autodiscovery.
  • Breadcrumb navigation with Schema.org markup23 April — auto-generated crumbs, BreadcrumbList structured data, accessible aria-current.
  • A share widget with the Clipboard API28 April — LinkedIn, email, copy-link with in-place feedback.
  • Page history and credits30 April — transparent revision logs and why attribution is a first-class concern.
  • Deploying to Netlify5 Maynetlify.toml, functions, environment variables, deploy previews.
  • Post notification emails with Resend7 May — a Node.js script that reads frontmatter, builds an HTML email, and sends a broadcast to subscribers.
  • Scheduled publishing12 May — a isPublished() helper that gates on both draft status and pubDate, a Netlify scheduled function, and a daily build hook so future-dated posts go live automatically.
  • Adding a mailing list14 May — Resend’s Segments API, a serverless subscribe function, honeypot spam protection.
  • Comments on a static site19 May — Netlify Forms as a queue, HMAC-signed approve/delete links, three serverless functions, no database.
  • Mermaid diagrams21 May — bypassing Expressive Code, client-side rendering, theme-aware SVGs, a fullscreen lightbox.
  • Better code blocks26 May — syntax highlighting with Expressive Code, dual themes, line numbers, frames, and markers.
  • Sticky table of contents28 May — build-time heading extraction, IntersectionObserver active state.
  • Pagination2 June — clean URLs, skeleton placeholder cards, no client-side JavaScript.
  • A custom 404 page4 June — outlined text, a ghost effect, and why a dead end is worth designing properly.
  • Web analytics on a static Astro blog9 June — picking PostHog from the free options, loading the snippet only in production, and wiring up credentials with Netlify environment variables.
  • Moving blog content to a private repository11 June — splitting Markdown content into a private GitHub repo, a build-time clone with a fine-grained token, and a GitHub Actions workflow to trigger deploys on content changes.
  • Adding search12 June — Pagefind for static site search, a command-palette header modal with keyboard navigation, and the non-obvious problems with meta elements, asset hashing, and scoped styles.
  • Emoji reactions with Netlify Blobs16 June — serverless key-value storage, a Netlify Function API, and an optimistic UI with pop animations and localStorage deduplication.
  • Automating Dev.to cross-posting19 June — a Node.js script that reads your frontmatter, normalises tags, makes image URLs absolute, sets the canonical URL, and publishes in one command.

That’s twenty-five posts rolling out through to late June. Some are short — a single technique worth documenting cleanly. Others go deeper. All of them are grounded in code that actually runs on this site right now. Subscribe below and you’ll get each one the morning it drops — no noise, just the article.

Why write this at all

Two reasons.

The first is that documenting things properly forces me to understand them better. When I built the comment system I had a rough sense of how the HMAC signing worked. Writing it up properly — in a way that another engineer could follow — required me to be precise about the details. Every single post in this series has taught me something about my own implementation.

The second is that I genuinely couldn’t find a comprehensive write-up for most of these patterns when I was building them. There are fragments — a hint in the Astro docs, a Stack Overflow answer that’s half-right, a GitHub issue with a workaround. Writing them up in one place, with enough context to be useful, seems worth doing.

Working on something similar?

If you’re building a content site, a developer blog, or anything along these lines and would rather not figure it all out from scratch — I’m available for consulting. I can help with architecture decisions, implementation, or a straightforward code review.

Get in touch via the contact page and tell me what you’re working on.

Free · No spam · Unsubscribe any time

Get new posts in your inbox

When the next article drops, I'll send a short note — a link and a summary, nothing else. One email per post.

Did you find this useful?

Comments

Loading comments…

Leave a comment