Building a Brutalist UI System with Tailwind CSS v4
How I designed and built the component system for this site — hard borders, monospace type, no shadows that lie about depth.
December 3, 2024
·2 min read
Brutalist design gets misused a lot. People slap Comic Sans on a black background and call it brutalist. Real brutalist UI is about honesty — surfaces that look like what they are, borders that don't pretend to be depth.
Here's how I built the system for this site.
The design tokens
Everything flows from CSS custom properties defined in globals.css:
:root {
--bg: #f5f1e8; /* warm off-white, not pure white */
--fg: #0a0a0a; /* near-black */
--muted: #6b6b6b; /* secondary text */
--border: #0a0a0a; /* borders match text — intentional */
--accent: #00d26a; /* the only color that isn't neutral */
--surface: #ffffff; /* elevated surfaces */
}The key decision: --border equals --fg. In most design systems borders are lighter than text, which creates a visual hierarchy. Here they're the same. It makes the UI feel more constructed, like type on paper.
The card component
The hard shadow is the signature element:
function Card({ interactive, children }: CardProps) {
return (
<div
className={cn(
'border-2 border-[var(--border)] bg-[var(--surface)]',
'shadow-[6px_6px_0_0_var(--border)]',
interactive && [
'cursor-pointer transition-all duration-100',
'hover:shadow-[2px_2px_0_0_var(--border)]',
'hover:translate-x-1 hover:translate-y-1',
]
)}
>
{children}
</div>
)
}The interactive version physically moves when you hover — the shadow shrinks as the element shifts. It's tactile without being skeuomorphic. The button presses, but it doesn't glow or blur.
Typography
Two fonts, both with a purpose:
- Space Grotesk — headings and display text. Slightly quirky, geometric. The
gandahave personality. - JetBrains Mono — all body text, labels, UI chrome. Not just code.
Using a monospace font for everything UI-related is the move that unifies the system. Every label, every nav link, every button reads with the same rhythm. The design becomes the content.
The accent color
#00D26A — electric green. There's exactly one accent color. It appears on:
- Interactive hover states
- Status badges
- The availability pulse in the footer
- Code syntax (via rehype-pretty-code)
- Text selections (
::selection)
One accent color makes every use of it feel meaningful. When something is green, it means something.
What I'd do differently
I almost added a secondary accent for warnings/errors. I'm glad I didn't. The --danger: #FF3B3B token exists but appears nowhere in the current design. Constraints are clarifying.
I'd also reconsider the border weight on mobile. border-2 is right for desktop, but on small screens the cards feel heavy. A responsive border might be worth the CSS overhead.
Takeaway
The system works because it makes decisions. No shadows that pretend to be lighting. No colors that exist for variety. Every element does exactly one thing and looks exactly like that thing. That's the honest part.