Skip to content

fix(frontend): restore SSR favicon rendering on public pages#433

Merged
jesposito merged 1 commit intomainfrom
fix/favicon-ssr-432
Apr 13, 2026
Merged

fix(frontend): restore SSR favicon rendering on public pages#433
jesposito merged 1 commit intomainfrom
fix/favicon-ssr-432

Conversation

@jesposito
Copy link
Copy Markdown
Owner

Summary

Fixes #432 — favicon missing on public pages (still shown on admin backend).

Root cause: commit 8b01708 ("feat: eliminate FOUC with SSR accent color, plan config, and palette generation", Mar 28 2026) replaced the direct data-init of faviconUrl with a null + $effect pattern:

-// Initialize from server-loaded data for correct SSR
-let faviconUrl = $state<string | null>(data.faviconUrl);
+let faviconUrl = $state<string | null>(null);
+
+$effect(() => {
+    faviconUrl = data.faviconUrl;
+});

$effect never runs during SSR, so the server-rendered HTML always contained the fallback <link rel="icon" href="/favicon.png"> even when a custom favicon was configured. The regression was hidden on admin routes because admin hydrates and navigates as an SPA, so the $effect fires after hydration and patches svelte:head client-side. Public pages are hit more often as fresh SSR loads (direct links, search, social), where the fallback was visible.

Fix

Restore $state(data.faviconUrl) so the initial value is picked up during SSR. $state remains writable, so the existing onMount settings-load (line 274) and handleFaviconChange event handler (line 355) keep working unchanged.

This restores the intent of PR #345 (commit e0a123b), whose comment // Initialize from server-loaded data for correct SSR was preserved through the regression while the line it described was silently gutted.

Test plan

  • cd frontend && npm run check — svelte-check passes (verified, no errors in +layout.svelte)
  • Run make dev, upload a custom favicon via /admin/settings, hard-reload / and view page source — SSR HTML contains <link rel="icon" type="image/x-icon" href="/api/favicon">, not the /favicon.png fallback
  • Navigate client-side between / and /admin — favicon remains correct (writable $state still updated by onMount/event handler)
  • Clear the custom favicon in admin settings and hard-reload / — falls back to /favicon.png as expected

Fixes #432

Commit 8b01708 ("feat: eliminate FOUC with SSR accent color...")
replaced the direct data init of faviconUrl with a null + $effect
pattern. $effect never runs during SSR, so the server-rendered HTML
always contained the fallback <link rel="icon" href="/favicon.png">
even when a custom favicon was configured. Admin routes masked the
bug because they hydrate and navigate as an SPA, where the $effect
runs and patches svelte:head client-side.

Restore $state(data.faviconUrl) so the initial value is picked up
during SSR. $state is still writable, so the existing onMount
settings-load and handleFaviconChange event handler keep working.

Fixes #432
@jesposito jesposito merged commit b6c14b4 into main Apr 13, 2026
7 checks passed
@jesposito jesposito deleted the fix/favicon-ssr-432 branch April 20, 2026 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Favicon missing on public page

1 participant