# How to Customize Jellium-Desktop’s Appearance: Web UI and Native Window Theming

> Learn to easily customize Jellium-Desktop's appearance. Control web UI theming and native window title-bars with built-in styles, custom CSS, or config options.

- Repository: [Andrew Rabert/jellium-desktop](https://github.com/andrewrabert/jellium-desktop)
- Tags: how-to-guide
- Published: 2026-07-20

---

**Jellium-desktop’s appearance is controlled by a generated CSS theme for the jellyfin-web overlay and a Rust theme module that synchronizes the native window title-bar with the web UI’s `<meta name="theme-color">` tag, configurable through built-in stylesheets, custom CSS files, and the `titlebarThemeColor` config option.**

Jellium-desktop combines an embedded web interface with platform-native window decorations. You can customize jellium-desktop’s appearance by modifying both the web overlay and the native host window. In the `andrewrabert/jellium-desktop` repository, theming is split between the CEF-based UI layer and the OS-level window chrome.

## How the Jellium-Desktop Theme System Works

The application manages appearance through two distinct but connected layers.

### Web UI Layer

The web UI layer controls colors, fonts, and layout inside the overlay. In [`src/jfn_cef/src/resource.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/jfn_cef/src/resource.rs), a generated [`theme.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/theme.css) is served at `app://resources/theme.css`. This stylesheet defines CSS variables such as `--bg-color` and `--primary-color` that the jellyfin-web interface consumes, and the CEF resource handler injects it into the browser context.

### Native Window Layer

The native window layer handles platform-specific decorations including the title-bar and background color. The Rust theme module in [`src/color/src/theme.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/color/src/theme.rs) tracks the `<meta name="theme-color">` tag emitted by the web UI and forwards that color to the operating system. On Windows, the tint applies through DWM. On macOS, it dispatches to an Objective-C helper. On Wayland, it renders a solid-color placeholder while the overlay loads.

## Customizing the Web UI Appearance

You have three primary ways to customize the visual style of the embedded web interface.

### Edit the Built-In theme.css

The default stylesheet is produced by the `theme_css()` function and served through [`src/jfn_cef/src/resource.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/jfn_cef/src/resource.rs). Modifying this function or the generated file changes the default values of CSS variables like `--bg-color` and `--primary-color` across the overlay UI.

### Add a Custom Stylesheet

Drop a file named [`custom.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/custom.css) next to the Jellium binary, then reference it inside [`src/web/overlay.html`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/web/overlay.html) with a standard `<link>` tag. Rules in this file override the default theme because the browser loads them after [`theme.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/theme.css).

```html
<link rel="stylesheet" href="theme.css">
<link rel="stylesheet" href="custom.css">

```

### Change the Meta Theme Color at Runtime

The JavaScript shim in [`src/web/native-shim.js`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/web/native-shim.js) observes the `<meta name="theme-color">` tag. When a user selects a different theme, the shim calls `window.jmpNative.themeColor('#RRGGBB')`. That call crosses to the Rust side via the `ThemeColor` IPC and updates the native title-bar. You can also force a color manually from the browser console:

```javascript
// Force a light theme from the console
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff');

```

## Customizing the Native Window Appearance

The color shown in the window chrome is driven by the theme singleton in [`src/color/src/theme.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/color/src/theme.rs). It stores two callbacks:

- `on_set_theme_color(u32)` — applied only when the **`titlebarThemeColor`** config option is enabled.
- `on_set_bg_hex(*const c_char)` — always called to keep the mpv background synchronized with the web UI.

### Toggle Title-Bar Theming via Config

The configuration option **`titlebarThemeColor`** lives in [`src/config/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/config/src/lib.rs). When set to `true`, the title-bar follows the web UI’s theme color. When `false`, the title-bar remains a static color (default `#101010`).

```toml

# src/config/jellium.toml

titlebarThemeColor = true

```

The underlying Rust accessor looks like this:

```rust
pub fn titlebar_theme_color() -> bool { … }

```

### Platform-Specific Native Implementations

Each platform handles the forwarded color differently.

**Windows:** [`src/windows/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/windows/src/lib.rs) calls `win_set_theme_color(rgb)`, which loads `dwmapi.dll` to tint the DWM title-bar.

**macOS:** [`src/macos/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/macos/src/lib.rs) forwards the value to `macos_set_theme_color`, which dispatches to the main thread and invokes the Objective-C helper `apply_theme_color_to_window`.

**Wayland:** [`src/wayland/src/make_platform.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/wayland/src/make_platform.rs) implements `set_theme_color(&self, rgb)` and renders a solid-color placeholder while the overlay finishes loading.

## Practical Code Examples

### Override the Theme Color from Rust

If you are writing a plugin or patching the binary, you can force a specific title-bar color by calling the native callback directly:

```rust
use jfn_color::theme::jfn_theme_color_on_color;

// Force a dark title-bar
unsafe { jfn_theme_color_on_color(0x202020) };

```

### Link a Custom CSS File

Add the following line to [`src/web/overlay.html`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/web/overlay.html) after the default theme link:

```html
<link rel="stylesheet" href="custom.css">

```

Place your override rules in [`custom.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/custom.css) beside the Jellium executable.

### Toggle Native Sync in Config

Enable automatic window decoration theming by setting the config value:

```toml
titlebarThemeColor = true

```

Set it to `false` to lock the native title-bar to the static default.

## Summary

- Jellium-desktop splits theming between a web UI CSS layer and a native Rust color tracker.
- The embedded browser loads [`theme.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/theme.css) from [`src/jfn_cef/src/resource.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/jfn_cef/src/resource.rs), which defines CSS variables like `--bg-color` and `--primary-color`.
- You can override styles by editing the built-in CSS or adding a [`custom.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/custom.css) file linked from [`src/web/overlay.html`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/web/overlay.html).
- The native window color is managed by [`src/color/src/theme.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/color/src/theme.rs) and synchronized through the `ThemeColor` IPC when `titlebarThemeColor` is enabled.
- Platform-specific code in [`src/windows/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/windows/src/lib.rs), [`src/macos/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/macos/src/lib.rs), and [`src/wayland/src/make_platform.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/wayland/src/make_platform.rs) applies the color to the OS title-bar or background placeholder.

## Frequently Asked Questions

### How do I change the default theme color in jellium-desktop without editing Rust code?

Place a [`custom.css`](https://github.com/andrewrabert/jellium-desktop/blob/main/custom.css) file next to the Jellium binary and load it via a `<link>` tag in [`src/web/overlay.html`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/web/overlay.html). You can also change the `<meta name="theme-color">` content from JavaScript, which triggers the native shim to update the window decoration if `titlebarThemeColor` is enabled.

### What file controls the native title-bar color on Windows?

On Windows, [`src/windows/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/windows/src/lib.rs) defines `win_set_theme_color(rgb)`, which calls into `dwmapi.dll` to apply the tint to the DWM title-bar. The function receives its value from the theme singleton in [`src/color/src/theme.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/color/src/theme.rs).

### Can I prevent the native title-bar from following the web UI theme?

Yes. Set `titlebarThemeColor = false` in your configuration file. According to [`src/config/src/lib.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/config/src/lib.rs), this disables the `on_set_theme_color` callback and keeps the title-bar at its static default of `#101010`.

### Does the mpv background stay in sync with the theme automatically?

Yes. The `on_set_bg_hex(*const c_char)` callback in [`src/color/src/theme.rs`](https://github.com/andrewrabert/jellium-desktop/blob/main/src/color/src/theme.rs) is always invoked regardless of the `titlebarThemeColor` setting, ensuring the mpv background remains visually consistent with the web UI.