From d9a50f5430f80b420245c8e197bda3248a5624a2 Mon Sep 17 00:00:00 2001 From: Vivek Khurana <774414+vkhurana@users.noreply.github.com> Date: Sat, 11 Jul 2026 14:20:06 -0700 Subject: [PATCH] Add configurable default theme --- backend/main.py | 12 ++++++++++++ config.yaml | 5 ++++- documentation/ENVIRONMENT_VARIABLES.md | 4 +++- documentation/THEMES.md | 3 ++- frontend/app.js | 9 ++++++--- frontend/login.html | 3 +-- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/backend/main.py b/backend/main.py index 8b12b565..4ce5b495 100644 --- a/backend/main.py +++ b/backend/main.py @@ -260,6 +260,16 @@ def safe_error_message(error: Exception, user_message: str = "An error occurred" _autosave_raw = 1000 AUTOSAVE_DELAY_MS = max(250, min(60000, _autosave_raw)) +# Default UI theme for browsers that do not have a saved preference yet. +DEFAULT_THEME = str(config.get('ui', {}).get('default_theme', 'light')).strip() or 'light' +_themes_dir = Path(__file__).parent.parent / "themes" +if not get_theme_css(str(_themes_dir), DEFAULT_THEME): + logger.warning( + "Configured ui.default_theme %r was not found; falling back to 'light'", + DEFAULT_THEME, + ) + DEFAULT_THEME = 'light' + if DEMO_MODE: # Enable rate limiting for demo deployments limiter = Limiter(key_func=get_remote_address, default_limits=["200/hour"]) @@ -460,6 +470,7 @@ async def login_page(request: Request, error: str = None): # Inject app name throughout the login page app_name = config['app']['name'] content = content.replace('NoteDiscovery', app_name) + content = content.replace('__DEFAULT_THEME__', DEFAULT_THEME) return content @@ -520,6 +531,7 @@ async def get_config(): "demoMode": DEMO_MODE, # Expose demo mode flag to frontend "alreadyDonated": ALREADY_DONATED, # Hide support buttons if true "autosaveDelayMs": AUTOSAVE_DELAY_MS, # Debounce for note/drawing autosave + "defaultTheme": DEFAULT_THEME, # Used when the browser has no saved preference "authentication": { "enabled": config.get('authentication', {}).get('enabled', False) } diff --git a/config.yaml b/config.yaml index 770f7bbb..22d76a52 100644 --- a/config.yaml +++ b/config.yaml @@ -25,6 +25,10 @@ search: # User interface behavior ui: + # Theme used when a browser has not saved a theme preference yet. + # Use a theme ID from the themes directory (the CSS filename without .css). + default_theme: "light" + # Autosave debounce in milliseconds (applies to note typing and drawing autosave). # Lower = saves more often (more disk writes); higher = saves less often. # Override via the AUTOSAVE_DELAY_MS env var. Server clamps to 250-60000ms. @@ -59,4 +63,3 @@ authentication: # # Leave empty to disable API key authentication (only session auth works) api_key: "" - diff --git a/documentation/ENVIRONMENT_VARIABLES.md b/documentation/ENVIRONMENT_VARIABLES.md index 4eeed873..07d43bca 100644 --- a/documentation/ENVIRONMENT_VARIABLES.md +++ b/documentation/ENVIRONMENT_VARIABLES.md @@ -113,6 +113,9 @@ Equivalent in `config.yaml`: ```yaml ui: autosave_delay_ms: 5000 + # Used only when the browser has no saved theme preference. + # Set this to a CSS filename from themes/ without the .css suffix. + default_theme: "dracula" ``` ## 🎯 Configuration Priority @@ -178,4 +181,3 @@ When `debug: false` (recommended): --- **Pro Tip:** Use environment variables for **deployment-specific** settings, and `config.yaml` for **application defaults**. This keeps your configuration flexible and maintainable! 🎯 - diff --git a/documentation/THEMES.md b/documentation/THEMES.md index 13f1e267..da8a08b7 100644 --- a/documentation/THEMES.md +++ b/documentation/THEMES.md @@ -4,6 +4,8 @@ NoteDiscovery ships with **several built-in themes** (light and dark styles). Open **Settings → Theme** to browse what is available; your choice is saved automatically. +To choose the theme shown to new browsers, set `ui.default_theme` in `config.yaml` to a theme ID (the CSS filename without `.css`). A theme previously selected in the browser is stored in `localStorage` and takes priority over this default. + The set can grow over time—see the `themes/` folder in the repository for the current files. You can also add your own (see below) or override themes when self-hosting. ## Create Custom Themes @@ -143,4 +145,3 @@ All these CSS variables **must** be defined for your theme to work properly: --- 🎨 **Tip:** Use browser DevTools to experiment with colors in real-time before creating your theme! - diff --git a/frontend/app.js b/frontend/app.js index a520819d..7d6e3fb6 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -261,6 +261,7 @@ function noteApp() { demoMode: false, alreadyDonated: false, autosaveDelayMs: CONFIG.AUTOSAVE_DELAY, // hydrated from /api/config in loadConfig() + defaultTheme: 'light', notes: [], // True while /api/notes is in flight. Drives the "Loading your vault…" @@ -971,6 +972,9 @@ function noteApp() { if (Number.isFinite(config.autosaveDelayMs) && config.autosaveDelayMs > 0) { this.autosaveDelayMs = config.autosaveDelayMs; } + if (typeof config.defaultTheme === 'string' && config.defaultTheme) { + this.defaultTheme = config.defaultTheme; + } } catch (error) { console.error('Failed to load config:', error); } @@ -996,8 +1000,8 @@ function noteApp() { // Initialize theme system async initTheme() { - // Load saved theme preference from localStorage - const savedTheme = localStorage.getItem('noteDiscoveryTheme') || 'light'; + // A user's saved preference takes priority over the configured default. + const savedTheme = localStorage.getItem('noteDiscoveryTheme') || this.defaultTheme; this.currentTheme = savedTheme; await this.applyTheme(savedTheme); }, @@ -7731,4 +7735,3 @@ function noteApp() { } } } - diff --git a/frontend/login.html b/frontend/login.html index 8e0706e2..e7429db4 100644 --- a/frontend/login.html +++ b/frontend/login.html @@ -51,7 +51,7 @@ -