A desktop theme for GNOME with a dark, high-contrast aesthetic. Works on Ubuntu, Fedora, and other GNOME-based distributions.
Design tokens:
- Background:
#000000 - Accent/stroke:
#BDA7F0(lavender) - Highlight:
#FF7447(orange) - Surface:
#191919
Ubuntu / Debian
sudo apt update
sudo apt install -y git gnome-tweaks gnome-shell-extensionsFedora
sudo dnf install -y git gnome-tweaks gnome-extensions-appThe User Themes extension allows GNOME Shell to use custom themes. You need to enable it before the shell theme will apply.
Option A: Via Extensions app (recommended)
- Open the Extensions app (search for "Extensions" in your app launcher)
- Find User Themes in the list and toggle it ON
- If you don't see it, you may need to log out and back in first
Option B: Via extensions.gnome.org
- Visit extensions.gnome.org/extension/19/user-themes
- Click the toggle to install/enable it
- You may need to install the browser extension first if prompted
Option C: Via command line
gnome-extensions enable user-theme@gnome-shell-extensions.gcampax.github.comNote: The install script will attempt to enable User Themes automatically, but enabling it manually first ensures everything works smoothly.
git clone https://github.com/zachfeldman/gnome-prism.git
cd gnome-prism
./scripts/install.shThis restarts GNOME Shell and applies all theme changes.
- Wayland (Fedora and Ubuntu default): You must log out and back in
- X11 (fallback): You can also press
Alt+F2, typer, and press Enter
The install script automatically:
- Installs the GTK theme, Shell theme, and icon theme
- Downloads and installs the DM Mono font
- Sets your wallpaper and lock screen background
- Configures Dash to Panel for a bottom taskbar layout
- Applies Firefox and Vivaldi browser theming
- Applies Cursor/VS Code editor settings
You don't need to run any manual gsettings commands — the script handles everything.
./scripts/uninstall.shRemoves all installed gnome-prism files from user paths.
If a GNOME update resets your settings, re-run the install script. To re-apply manually:
gsettings set org.gnome.desktop.interface gtk-theme 'gnome-prism'
gsettings set org.gnome.shell.extensions.user-theme name 'gnome-prism'
gsettings set org.gnome.desktop.interface icon-theme 'gnome-prism'Two levels of Firefox theming are available:
- Theme add-on (
apps/firefox/gnome-prism-theme/) — install as a temporary extension in Firefox for toolbar/tab colors - userChrome.css — deeper UI customization:
./scripts/apply_firefox_userchrome.shThe install script writes apps/ghostty/gnome-prism to
~/.config/ghostty/themes/gnome-prism and sets theme = gnome-prism in an
existing ~/.config/ghostty/config. If you have no config yet, create one with:
theme = gnome-prism
Ghostty reads its config at startup; press ctrl+shift+, to reload it in place.
The colors are the same tokens as the Tilix scheme, so both terminals match.
./scripts/apply_vivaldi_theme.shInstalls a CSS mod to ~/.local/share/gnome-prism/vivaldi/ and opens Vivaldi's mod path settings.
The install script automatically applies apps/cursor/gnome-prism-settings.json to ~/.config/Cursor/User/settings.json, merging color theme, font, and color customizations while preserving existing settings. The same settings work for VS Code (~/.config/Code/User/settings.json).
The icon theme ships overrides for 100+ applications as SVG (scalable) and PNG (256×256), including:
- GNOME core apps (Files, Settings, Terminal, Calculator, Calendar, Text Editor, etc.)
- Browsers: Firefox, Chrome, Chromium, Vivaldi
- Terminals: GNOME Terminal, Tilix, Ptyxis, Ghostty
- Dev tools: Cursor, VS Code, Sublime Text, btop, htop
- Media: Spotify, VLC, Rhythmbox, Tenacity
- Productivity: LibreOffice (Writer, Calc, Impress, Draw), Evince, Shotwell
- Comms: Signal, Thunderbird
- Utilities: 1Password, Yubico Authenticator, Steam, Transmission, Remmina
- Framework-specific: Factory Reset Tools, Firmware Updater
Status/tray icon overrides: Wi-Fi, Bluetooth, audio volume, battery levels, brightness, night light, display.
Shell theme not applying:
- Make sure the User Themes extension is enabled (see Step 2 above)
- Log out and back in (required on Wayland)
- Run
gnome-extensions listand confirmuser-theme@gnome-shell-extensions.gcampax.github.comis listed
Theme not showing in GNOME Tweaks:
- Confirm install ran without
sudo - Check
~/.themes/gnome-prismand~/.local/share/themes/gnome-prismexist - Fully quit and reopen Tweaks, or log out/in
libadwaita apps (Files, Settings) not themed:
GTK4 theming relies on ~/.config/gtk-4.0/gtk.css. The install script writes this file. Re-run ./scripts/install.sh if it was removed.
Icons not updating for some apps:
Some apps (especially Snaps and Flatpaks) use hardcoded icon paths. The install script creates overrides for common apps, but you may need to log out/in or run gtk-update-icon-cache ~/.local/share/icons/gnome-prism to refresh.
Taskbar icons look misaligned (Fedora):
Re-run ./scripts/setup_bottom_panel.sh after logging in. The Dash to Panel extension needs to be fully loaded before the script can apply all settings.
Taskbar borders/icon alignment/clock font suddenly look wrong:
GNOME Shell's background extension updater can silently replace an already-installed Dash to Panel with a newer version, and a newer version can rename the CSS classes/JS structure the GNOME_PRISM_* overrides in scripts/setup_bottom_panel.sh target — breaking the taskbar styling with no error logged. setup_bottom_panel.sh pins Dash to Panel to a known-good version (DTP_PINNED_VERSION) and makes its extension directory read-only after patching, specifically to stop this. If it still happens (e.g. an old install predates this protection), re-run ./scripts/setup_bottom_panel.sh, then fully log out and back in — gnome-extensions disable/enable alone does not reliably reload an extension's code on Wayland.
GNOME Prism can optionally play a user-selected looping video on GNOME's
real, secure lock screen — a maintained fork of
Live Lock Screen, developed
in its own repository,
zachfeldman/LiveLockScreen
(UUID gnome-prism-screensaver@zachfeldman, AGPL-3.0 licensed — separate
from this repository's MIT license; see that repo's NOTICE.md).
This never replaces, weakens, or bypasses GNOME's authentication. Locking
is always performed by GNOME itself (Main.screenShield.lock()); the
extension only changes what's visually shown before you unlock. Interacting
with the keyboard, mouse, touchpad, or touchscreen always reveals GNOME's
normal password prompt.
- Plays your chosen video full-screen behind GNOME's lock dialog.
- Optionally rotate between videos in a folder instead of playing a single file — sequential (in order, resuming where it left off) or random, picking a new one each time the screensaver starts.
- Optional "clean" mode hides the clock, date, and notifications until you interact, so only the video shows initially.
- Start it immediately from Quick Settings ("Screensaver") or a configurable
keyboard shortcut (default
Super+Shift+L) — both just trigger a normal GNOME lock. - Everything else (loop, scaling, blur/grayscale/pause on prompt, disable-on-battery, keep-awake) is configurable in the extension's preferences.
Declared as GNOME Shell 46–50 in metadata.json, inherited from the upstream
Live Lock Screen project's own tested range. GNOME Prism has not
independently re-verified every one of those versions; if something breaks
on your version, clean mode and other GNOME-Shell-private-API-dependent
behavior are designed to fail safe back to normal locking (see Known
limitations below) rather than leaving you unable to unlock.
Requires GStreamer's good/bad/ugly plugins for broad video codec support.
The core elements the extension itself needs (playbin, appsink,
videoconvert, videoscale) are part of gstreamer-plugins-base, which is
essentially always already installed:
# Fedora
sudo dnf install gstreamer1-plugins-good gstreamer1-plugins-bad-free \
gstreamer1-plugins-ugly gstreamer1-plugins-bad-free-extras
# Ubuntu/Debian
sudo apt install gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-uglyscripts/install_screensaver.sh detects your distro and installs these
automatically, warning (never silently failing the whole install) if a
package isn't available for your release.
./scripts/install.sh --with-screensaver
# or, standalone:
./scripts/install_screensaver.shThis is opt-in only — it's never installed as part of a plain
./scripts/install.sh run, since it needs a user-selected video and extra
packages.
Log out and back in afterwards (required on Wayland — and after every update to the extension — for GNOME Shell to load it).
gnome-extensions prefs gnome-prism-screensaver@zachfeldmanPick a video file on the General page. GNOME Prism never copies this file anywhere; it stays exactly where you put it, and uninstalling never touches it.
- Quick Settings → "Screensaver" (toggle this off in preferences if you don't want it shown).
- Keyboard shortcut, default
Super+Shift+L(configurable, and can be disabled entirely in preferences). - Or just lock normally (
Super+L/loginctl lock-session) — the screensaver activates on any lock, not only via the actions above.
Open preferences (gnome-extensions prefs gnome-prism-screensaver@zachfeldman)
→ Screensaver page → set or clear the shortcut field, and toggle it on/off.
# Disable without removing:
gnome-extensions disable gnome-prism-screensaver@zachfeldman
# Fully remove (part of the normal uninstall; only removes this extension's
# own files, never touches other extensions or your video file):
./scripts/uninstall.sh- "Clean" mode (hiding the clock/date/notifications) and suppression of GNOME's own lock-transition "curtain" (so the video doesn't briefly go black right after locking) both rely on private GNOME Shell internals that can change between versions. If they're not found, both are silently skipped and the screensaver falls back to normal GNOME behavior — locking itself is never affected.
- Inherited from upstream: possible audio/video desync after suspend/wake, and possible clicking/crackling audio on pause/play.
- Video is decoded and rendered directly inside GNOME Shell's own process
(see the screensaver repo's
NOTICE.mdfor why); this avoids the cross-process/cross-GPU rendering issues the original window-based approach could hit, at the cost of a small extra CPU copy per frame to upload decoded frames into the Shell's compositor.
# Confirm the extension is installed and its state:
gnome-extensions info gnome-prism-screensaver@zachfeldman
# Check logs for extension/lock-related messages:
journalctl --user -b | grep -iE 'gnome-prism|screensaver|lock'
# Confirm the required GStreamer element is available:
gst-inspect-1.0 appsinkIf nothing plays, first confirm gst-inspect-1.0 appsink succeeds, then
confirm a video is selected in preferences, then check the journal for
gnome-prism-screensaver: log lines and any In-process pipeline error
messages.
This feature touches your real lock screen, so verify it end-to-end on a real GNOME session before relying on it:
- Install GNOME Prism with screensaver support.
- Log out and back in.
- Confirm GNOME Prism and Dash to Panel still work.
- Confirm ordinary
Super+Llocking works. - Confirm
loginctl lock-sessionworks. - Start the screensaver from Quick Settings.
- Confirm the video is visible immediately, with no black gap (and, if clean mode is enabled, without the clock/date/notifications overlaid).
- Interact with the keyboard or mouse.
- Confirm GNOME's real password prompt appears.
- Unlock successfully.
- Confirm the extension does not immediately return from unlock-dialog to the normal session.
- Test on AC and on battery.
- Disable the screensaver extension and confirm normal locking still works.
- Uninstall and confirm no lock-screen functionality is broken.
Contributions are welcome! If you have a bug report, feature request, or question, please file a GitHub issue.
- All public-facing names use
gnome-prism - libadwaita apps may ignore parts of custom GTK theming by design
- Best visual consistency comes from coordinating shell + GTK + icons + wallpaper
- This repository is MIT licensed. The optional screensaver extension lives in its own AGPL-3.0 repository (a Live Lock Screen derivative — see zachfeldman/LiveLockScreen), kept separate specifically to avoid mixing licenses in one repo.
- prism-port: the prism palette and conventions for a tiling window manager environment (mango, foot, Neovim, fuzzel, mako, and others)
- Gaurav Singh — theme design
- Ross Jernigan (@bonkrat) — design input and guidance
- Zach Feldman (@zachfeldman) — implementation, vibe-coded this into a real Ubuntu theme
- Sam Fleming (@SamPlaysKeys) — added Fedora-specific features, as well as misc fixes




0 comments
log in to comment.