Version 0.1.0 just released! Check out the release notes from GitHub Releases

The Origin Story Behind Salty CSS, What It's Reacting to, and Who It Isn't For

Why Salty CSS Exists

Most of the other pages in this section explain how Salty CSS works — the compiler, the scoping model, the theming architecture. This one is the story behind all of that: why I built it, what it's reacting to, and — just as importantly — who it isn't for.

I'm Teemu, and Salty CSS is my project. After enough years of handcrafting design-led websites, I'd built up strong opinions about how styling should work — and I kept watching the ecosystem solve its problems in ways that cut against how I actually build sites. Part of this was wanting a tool that made the tradeoffs the way I'd make them. Part of it, honestly, was wanting to challenge myself to solve those problems directly instead of just being annoyed at them. So I did. The honest way to introduce the result is to tell you where it came from.

What shaped it

Two things set this off: a library I loved went away, and the ground underneath it shifted.

The library was Stitches — a huge inspiration and the original spark. (I'll name the specific debts I owe it and a few others below.) Its typed, variant-driven styled API was simply a joy to use, and when it was discontinued I went hunting for a replacement, worked through the alternatives, and eventually got stupid enough to build my own.

The ground shifting is the bigger half. React Server Components and server-first frameworks put real structural pressure on runtime CSS-in-JS: the old model leaned on React Context for theming and injected styles during render, and in a server-rendered world — where much of your tree never touches a client runtime — that becomes a liability. Astro pushed me especially hard. I love building with it, and native, zero-runtime styling that feels at home there is rare; a lot of what I wanted simply didn't exist, so I decided to make it.

The ecosystem's other answers mostly split two ways — static extraction that analyzes your code without running it, and atomic CSS that optimizes for the tiniest possible stylesheet. Both are legitimate, and keeping a build-time styling tool alive across a churning bundler ecosystem is genuinely hard work that I respect. They just weren't the directions I wanted to take. I wanted to keep the component-first styled API, execute style files rather than statically analyze them, and lean on native browser features for theming and overrides. The how lives on the other pages; this is only the why.

And a fair amount of it is simply me. Years of building sites a certain way — plus my own experiments, tests, and other open-source projects — added up to a fairly specific idea of how styling should feel. Salty is me chasing that idea instead of waiting for someone else to.

Where it came from

Salty CSS wasn't designed in the abstract. It grew out of my agency work building brand-led, design-heavy sites — and it's very much a side project of mine, not something tied to any particular company or client.

That environment shaped every important decision. A lot of that work is about crafting the nicest-looking atoms you can and seeing how they fit together — and trying to scope that kind of detail inside nested utility classes is genuinely painful. But raw CSS Modules weren't the answer either; I wanted type-safe, reusable components. The styled + TypeScript combination lets you build those atoms directly, with variants managed as typed props instead of hand-rolled class-name juggling.

The other pressure was dynamism. So much of this work is headless-CMS-driven: the same component or molecule has to handle many different cases through a single, consistent variant API. You can't hardcode every atom in advance. That demands absolute scoping and a typed, composable API. For that problem, styled plus good TypeScript is the only combination I've found that scales.

I built it for myself first and validated it on my own projects; the agency work is simply where the requirements came from. That's why Salty optimizes for high-fidelity, dynamic, design-led sites rather than for the leanest possible dashboard.

Who it's for — and who it isn't

I'd rather you pick the right tool than pick mine. So, plainly:

Salty CSS is a good fit if you're building design-led or highly dynamic sites, working server-first with React Server Components or Astro, missing the Stitches-style styled DX but unwilling to pay a runtime cost for it, or assembling your own design system from primitives rather than adopting a pre-baked UI kit.

It might not be the tool if you're building lean, repetitive, utilitarian dashboards where the absolute smallest stylesheet is the priority — atomic CSS might genuinely be the better fit there, and I'll happily say so. And if your team is deep in a legacy runtime CSS-in-JS codebase and not yet thinking in native-web-standards terms, I won't pretend migration is painless. It isn't, and I can't market it as easy. (AI assistants help a lot with the translation work these days, for what it's worth.)

What Salty CSS is right now

Some honesty about where things stand, so your expectations are calibrated.

Salty CSS is stable and already used to ship real sites, sitting at a pre-1.0 release. I'm not planning major breaking changes before V2 — reaching V1 is largely about committing to proper semantic versioning from there on. It's been in development since the autumn of 2024, mostly as a side project that gets the most attention when I have the most time for it. And I'm deliberately not in "I am the new industry standard" mode: the near-term goal is to ship V1, gather real users, and grow a community — maybe even new maintainers — heading into V2 and V3.

If you want a reason to start testing it even though it's largely a one-person project: it's used to build actual client websites, and real stakes keep it maintained — which is exactly the failure mode that kills so many open-source side projects. I keep it current because I depend on it too. Usually a fix just takes me cracking open a beer and getting it done.

Prior art & acknowledgments

Salty CSS didn't appear from nowhere, and it isn't trying to win a head-to-head fight with the libraries that shaped it. The honest thing is to name the work it stands on.

  • Stitches — the big one, and the closest thing this list has to a love note. Its variant model and the client-side developer experience it delivered were a genuine joy, and honestly its death is what sent me looking in the first place. It isn't the single reason Salty exists, but it's the feeling Salty will always be chasing.
  • Panda CSS taught me a lot about approaching server-first styling, and about how to evolve the already-brilliant API Stitches pioneered. You'll find its fingerprints in Salty on purpose — conventions like base, and treating text styles as templates, are adopted directly because they're good ideas.
  • Vanilla Extract is where the .css.ts execution model comes from. The idea that your styles can live in their own files — like the old days — but with the full power of TypeScript was an architectural benchmark.

Different tools draw the lines in different places; Salty draws them where I needed them drawn. If one of these fits your project better, use it with my blessing — they're excellent, and Salty is better for existing alongside them, spicing up the mix. 🧂

While I want to keep Salty CSS as a project with real goals, none of this has to feel like a corporate procurement decision to be taken super seriously. The name itself lives somewhere between an inside pun and the salt mines any CSS work can feel like for most web developers. So while I'm putting the cat on the table and telling bad jokes, what matters underneath is the engineering — the umami — that's the real reason anyone should reach for Salty CSS.


Where to go next