One-off tip

Support checkout

  1. 1 Choose amount
  2. 2 Payment
  3. 3 Thank you

Choose amount

Pick the level of support that feels right. You can keep it simple or enter a custom amount, then continue to secure payment.

Choose a one-off amount
How this blog was built
Cover image: Miniature construction scene — figures building with bricks and a wheelbarrow — Photo by Simone Dinoia on Unsplash
astro engineering meta

How this blog was built

A series on the technical and design decisions behind Sourcier

Published
30 March 2026
Read time
6 min read

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 toggleLive — CSS custom properties, localStorage persistence, and why not getting this right causes the flash of wrong theme.
  • Blog card and post hero designLive — typography hierarchy, cover image pipeline, the draft overlay.
  • Building a tag system in AstroLive — slug normalisation, publication-aware counts, the blog archive cloud, a concentric ring layout, paginated tag pages, and the post sidebar browser.
  • OpenGraph and SEO metadataLive — OG tags, Twitter Cards, canonical URLs, article metadata — all centralised in one place.
  • RSS in AstroLive — the @astrojs/rss package, draft filtering, autodiscovery.
  • Breadcrumb navigation with Schema.org markupLive — auto-generated crumbs, BreadcrumbList structured data, accessible aria-current.
  • A share widget with the Clipboard APILive — LinkedIn, Reddit, email, and copy-link with in-place feedback and a graceful clipboard fallback.
  • Page history and credits on a static blogLive — transparent revision logs, attribution as a first-class concern, and why both belong in the schema.
  • Deploying to NetlifyLivenetlify.toml, cache headers, serverless and edge functions, environment variables, and passcode-gated deploy previews.
  • Post notification emails with ResendLive — a Node.js script that reads frontmatter, builds an HTML email, and sends a broadcast to subscribers.
  • Scheduled publishingLive — 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 listLive — Resend’s Segments API, a serverless subscribe function, a shared form utility, honeypot spam protection, and a welcome email with Resend template support.
  • Comments on a static site26 May — Netlify Forms as a queue, HMAC-signed approve/delete links, three serverless functions, no database.
  • Mermaid diagrams28 May — bypassing Expressive Code, client-side rendering, theme-aware SVGs, a fullscreen lightbox.
  • Better code blocks2 June — syntax highlighting with Expressive Code, dual themes, line numbers, frames, and markers.
  • Sticky table of contents4 June — build-time heading extraction, IntersectionObserver active state.
  • Pagination9 June — clean URLs, skeleton placeholder cards, no client-side JavaScript.
  • A custom 404 page11 June — outlined text, a ghost effect, and why a dead end is worth designing properly.
  • Web analytics on a static Astro blog16 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 repository18 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 search19 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 Blobs23 June — serverless key-value storage, a Netlify Function API, and an optimistic UI with pop animations and localStorage deduplication.
  • Automating Dev.to cross-posting26 June — a Node.js script that reads your frontmatter, normalises tags, makes image URLs absolute, sets the canonical URL, and publishes in one command.
  • Reading times in Astro30 June — the reading-time npm package, flowing the value through blog cards and post pages, and fixing a lurking TypeScript JSX misconfiguration.
  • Setting up ESLint, Prettier, and Husky2 July — flat config linting for Astro and TypeScript, Prettier with Astro support, staged pre-commit checks, and build-time enforcement through Netlify.

That’s twenty-six posts rolling out through to early July. Some are short, covering 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?

Need help raising the bar?

I help teams improve engineering practice through hands-on delivery, pragmatic reviews, and mentoring. If you want a second pair of eyes or practical support, let's talk.

  • Engineering practice review
  • Hands-on delivery
  • Team mentoring
Get guidance

If this has been useful, you can back the writing with a one-off tip through a secure Stripe checkout.

Comments

Loading comments…

Leave a comment

Free · Practical · One email per post

Get practical engineering notes

One short email when a new article goes live. Useful if you are breaking into tech, growing as an engineer, or improving engineering practice on your team.