Repository source: docs/plans/archive/theme_css_loading_step4_implementation_summary.md
Theme CSS Loading — Step 4: Implementation Summary
Stage 1 - Define theme asset and hint contracts
Changes:
Added the canonical
theme-hintcookie name, explicit-theme validation, and per-theme stylesheet paths toThemeRegistry.Added registry coverage for the cookie, valid theme paths, and rejection of
autoor unknown hints.
Verification:
php -l src/ForumRewrite/View/ThemeRegistry.phpphp -l tests/ThemeRegistryTest.phpphp tests/run.php ThemeRegistryTest— 5 tests passed.
Notes:
Cookie reading and rendering are intentionally deferred to Stages 3–4.
Stage 2 - Extract shared and per-theme stylesheets
Changes:
Reduced
site.cssfrom 94,509 to 40,753 bytes by retaining shared, fallback, and critical rules only.Extracted all 13 explicit theme selector groups, including their responsive rules and swatch styling, to fingerprintable
theme-<name>.cssassets.Added a regression test that requires every registered theme asset and rejects explicit theme selectors in the shared stylesheet.
Verification:
php tests/run.php ThemeRegistryTest— 6 tests passed.Confirmed all 13 stylesheet assets are non-empty and no direct explicit-theme, swatch, or theme-option selector remains in
site.css.
Notes:
The unscoped light variables remain in
site.cssas the deliberate no-JavaScript/default fallback.
Stage 3 - Render the prioritized stylesheet link
Changes:
Added a validated
theme-hintlookup to the shared renderer and a fingerprinted stylesheet manifest for every explicit theme.Rendered one high-priority theme stylesheet link before the head resolver; a valid hint (or explicit site default) supplies its initial path.
Extended the early resolver to replace a stale or missing hinted path with the client-resolved explicit or Auto/System theme before first paint.
Verification:
php tests/run.php LocalAppSmokeTest::testLayoutUsesOnlyAValidatedThemeHintForTheInitialStylesheet LocalAppSmokeTest::testCompactModeMenuStylesUseScopedDensitySelectors LocalAppSmokeTest::testApplicationRendersCoreRoutes ThemeRegistryTest— passed.Confirmed valid
word97and invalidautohints respectively render the fingerprinted Word 97 and fallback Light stylesheet paths.
Notes:
The hint is not trusted as user preference and
autois rejected server-side.
Stage 4 - Reconcile preference, Auto/System, and hint updates
Changes:
The early resolver now writes the cookie only when its resolved concrete theme differs from the current hint.
The theme script keeps the active stylesheet, resolved-theme attribute, and cookie hint synchronized after explicit selections and Auto/System scheme changes.
Kept the stored
auto/explicit preference separate from the concrete cookie value.
Verification:
php -l src/ForumRewrite/View/TemplateRenderer.phpnode -c public/assets/theme_toggle.jsphp tests/run.php LocalAppSmokeTest::testLayoutUsesOnlyAValidatedThemeHintForTheInitialStylesheet ThemeRegistryTest— passed.
Notes:
Cookie lifetime is one year, path is site-wide, and
Secureis added on HTTPS.
Stage 5 - Warm alternate themes and preserve responsive switching
Changes:
Added idle-time, low-priority loading for every non-active resolved theme stylesheet.
Added stylesheet readiness tracking; a selection promotes an unfinished asset and waits without switching to incomplete styling.
Preserved immediate application for already warm/cached themes and kept Auto/System changes synchronized while their asset warms.
Verification:
node -c public/assets/theme_toggle.jsphp tests/run.php LocalAppSmokeTest::testThemeToggleWarmsAlternateThemeStylesheetsAtLowPriority LocalAppSmokeTest::testLayoutUsesOnlyAValidatedThemeHintForTheInitialStylesheet ThemeRegistryTest— passed.
Notes:
A failed stylesheet request releases the loading state so controls cannot become permanently stuck.
Stage 6 - Cover static artifacts and regressions
Changes:
Added static-artifact coverage that requires every fingerprinted theme stylesheet to be referenced by the generated layout and present in its artifact assets.
Reused the existing asset copier and fingerprint reference health check; no release-pipeline change was needed.
Updated the Word 97 invitation regression to read its extracted theme stylesheet.
Verification:
php tests/run.php LocalAppSmokeTest::testStaticArtifactBuilderWritesApacheFriendlyArtifactLayout LocalAppSmokeTest::testLayoutUsesOnlyAValidatedThemeHintForTheInitialStylesheet LocalAppSmokeTest::testThemeToggleWarmsAlternateThemeStylesheetsAtLowPriority ThemeRegistryTest— passed.php tests/run.php InvitationIssuanceTest— passed after moving its Word 97 assertion to the extracted asset.Full
php tests/run.phprun: theme-related coverage passed; unrelated failures remain in activity-manifest, adjacent-signature, and lazy-compose test paths.
Notes:
Static pages use the default hint-free initial link; pages carrying a theme hint already take the dynamic path and are corrected by the early resolver.
Final Verification
Changes:
None; recorded final route-level verification.
Verification:
Started
php -S 127.0.0.1:8099 -t public public/router.php, requested/, and confirmed the fingerprinted Light theme link plus all 13 fingerprinted theme paths in the rendered manifest.
Notes:
Stopped the temporary development server after the check.