had dev block, so spent an entire day making this theme

was it productive? no. but was it fun? also no. but at least I got to play around with neo brutalism, and that's something too, you know.

Aug 9, 2025

Featured image for had dev block, so spent an entire day making this theme

You know those days where you've got about a trillion things to do, and every single bullet on the planner feels so overwhelming you'd rather do literally anything else?

That was my day today. I've got a lot on my plate to be honest. I have to finish an implementation of some pretty complicated mathematics on a prototype I'm building to solve a pretty big algorithmic problem in eCommerce (aptly labelled the multi-armed bandit (MAB) problem, if you're curious). And I decided to make a theme instead.

You can download it too, by the way, if you're so inclined, I'll upload it further below. But heads up, it's very much a work in progress and has a lot of hard-coded custom elements. If you're not familiar with HTML and CSS, spare yourself the headache.

Anyway, as I was saying, today just wasn't that day.

Solving half of what is on my to-do for the stuff I'm actually working on (wouldn't you know it, half-assedly designing themes for a CMS does indeed not pay the bills) requires getting really technical with high-level mathematical theory like IF-IDF-scoring, Thompson Sampling ... you get it.

Not to mention, my implementation solves the aforementioned MAB by integrating several large-language-models (colloquially referred to as AI these days) from three different providers, doing everything from complex reasoning to 384-dimensional semantic embeddings of product tags. It's a mess. Today was not the day.

I'll be honest and admit I kind of ran out of patience halfway through and handed a lot of it over to ChatGPT-5, because I figured OpenAI had just released it and now was as good a time as any to see what it was capable of. In all honesty, not as bad as the internet hive mind made it out to be. Which, the internet hive mind considered, is no surprise to anybody.

So here we are. I decided to overhaul my agency page (linked below), which is written in pure HTML/CSS, and which I could not be bothered to integrate into the ghost platform for a multitude of reasons.

After I spent a few hours doing some housekeeping on the virtual private server keeping this blog (and most of my other self-hosted software) up and running, I spent the rest of the day trying to fit this theme to the new index page.

Ghost: The best open source blog & newsletter platform
Beautiful, modern publishing with email newsletters and paid subscriptions built-in. Used by Platformer, 404Media, Lever News, Tangle, The Browser, and thousands more.

This is a bookmark.

And wouldn't you know it came out pretty close, honestly. Well done, me. I'll be honest and admit I kind of ran out of patience halfway through and handed a lot of it over to ChatGPT-5, because I figured OpenAI had just released it and now was as good a time as any to see what it was capable of. In all honesty, not as bad as the internet hive mind made it out to be. Which, the internet hive mind considered, is no surprise to anybody.

I've thrown in a few of the content cards this Ghost CMS offers along the way, just so both you and I can see how they look with this new design. As you can see, it's an ongoing work in progress, I haven't really themed every single element of the editor's many features yet. Maybe one day.

This is a cta

it's pretty standard to be honest.

this button does nothing

