feat(branding): render custom logo in the enclave switcher (LC-141) #161

Merged
nrupard merged 2 commits from feat/lc-141-sidebar-logo into main 2026-05-20 17:38:44 +02:00
Owner

Summary

Renders the custom branding logo (LC-96) inside the authenticated chrome. Follow-up to LC-96, which only showed the logo on the login page and admin preview.

Each enclave-switcher icon now shows the branding logo when one is set, falling back to the single-letter initial otherwise:

  • Global logo: the Home icon at the top of the switcher rail renders /branding/logo.
  • Per-enclave logo: each enclave icon renders /enclave/{id}/branding/logo (which itself falls back to the global logo).

How

  • SwitcherEntry grows logo_url: Option<String>, populated in load_switcher via db::branding::resolve. Because resolve falls back to the global row, a logo URL is set whenever the matching logo route would actually serve an image. This keeps the change to SwitcherEntry + load_switcher + the switcher partial, with no logo field threaded through every layout-extending page struct (the blocker noted on the issue).
  • The switcher template renders the logo inside a white rounded chip with object-contain padding, so a dark or edge-to-edge logo stays visible against the dark switcher rail (respects the safe-area note in the issue).

Tests

Two new cases in routes_branding.rs: the Home icon renders the global logo once set (and not before), and an active enclave's icon renders its own logo. just check, just test, just test-saas all green.

🤖 Generated with Claude Code

## Summary Renders the custom branding logo (LC-96) inside the authenticated chrome. Follow-up to LC-96, which only showed the logo on the login page and admin preview. Each enclave-switcher icon now shows the branding logo when one is set, falling back to the single-letter initial otherwise: - **Global logo**: the Home icon at the top of the switcher rail renders `/branding/logo`. - **Per-enclave logo**: each enclave icon renders `/enclave/{id}/branding/logo` (which itself falls back to the global logo). ## How - `SwitcherEntry` grows `logo_url: Option<String>`, populated in `load_switcher` via `db::branding::resolve`. Because `resolve` falls back to the global row, a logo URL is set whenever the matching logo route would actually serve an image. This keeps the change to `SwitcherEntry` + `load_switcher` + the switcher partial, with no logo field threaded through every layout-extending page struct (the blocker noted on the issue). - The switcher template renders the logo inside a white rounded chip with `object-contain` padding, so a dark or edge-to-edge logo stays visible against the dark switcher rail (respects the safe-area note in the issue). ## Tests Two new cases in `routes_branding.rs`: the Home icon renders the global logo once set (and not before), and an active enclave's icon renders its own logo. `just check`, `just test`, `just test-saas` all green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(branding): render custom logo in the enclave switcher (LC-141)
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 1m7s
d08273434e
LC-96 shipped per-scope branding but only rendered the logo on the login page and the admin preview. Render it in the authenticated chrome too: each enclave-switcher icon now shows the branding logo when one is set, falling back to the single-letter initial otherwise.

SwitcherEntry grows a logo_url: Option<String>, populated in load_switcher. The Home entry resolves the global branding (/branding/logo); each enclave entry resolves /enclave/{id}/branding/logo. Both use db::branding::resolve, which falls back to the global row, so a logo URL is set whenever the matching logo route would actually serve an image (the enclave route itself falls back to the global logo). This satisfies both the global brand area (the Home icon at the top of the rail) and the per-enclave logo (the active enclave's icon) without threading a logo field through every layout-extending page struct.

The switcher template renders the logo inside a white rounded chip with object-contain padding, so a dark or edge-to-edge logo stays visible against the dark switcher rail rather than disappearing into it.

Tests: two new cases in routes_branding.rs assert the Home icon renders the global logo once set (and not before), and that an active enclave's icon renders its own logo. just check, just test, and just test-saas all green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix(branding): cache-bust switcher logo URLs with asset_version (LC-141)
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 1m16s
efbac564a7
The logo route sets Cache-Control: max-age=86400, so without a version query the switcher icon would serve a stale logo for up to a day after an operator changes it. Append ?v={asset_version} to match the cache-bust the login page and admin preview already use; the logo refreshes on deploy. Tests updated to assert the versioned URL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nrupard deleted branch feat/lc-141-sidebar-logo 2026-05-20 17:38:45 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!161
No description provided.