← Projects

Personal site

Live

This site. Astro and Tailwind, built from scratch and deployed to GitHub Pages via Actions, on a domain routed through Cloudflare.

  • Astro
  • Tailwind
  • GitHub Actions
  • Cloudflare
View on GitHub

My first public site, built from nothing rather than from a template - the point was to understand every piece of it.

What it is

A static site generated by Astro, styled with Tailwind, and deployed to GitHub Pages by a GitHub Actions workflow that runs on every push to main. No server, no database, no client-side JavaScript framework - the pages ship as plain HTML, between 3 and 10 KB each.

The only JavaScript on the whole site is a few hundred bytes: the tag filter on the project and blog lists, and a script that makes images in posts clickable. Both are written by hand and inlined at build time. There is no framework underneath them.

Content is files, not code

Every project and every post is a markdown file in a folder. Drop one in, and it appears - on its own page, on the index, in the RSS feed, in the sitemap. Nothing else gets edited.

What makes that safe rather than fragile is that the frontmatter is validated at build time. Each collection has a schema, so a missing summary or a misspelled field fails the build with a line number instead of quietly rendering an empty page. A date is parsed into a real date, not a string that happens to look like one.

The same idea covers a few things that would otherwise be manual work:

  • draft: true hides an entry in production while leaving it visible while I am writing it locally.
  • A post can declare a series and a part, which links the instalments together and orders them.
  • A project naming that same series lists its posts automatically, so the devlog on my game’s page builds itself from the posts themselves.
  • Tags become filter chips on the index pages, generated from whatever tags the files actually use.

The domain

It started on the free github.io address and now runs on lukajerman.dev, registered through Cloudflare. DNS points at GitHub Pages, and the certificate is issued by GitHub rather than proxied, which matters more than it sounds: a .dev domain is on the HSTS preload list, so browsers refuse to load it over plain HTTP at all. There is no “works but insecure” state to fall back on.

Cloudflare also handles mail. The address on my contact page is a routing alias that forwards to a personal inbox which appears nowhere on the site. If it ever collects too much spam, deleting the alias and creating another is the entire fix.

What I learned

  • How static hosting actually works: build once on a runner, upload the output, serve it from a CDN. Nothing is “running” the site.
  • Why a repo named username.github.io is worth having over a project repo - it serves from the root, so no base path to thread through every link.
  • Astro’s split between build-time frontmatter and the markup below it.
  • That a schema is worth writing even for a personal site. Most of the bugs I hit while building this were content mistakes, and the schema turned them into build failures instead of pages that looked subtly wrong.
  • That publishing an email address is a decision with consequences, and the time to think about it is before the first commit rather than after.