Some very apparent quirks I've come across so far are:

  • I'm not really satisfied with the hamburger menu on mobile but for now it is what it is.
  • My theme breaks a few customizations in the admin panel. But since nobody but me (and you, if you're crazy enough to install this theme) will see it, I just ... can't be bothered right now. That'll be v1.0.

Anyway, I think that just about covers most of it. You can download the theme here, if you feel like it, but as I said in the intro, you're on your own with its weird quirks and hard-coded elements. You're welcome to send me an email if you trip over something, but I'm not sure when exactly I'll get around to fixing it, hopefully I'll be back to my actual work by tomorrow. Otherwise, submit a pull request.

To get a notification whenever a new update is released, sign up below. Don't worry, this mailing list is ONLY for updates. Find a changelog of rolling updates below the form.

Rolling changelog:


Changelog 0.9.0 | August 12, 2025

This one required significant patience. I decided to do a lot of critical housekeeping on the botched patchwork that came before it, since I have now decided to publish the theme for everyone to use. If you have visited my site these past couple days, you will have seen a lot of weird iterations of increasingly broken things until it suddenly worked.

  • Stylesheet rebuilt almost from scratch - CSS is now (somewhat) human readable, and a lot of classes have been standardized.
  • Ghost card_assets disabled - I was in a constant battle with them over permission to style certain cards. It was easier this way. Every card has now been rebuilt specifically to suit the theme.
  • Fonts now up to code - font loading is now being handled in a more efficient manner, manageable by all modern browsers. Fallbacks are implemented.
  • Cards massively improved - No more overflow off the DOM or bad padding on smaller devices. Cards now share standardized classes for width and box-shadows. (Video card remains broken.)
  • Consistent hero padding - The post hero is now no longer much wider than the content.
  • Consistent hero wrapping on mobile - Finally.
  • Theme toggle now overrides OS default - You can now view light mode even if your device is in dark mode, the design does not break.
  • Navigation works properly - Dropout menus now show up where and as they are expected to.
  • Earliest admin panel options being introduced (delayed until v1.0) - this began as a way to overrule custom fonts until disabled by the user, but has been expanded to allow for a bit more customization, like hero image positioning, custom lottie animations without code edits, card border radius control, related posts, and more.
  • QoL improvements - many smaller changes here and there mostly relevant for those who feel like digging into the code.

Changelog 0.8.0 | August 10, 2025

  • Fonts now load correctly - Massively changed the structure to allow fonts to load correctly. Does not support custom themes until I set up an admin panel option.
  • Blockquote card works in dark – Blockquotes now use tokenized surfaces (--paper/--surface) and are targeted in .gh-content (not legacy .kg-post), so they render correctly in dark mode. (screen.css)
  • Bookmark card fixed – Implemented full .kg-bookmark-card + .kg-bookmark-container styles and responsive stacking. (screen.css)
  • Font spacing on heroes – Tightened tracking & line-height and enforced weight (800) to prevent faux bold. (screen.css)
  • Inconsistent wrappers solved – .wrap and .gh-content.gh-canvas now share the same gutter tokens so nav/hero/content align to one grid. (screen.css)
  • All editor cards styled, neo-brutalist – Added/normalized styles for Callout, Toggle, Gallery, Header, File, Signup, Bookmark, Audio, Video, Product with shared --nb-* tokens. (screen.css)
  • Post hero now wraps on mobile, columns dropped – mobile media query stacks text above image using CSS order. (screen.css) (debugging this)
  • Footer padded away from bottom – Added spacing + border-top. (screen.css)
  • Sections fill viewport – .home-template .latest + .featured get min-height: calc(100svh - var(--nav-h)). (screen.css)
  • Overrides merged; file removed – Merged assets/css/overrides.css into screen.css, deleted the file, and ensured no template references to it remain. (screen.css, file removed)
  • Template bug in default.hbs fixed – Cleaned malformed class attribute on . (default.hbs)
  • Custom dark mode toggle compatible – Added body.dark { … } variable overrides so your toggle wins; left prefers-color-scheme as fallback. (screen.css)
  • Heading weight/spacing better – See (3); tightened tracking and disabled font-synthesis-weight to avoid fake bold. (screen.css)
  • Proper font families declared and implemented – Proper @font-face for Manrope & Sora, preferring woff2-variations and falling back to your TTFs. (screen.css)
  • Tracking tightened – Adjusted .h1 letter-spacing to ~-0.02em and post-hero line-height to 1.08. (screen.css)
  • Blockquote targets .gh-content – Selectors updated so editor/front-end behave consistently. (screen.css)
  • Dark mode variables – Implemented both OS (@media (prefers-color-scheme: dark)) and body.dark token sets. (screen.css)
  • Wrapper & canvas aligned – Shared tokens across .wrap & .gh-content.gh-canvas for uniform padding and max widths. (screen.css)
  • Template syntax sorted – Cleaned stray/truncated markup, normalized sections in post.hbs. (default.hbs, post.hbs)
  • nav.hbs truncated button repaired – Replaced the cut button with valid accessible markup (aria-expanded, inner bars). (partials/nav.hbs)
  • Copy button on code blocks – Added branded copy pill to .gh-content pre and .kg-code-card pre with robust clipboard fallback. (screen.css, assets/js/site.js)

More card tests:

💡
a callout
audio-thumbnail
a song
0:00
/126.64163265306122