Golden wireframe UI panels assembled by hand on charcoal — a site built piece by piece

My site is mine, and yours should be yours

2 min read
astro design portfolio

Most personal sites are a theme with your name swapped in. This one is not.

Every page is an .astro file I wrote. The Notes feed is a content collection I shaped. The homepage intro, the resume layout, the side-project pages for Capsule and Daemi — hand-built markup, not slots in someone else’s template.

What “bespoke” means here

I do not mean “I reinvented the browser.” Astro ships the HTML. Tailwind helps with layout. Sharp is already in the tree, so I use it.

I mean the surface you actually touch was made for this site:

  • Theme: one dark charcoal palette as CSS custom properties. No theme toggle. No DaisyUI. Buttons are classes I wrote in theme.css.
  • Hover tooltips: a small component, dotted underline, nothing fancy. Used for Toronto’s maple leaf, name pronunciation, and terms I want to define without a glossary page.
  • OG images: SVG templated in the site palette, rasterized at build with sharp. No third-party card service.
  • Cover videos: some Notes cards play muted clips. A few run as a boomerang loop I implemented with requestAnimationFrame so they ping-pong instead of hard-cutting.
  • GitHub strip: contribution count and 52-week bars from a JSON file I refresh with a script, not an iframe widget.
  • Resume: modular sections in Astro, plus a PDF endpoint. Same content, two outputs.

There is no React on this site. There is no design system package. Icons that matter (CN Tower, maple leaf) are local SVG components.

Why bother

A theme gets you shipping tomorrow. It also gets you looking like everyone who picked the same theme.

I work on infrastructure and products for a living. This site is the one place I can keep the whole stack small enough to hold in my head: content model, SEO, OG cards, print styles, performance budget, the weird video loop. When something feels off, I change the component — not open an issue on a theme repo.

The stack is intentionally thin. Dependencies get a 7-day cooldown before I trust a new release. Favicons are sized on purpose. Critical CSS is inlined; the rest loads async. None of that is heroic. It is just ownership.

What I still use off the shelf

Astro. Tailwind. MDX. Vitest for a handful of pure helpers. Vercel for deploy. Lucide for generic icons. RSS and sitemap integrations so I do not hand-roll XML.

Bespoke is not “zero dependencies.” It is “every interaction and visual choice was made for this URL.”

If a piece does not belong here, it is not on the page.