← All articles

How I revamped this site using Astro, Tailwind and Cloudflare

· 6 min read
🇮🇹This article is also available in Italian.Leggi in italiano →

If you read my post on why I had picked Grav CMS (in Italian), you already know how it ended: at some point I switched to Astro. Truth be told, I had already moved to Astro before writing this article, but the layout was bare — let’s be honest: it worked, but it was plain ugly. So I decided to start almost from scratch and rebuild everything, with a hand from Claude, this time with a sharper design idea and a few more tools to back it up.

This article is a tour of the tools and technologies I used, with the why behind each choice. No step-by-step tutorial: more of an overview for anyone curious about what’s under the hood.

Astro: static HTML, (almost) zero JavaScript

The heart of it all is Astro, a framework for building static sites. The idea that won me over is simple: by default Astro ships plain HTML, without sending the browser any JavaScript it doesn’t need. You add interactive code only where it’s actually required; what’s left is lightweight HTML that loads in a blink.

For a site like this one — mostly made of content you read — it’s the ideal choice: pages that weigh next to nothing, great response times and solid SEO behaviour, without any hand-tuning.

One detail I appreciate: Astro doesn’t force me into a single way of writing components and lets me use the syntax I prefer, while staying framework-agnostic. In short: little ceremony, plenty of control.

Tailwind for styling

For the visual side I use Tailwind CSS. Instead of writing separate stylesheets and inventing class names, I compose styles right in the markup using ready-made classes (flex, text-lg, mt-4, and so on).

Why does it click for me? Because the styling lives next to the element I’m building: no jumping back and forth between files, and no “dead” CSS that nobody dares touch anymore. At build time Tailwind keeps only the classes actually in use, so the final CSS is tiny. Light/dark mode is handled the same way, with a handful of dedicated classes.

Cloudflare Pages for hosting

The site is hosted on Cloudflare Pages. It works exactly how I’d expect a modern platform to: I git push, Cloudflare builds the project and publishes the result automatically, served from their global network. No servers to manage, HTTPS included, zero-downtime deploys in seconds.

There’s one aspect worth calling out, though: since this is a static site, in theory there’s no “server-side code”. But I still wanted a bit of dynamic behaviour, and this is where Pages Functions come in — small serverless functions running at the edge of Cloudflare’s network. I use them for two things:

  • the “Now Playing” widget on the About page, which asks Spotify what I’m listening to right now (or the last track I played);
  • a gate for staging: when needed, I can protect the staging version with authentication, so I can preview it before going to production, all without touching the public version.

Basically the best of both worlds: static and blazing fast by default, with a sprinkle of dynamism where it matters.

Content: Markdown + frontmatter

Luckily I was able to “recycle” every article published up to that point (including the ones I had written on the first version, the one based on GravCMS). The idea of steering clear of databases, CMSs, template engines, frameworks and external platforms turned out to be a winning one.

Every article is a plain Markdown file. At the top of the file, a frontmatter block describes the metadata: title, date, language, tags, description and little else. Convenient, standard, easy to move around: if I ever switched technology, the content would come with me — no painful migrations.

Astro lends an extra hand with Content Collections: a schema (validated with Zod) checks that every article has the right fields, in the right format. If I forget a required field or blow past the description’s character limit, I find out at build time, not after publishing. It’s a small safety net that brings peace of mind.

Bilingual IT/EN

I wanted to publish in both Italian and English, without duplicating pages and components for every article. The solution: Italian lives at the root (/, /blog/), English under /en/, but both languages draw from the same content, filtered by language.

The two versions of an article are separate files sharing a translation key: that’s the glue that lets me show the “also available in…” link and jump from one language to the other. An article can also exist in a single language: no obligation to translate everything.

What’s better than before

The previous version was functional, but bare. Rebuilding it, I added quite a few things that were missing before — and this is where much of the work (and the fun) lives:

  • Look and typography. A coherent design (the Atlas theme) and careful typography: Hanken Grotesk for body text, JetBrains Mono for code. Before, everything was very bare-bones (not to say plain ugly).
  • Light/dark theme. A light/dark toggle, with the right theme applied before the page paints: no classic white flash when opening the site in dark mode.
  • Tags on articles. Every article has its own tags, with dedicated pages to browse content by topic.
  • Reading time. Each article shows an estimated reading time in minutes.
  • Article outline. A small side table of contents with the section headings, to get your bearings and jump straight to the part you care about.
  • Latest posts on the homepage. The home page shows the most recent blog posts, so there’s always an entry point into the content.
  • RSS feeds. Links to the feeds (one for Italian, one for English) for anyone who prefers following the blog from an RSS reader.
  • Nice-looking code snippets. Code blocks coloured at build time (no JavaScript to load), with two coordinated light/dark themes, line numbers where they help and a “copy” button on every block.
  • “View in Markdown” button. Every article can also be opened in its raw Markdown form, for those who prefer it.
  • Contact form on the homepage. A form to write to me straight from the home page, sent through an external service (Web3Forms) with a small anti-spam honeypot. No backend to maintain just to receive a handful of emails.
  • “Uses” page. A dedicated page for the hardware, software and tools I use every day.
  • Automatic social images and no “jumps”. Every article gets its own 1200×630 preview generated automatically at build time, and images don’t cause layout shift while they load.

Wrapping up

As I said in the Grav article, I don’t believe there’s one tool that’s flat-out better than all the others: it depends on your needs (and on what you already know). For a personal site made mostly of content, this stack — Astro for static HTML, Tailwind for styling, Cloudflare Pages for hosting — gave me exactly what I was after: light, fast pages, Markdown content that stays mine, a touch of dynamism where needed and, at last, a layout I’m happy with.

If you’re thinking of rebuilding your site or starting one, I’d suggest taking a look at Astro: the learning curve is gentle and, once you find your rhythm, it’s genuinely a pleasure to use.

Erik D'Ercole
Erik D'Ercole
Web developer, sysadmin and DevOps. Partner and co-founder of Encodia.
RSS
Stay up to date
Subscribe to the RSS feed to get new articles in your favourite reader.
RSS feed ↗