diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 7257ce1f..838fc0be 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -396,19 +396,52 @@ export async function load({ fetch, params, parent, route, url }) { // Apply site-level theme defaults only when there is no persisted ae_loc // in localStorage (first-run). URL params and manual selection still override. try { - const scfg = ae_loc_init['site_cfg_json'] as any; - let has_persisted_ae_loc = false; - if (typeof localStorage !== 'undefined') { + // site_cfg_json may be an object or a JSON string depending on the API/backend. + let scfg_raw = ae_loc_init['site_cfg_json']; + let scfg: any = scfg_raw; + if (typeof scfg_raw === 'string') { try { - const raw = localStorage.getItem('ae_loc'); - if (raw) has_persisted_ae_loc = true; + scfg = JSON.parse(scfg_raw); } catch (e) { - has_persisted_ae_loc = false; + scfg = {}; } } - if (scfg && typeof scfg === 'object' && !has_persisted_ae_loc) { - if (scfg.theme_name) ae_loc_init['theme_name'] = scfg.theme_name; + // Inspect persisted `ae_loc` in localStorage to determine whether the + // user has already selected a theme. Some persisted-store implementations + // write a default `ae_loc` object immediately, so the mere presence of + // the key is not a reliable indicator of a user choice. + let persistedRaw: string | null = null; + try { + if (typeof localStorage !== 'undefined') persistedRaw = localStorage.getItem('ae_loc'); + } catch (e) { + persistedRaw = null; + } + + let persistedObj: any = null; + let persistedHasUserTheme = false; + if (persistedRaw) { + try { + persistedObj = JSON.parse(persistedRaw); + } catch (e) { + persistedObj = null; + } + if (persistedObj) { + // Explicit flag wins. + if (persistedObj.user_theme_selected === true) { + persistedHasUserTheme = true; + } else if (persistedObj.theme_name && persistedObj.theme_name !== 'AE_Firefly') { + // If the persisted theme differs from the global default, assume + // it was a prior user choice (backcompat for older installs). + persistedHasUserTheme = true; + } + } + } + + if (scfg && typeof scfg === 'object' && !persistedHasUserTheme) { + // Accept common keys for theme name so site authors have flexibility. + const themeName = scfg.theme_name ?? scfg.theme ?? scfg.themeName ?? scfg.site_theme; + if (themeName) ae_loc_init['theme_name'] = themeName; if (scfg.theme_mode && (scfg.theme_mode === 'light' || scfg.theme_mode === 'dark')) ae_loc_init['theme_mode'] = scfg.theme_mode; }