A New Theme for Everytheme

If you're an avid unixporn lurker like I am, you appreciate the beauty of customizing every little thing you possibly can when it comes to your desktop. Part of the feel of a personalized system comes from making all of your programs have matching colors. I've been using catppuccin, a soothing pastel color scheme; and while it's a great theme, I figured trying out niri would be a great opportunity to switch it up.

Searching for a new color home

After doing a bit of searching, I found Gogh, a collection of hundreds color schemes meant for your terminal. It also has the ability to change your terminal's color scheme on the fly, though I never used that feature. I used it to find a theme called Everblush.

Everblush

After settling on this theme, I applied it to my terminal and liked the look enough to commit to using it for everything.

So... About using it for everything...

The problem I soon ran into, was that once I applied the theme to my terminal and my code editors, that's all Everblush had to offer. I was stuck with having two themed windows, while everything else remains default. Not nice!

I was so used to catppuccin being an everytheme, having over 400 different ports to nearly every application or website you'd want. Now it feels like I can't move to any other color scheme, because it won't have that niche program I use once or twice. Specfically for me, that program was Chatterino, a desktop chat client for Twitch.

Enter Whiskers

Part of what makes catppuccin so nice, is that in addition to having your colors match, you can choose from several accent colors to make it that much more custom. With catppuccin's 14 different accent colors, and four different flavors, port creators often have to make 56 different variations of catppuccin themes to their software, with slightly different color variations.

Catppuccin's answer to this, is Whiskers, a custom-built templating engine that allows developers to generate each of the 56 varations programmatically, as long as your theme can be expressed in text. While not all of the themes built for catppuccin are built using Whiskers, many of them are.

Luckily for me, Chatterino was one of those themes, so I figured: If I can hijack the whiskers program with Everblush, I should be able to generate a whole suite of ports for Everblush, or whatever theme I want to switch to again in the future, without doing it all manually!

Hijacking Whiskers

As it turns out, Whiskers is an incredibly bespoke piece of software. All the flavors and accents are built directly into the command line arguments of the utility, meaning if I wanted to switch colors, I'd have to directly replace one of the flavors.

Finding What to Replace

Digging into the source code I was looking for a source-of-truth for where Whiskers gets it's colors from. And after looking at the project, for about two minutes, I found my answer:

[dependencies]
anyhow = "1.0.101"
base64 = "0.22.1"
catppuccin = { version = "2.6.0", features = ["css-colors", "serde"] }

Catppuccin has it's own cargo package for rust, and Whiskers imports the colors from that.

After looking at the cargo package, I found our source of truth! In a file named palette.json in the src folder, I could finally see where our colors were coming from:'

"rosewater": {
"name": "Rosewater",
"order": 0,
"hex": "#d68080",
"rgb": {
"r": 214,
"g": 128,
"b": 128
},
"hsl": {
"h": 0,
"s": 0.5119047619047621,
"l": 0.6705882352941177
},
"accent": true
},

That's... not great. If I wanted to change the color for rosewater, not only would I have to change the hex code. I'd also have to calculate the rgb values from the hex code, and I'd have to convert to HSL for each color, and change it.

Considering the length of the decimal places, I figured that this file probably got generated from somewhere, so I took a look into the palette repo, and sure enough, a script titled gen_palette.ts:

rosewater: {
name: "Rosewater",
object: new Color("#d68080"),
accent: true,
},

Finally!

So, if I want to generate a port for all my programs in Everblush colors, I have to change the hex codes in gen_palette.ts to generate a palette.json, which will be included in a custom version of the catppuccin rust crate, which will then be replaced as an import in Whiskers, which I'll then build into an executable to render a whisker template into a theme.

Confused? Don't blame you. It seems like way more effort than it's worth, but let's go for it anyways.

Theming Chatterino

First, I need to fill out all the colors. Since everblush only supplies standard ANSI colors, which only includes the ten base colors, I need to substitute some of my own colors for catppuccin's three shades of pink, four shades of blue, and several background color variations. To do this, I used w3schools' color picker, which lets you select a color, then generates several hue-shifted and brightness-shifted variants.

Then I replaced all of my colors in the gen_palette.ts file with the "latte" flavor, and ran a deno command to build my palette.json (This also let me generate some test PNGs so I could look at what the spread of colors looked like. In the case of my theme, here's what I came up with:

Not perfect, but I was pretty ready to just have a theme by this point, so I was willing to work with it.

Next I cloned a version of whiskers, and edited the Cargo.toml so that it imported a locally cloned version of the rust package instead of pulling one from crates.io:

[dependencies]
anyhow = "1.0.101"
base64 = "0.22.1"
-catppuccin = { version = "2.6.0", features = ["css-colors", "serde"] }
+catppuccin = { path = "./rust", features = ["css-colors", "serde"] }
clap = { version = "4.5.59", features = ["derive"] }
clap-stdin = "0.8.0"
detect-newline-style = "0.1.2"

In the ./rust directory, I cloned a version of the catppuccin rust package, and replaced it's palette.json with the one I'd generated previously.

Now, I can build Whiskers, and it should build an executable that can generate an everblush theme for any port I wish when I build a whisker template with the latte theme.

To do this, I cloned catppuccin's chatterino theme, and ran Whiskers with it's themes.json.tera file (tera is the templating engine whiskers uses under the hood.) After the theme's install instructions...

Not too bad!

What about the Web

Catppuccin also has several web ports for things like Youtube, Twitch, Chess.com etc. Those all seem to have one source-of-truth as well, in the form of a lib.less file. In theory the same thing should be possible. The current issue is that file includes "catppuccin-filters", which seem to allow port creators to change the color of images using css.

While this is great news for people in the catppuccin ecosystem, it makes it much harder to make a fully cohesive color theme if you're trying to break out of catppuccin. This PR that introduces CSS filters to whiskers gives us some hints as to how we might generate these CSS filters for arbitrary colors, but the process looks to be much more involved. than replacing a few hex codes, so I'll save this one for another time.

Final Words

If your thoughts while reading this were "that's a lot of work just to generate some colors," I'd agree with you! While this was definitely worth experimenting with to get the colors on my desktop to match, doing this for every color scheme I might want to use in the future is a lot of work. There's a lot of potential in generating templates to theme everything, and catppuccin seems to be a good starting point towards being able to bring your own colors, but building some tools to convert catppuccin themes into any theme would allow for making unique themes for all sorts of systems incredibly easy.