How to Customize Invidious Appearance: Themes, CSS, and User Preferences
You can customize Invidious appearance by toggling the built-in dark/light theme, modifying user preferences like thin_mode and player_style, or editing the static CSS files in assets/css/ to apply global style overrides.
The Invidious frontend offers multiple integration points for visual customization, ranging from simple user toggles to server-wide CSS modifications. Whether you run a private instance or use a public one, you can adjust the look and feel through the preference system or direct asset editing according to the iv-org/invidious source code.
1. Switch Between Dark and Light Themes
Using the UI Toggle
The fastest way to customize Invidious appearance is the theme toggle button (sun/moon icon) in the header. Clicking it sends a GET request to the /toggle_theme endpoint, which flips the dark_mode value stored in your preferences.
In src/invidious/routes/preferences.cr (lines 35-73), the toggle_theme route handles this by inverting the current value between "dark" and "light" and persisting it to either the database (for logged-in users) or the PREFS cookie (for anonymous sessions).
Programmatic Theme Switching
You can automate theme changes using the HTTP endpoint. This is useful for scripts or browser extensions:
curl -b cookie.txt -c cookie.txt "https://invidious.example.com/toggle_theme?redirect=false"
The redirect=false parameter returns an empty JSON response {} instead of a page redirect. When a request includes the query parameter dark_mode, the value passes through convert_theme in src/invidious/user/converters.cr, which maps "true" to "dark" and "false" to "light".
Setting a Default Theme for All Users
Instance administrators can set a site-wide default by editing config/config.yml. Add or modify the dark_mode entry under default_user_preferences:
default_user_preferences:
dark_mode: "dark" # or "light"
After restarting the Invidious service, new sessions without existing preferences inherit this default. The configuration structure is defined in src/invidious/config.cr (lines 30-33).
2. Modify Layout and Player Preferences
Key Appearance Preferences
Beyond the binary theme option, the Preferences struct in src/invidious/user/preferences.cr exposes several UI customization fields:
thin_mode– Switches to a compact, density-optimized layout (handled insrc/invidious/routes/preferences.cr, lines 124-128)player_style– Selects between"invidious"or"youtube"player chrome (lines 60-61)quality/quality_dash– Sets default resolution selectors (lines 63-68)extend_desc– Expands video descriptions by default (lines 72-75)vr_mode– Enables VR/360° interface elements (lines 76-78)show_nick– Displays your nickname on comments (lines 84-86)
Updating Preferences via API
These values are submitted through the /preferences page form, which POSTs to PreferencesRoute.update. The route reconstructs the Preferences object using Preferences.from_json (around line 48 of preferences.cr).
To update programmatically:
curl -b cookies.txt -c cookies.txt \
-X POST "https://invidious.example.com/preferences" \
-d "thin_mode=on" \
-d "player_style=invidious"
3. Apply Custom CSS Overrides
Editing Static CSS Files
For global visual changes affecting all users, modify the stylesheets in the assets/css/ directory:
| File | Purpose |
|---|---|
assets/css/default.css |
Global colors, typography, and spacing |
assets/css/player.css |
Video player controls and overlays |
assets/css/search.css |
Search results layout and grid |
assets/css/quality-selector.css |
Quality dropdown styling |
Invidious serves these files directly from the filesystem, so changes apply immediately after saving (though browser cache clearing may be necessary).
Common CSS Customization Examples
Change the primary accent color by adding rules to assets/css/default.css:
a, .btn-primary, .header a {
color: #ff6600 !important;
}
Darken the video player background in assets/css/player.css:
.video-player {
background-color: #111 !important;
}
Unlike preference-based changes, CSS modifications require server filesystem access and affect all visitors to the instance.
4. Browser Extension Methods for Personal Styling
If you cannot modify server files (using a public instance), use browser extensions to inject custom CSS locally:
- Stylus – Create a style matching
https://invidious.example.com/*and add your rules - Firefox userContent.css – Place custom CSS in your Firefox profile's
chrome/userContent.css
This method respects user privacy and works on any Invidious instance without administrative access.
Summary
- Theme switching uses the
/toggle_themeendpoint ordefault_user_preferences.dark_modeinconfig/config.ymlto set defaults insrc/invidious/config.cr - Layout preferences like
thin_modeandplayer_styleare stored in thePreferencesstruct and updated via POST to/preferences - Global CSS changes require editing files in
assets/css/such asdefault.cssandplayer.css - Personal styling can be achieved through browser extensions like Stylus when server access is unavailable
Frequently Asked Questions
How do I set a default dark theme for all users on my Invidious instance?
Edit config/config.yml and add dark_mode: "dark" under the default_user_preferences section, then restart the Invidious service. This writes the default into the configuration struct defined in src/invidious/config.cr and applies to all new sessions without existing cookies.
Can I customize Invidious appearance without an account?
Yes. Anonymous preferences are stored in the PREFS cookie. You can toggle themes via the UI button or curl commands with cookie persistence. For advanced styling, use browser extensions like Stylus to inject CSS locally without needing server access.
Where is the theme preference stored in the source code?
The dark_mode property lives in the Preferences struct in src/invidious/user/preferences.cr. The toggle logic resides in src/invidious/routes/preferences.cr (lines 35-73), and query parameter conversion happens in src/invidious/user/converters.cr.
Why don't my CSS changes show up immediately?
Invidious serves static CSS files directly from assets/css/, so changes should reflect after a browser cache refresh (Ctrl+F5 or Cmd+Shift+R). If you compiled assets into the binary, you must rebuild or restart the service to pick up modifications.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →