Colophon · How this site is made

Specced by me, built with AI, served from a server I run.

I wrote the plan, designed every page on a canvas, and built the site with Claude Code as my pair. It runs on Astro and Node, reads its content live from MariaDB, and takes its look from Ryvanse, the design system I made for my streaming brand.

This page lists the parts, how they fit together, and who made the pieces I didn't.

The stack

Rendered on request, with very little JavaScript

Every page is built on the server when you ask for it, so a note I post shows up within half a minute, with no deploy.

The browser gets HTML, one stylesheet and a few small scripts: the theme switch, the ⌘K palette and the rearrangeable tiles on the home page.

Framework
Astro 7 in server mode with the Node adapter, TypeScript strict throughout.
Runtime
Node 24 run by Phusion Passenger on SERVERIZZ Grid, my company's cPanel hosting. A small startup file, app.cjs, loads the built server.
Data
MariaDB 10.11 through mysql2. Case studies, notes, link previews and images live there, and lists are cached for 30 seconds.
Markdown
marked renders each body on request, and Shiki colors code with CSS variables, so code blocks follow the theme.
Images
sharp makes the About headshot in three WebP sizes, saves link preview images and re-encodes uploads. Stored images are named by their SHA-256 hash and cached for a year.
Share cards
satori lays out the 1200 by 630 card for each note, and resvg turns it into a PNG on first request.
Styling
Plain CSS in cascade layers, with every color, size and radius coming from generated tokens. No CSS framework.
Motion
View Transitions across pages for page changes and the theme fade, with no JavaScript router. Reduced motion is respected everywhere.

How it was built

I wrote the spec. Claude Code wrote the first drafts.

This site went from a written plan to a live server in about a day. AI did a lot of the typing. The decisions, and the review of every change, were mine.

  1. 01 · Plan

    A written plan first

    I wrote the implementation plan in the Claude app: the pages, the stack, the design register and the launch date. Everything after it worked from that plan.

  2. 02 · Design

    Designed before it was coded

    The home page, About and Writing were each laid out on a Claude Design canvas in the Ryvanse system, in both themes, before any markup existed.

  3. 03 · Build

    Drafted by AI, reviewed by me

    Claude Code drafted the pages, the database layer, the publishing API and the deploy script. I checked each change against the plan and sent it back until it matched.

  4. 04 · Memory

    Rules that carry over

    My house rules live in an Obsidian vault the AI reads before each session and adds to after: US English, nothing touches production without me, and nothing is committed until I say so.

Build log · from git, Central Time

  1. Oct 26Day 0Implementation plan written. Home page and first case study designed on a canvas.
  2. Oct 2712:49 AMHome page, bento grid and deploy setup
  3. Oct 271:56 AMAbout page and page transitions
  4. Oct 272:26 AMWriting, the microblog, and the positioning opened to any industry
  5. Oct 272:43 AMCase studies and notes move into MariaDB, read live
  6. Oct 273:11 AMDeploys from cPanel's Git copy of the repository
  7. Oct 274:32 AMPublishing API for the companion apps
  8. Oct 274:59 AMPublisher for macOS, first commit
  9. Nov 9LaunchMVP launch

Design system

Ryvanse, turned down for work

Ryvanse is the identity I built for my gaming and streaming brand: a night ground, a five-color spectrum, hard offset shadows and a streak of terminal. Here it runs in a quieter register. The big display type appears once a page, pink marks the main action, and tiles only get the sticker shadow on hover.

The site never copies a color by hand. A small script turns the design system's token files into CSS before every build.

ryvanse.tokens.json

A copy of the Ryvanse tokens, untouched: colors, type, spacing, radii and shadows.

10 colors3 families

ry-bealey.tokens.json

The work register: semantic roles, each with a light and a dark value, plus long-form type.

18 roles × 2 themes

scripts/build-tokens.mjs

Runs before every dev server and build. Resolves each role to a Ryvanse color and fails loudly on a name it doesn't know.

Before dev and build

src/styles/tokens.css

Custom properties in their own cascade layer. Light is the default; dark swaps the semantic roles. Never edited by hand.

85 properties

  • Pink#ff3d9aPrimary action
  • Tangerine#ff8f2eWarnings
  • Lime#c8ff3cHUD and billing
  • Cyan#33e3e8Links and web
  • Violet#a77bffSupport and AI

In light mode the fills stay the same, and text in an accent switches to a darker ink that passes 4.5:1 on white.

Type

Three typefaces, all open source

Self-hosted as WOFF2, so no font request leaves this site. The share cards use WOFF copies of the same faces, because satori can't read WOFF2.

Display

Unbounded

Headlines and my name on the home page. Bold and Black.

© 2022 The Unbounded Project AuthorsSIL Open Font License 1.1

Text

Atkinson Hyperlegible

Everything you read. Drawn by the Braille Institute so letters stay distinct at small sizes. Regular, Italic and Bold.

© 2020 Braille Institute of AmericaSIL Open Font License 1.1

HUD and code

JetBrains Mono

Labels, readouts and code blocks. Medium and Bold.

© 2020 The JetBrains Mono Project AuthorsSIL Open Font License 1.1

Shipping

Code ships through Git. Words ship through an API.

Changing how the site works and posting to it are separate paths, so writing a note never needs a deploy, and a bad build never takes the site down.

Code · Deploy

A few minutes
  1. 1I push to GitHub.
  2. 2cPanel's Git Version Control pulls the change and runs the deploy script.
  3. 3The script installs with Node 24 and builds a copy of the site in a staging folder.
  4. 4It swaps the new build in and restarts Passenger.

SafeA failed build stops before the swap, so the live site stays as it was.

Words · Publish

Under 30 seconds
  1. 1I write a note or case study in Publisher on my Mac.
  2. 2Publisher sends it to the site's API with that device's own token.
  3. 3The API checks every field, saves to MariaDB, and unfurls any link.
  4. 4The next visitor sees it. The content cache only lasts 30 seconds.

No deployNothing in the repository changes when I post.

Companion app

Publisher, a Mac app made for this site

There's no web admin on this site. I publish from Publisher, a native SwiftUI app that talks to the site's publishing API. It lists, edits and creates notes and case studies, previews Markdown the way the site renders it, and uploads images.

An iPhone app for posting notes on the go joins it next, in the same Xcode project.

SwiftUImacOS 26Swift 6

  • Each device has its own token, kept in the Keychain. The server stores only a hash, and one device can be cut off without touching the others.
  • Every edit carries a version. If my other device changed the same note first, nothing is overwritten, and Publisher asks whether to apply my changes or reload.
  • Photos are re-encoded on upload, which strips location data.
  • Its icon is the site's spectrum chevron, one layer per band.

Credits

Made with other people's good work

Typefaces

  • Unbounded by the Unbounded Project Authors
  • Atkinson Hyperlegible by the Braille Institute
  • JetBrains Mono by JetBrains
  • Fontsource for the packages

Open source

  • Astro, Node.js and MariaDB
  • Shiki, marked and mysql2
  • satori, resvg and sharp

Hosting

  • SERVERIZZ Grid my company
  • cPanel and WHM
  • Phusion Passenger
  • CloudLinux

Built with

  • Claude Code for drafting code
  • Claude Design for the page canvases
  • Obsidian for the notes vault
  • Ryvanse my own design system

Source

The code for this site is public, README and all.

View on GitHub

Contact · reply by email

Say hello

Tell me what you're working on. I read everything and reply by email.

What's it about? Optional
0 / 2000
Rather not use a form?Message me on LinkedIn

I only use your details to reply. No mailing list.