From a32255e110264d106095612be9dbc943ba80129d Mon Sep 17 00:00:00 2001 From: JingleManSweep Date: Mon, 9 Mar 2026 17:30:40 +0000 Subject: [PATCH] fix: support monochrome custom logos via logo-invert.svg filename convention (#141) Custom logos were hardcoded as full-color, making white/monochrome logos invisible in light mode. Adds logo-invert.svg as a higher-priority candidate that enables the brightness filter in light mode. --- AGENTS.md | 3 ++- README.md | 8 +++++--- .../media/images/{logo_ipnet.svg => logo-invert.svg} | 0 src/meshcore_hub/web/app.py | 10 ++++++---- 4 files changed, 13 insertions(+), 8 deletions(-) rename example/content/media/images/{logo_ipnet.svg => logo-invert.svg} (100%) diff --git a/AGENTS.md b/AGENTS.md index e7edc97..332aa20 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -640,7 +640,8 @@ ${CONTENT_HOME}/ │ └── getting-started.md # Example: Getting Started (/pages/getting-started) └── media/ # Custom media files └── images/ - └── logo.svg # Custom logo (replaces default favicon and navbar/home logo) + ├── logo.svg # Full-color custom logo (default) + └── logo-invert.svg # Monochrome custom logo (darkened in light mode) ``` Pages use YAML frontmatter for metadata: diff --git a/README.md b/README.md index 6f9615b..2a9b27e 100644 --- a/README.md +++ b/README.md @@ -480,15 +480,17 @@ Control which pages are visible in the web dashboard. Disabled features are full The web dashboard supports custom content including markdown pages and media files. Content is organized in subdirectories: -Custom logo note: -- If a custom logo file is present, the UI keeps its original colors in both light/dark themes (no automatic light-mode darkening). +Custom logo options: +- `logo.svg` — full-color logo, displayed as-is in both themes (no automatic darkening) +- `logo-invert.svg` — monochrome/two-tone logo, automatically darkened in light mode for visibility ``` content/ ├── pages/ # Custom markdown pages │ └── about.md └── media/ # Custom media files └── images/ - └── logo.svg # Custom logo (replaces favicon and navbar/home logo) + ├── logo.svg # Full-color custom logo (default) + └── logo-invert.svg # Monochrome custom logo (darkened in light mode) ``` **Setup:** diff --git a/example/content/media/images/logo_ipnet.svg b/example/content/media/images/logo-invert.svg similarity index 100% rename from example/content/media/images/logo_ipnet.svg rename to example/content/media/images/logo-invert.svg diff --git a/src/meshcore_hub/web/app.py b/src/meshcore_hub/web/app.py index 6316d91..0a54ab6 100644 --- a/src/meshcore_hub/web/app.py +++ b/src/meshcore_hub/web/app.py @@ -56,13 +56,15 @@ def _resolve_logo(media_home: Path) -> tuple[str, bool, Path | None]: Returns: tuple of (logo_url, invert_in_light_mode, resolved_path) """ - custom_logo_candidates = (("logo.svg", "/media/images/logo.svg"),) - for filename, url in custom_logo_candidates: + custom_logo_candidates = ( + ("logo-invert.svg", "/media/images/logo-invert.svg", True), + ("logo.svg", "/media/images/logo.svg", False), + ) + for filename, url, invert_in_light_mode in custom_logo_candidates: path = media_home / "images" / filename if path.exists(): - # Custom logos are assumed to be full-color and should not be darkened. cache_buster = int(path.stat().st_mtime) - return f"{url}?v={cache_buster}", False, path + return f"{url}?v={cache_buster}", invert_in_light_mode, path # Default packaged logo is monochrome and needs darkening in light mode. return "/static/img/logo.svg", True, None