Yellow Theme

Next start · November 2026

Notes / Engineering note

Part of the yellow theme method · stage 1

2026-10-03

A strict content-security policy never runs an inline theme boot

A strict CSP with script-src 'self' blocks an inline theme boot. Put the theme class on the static HTML — do not loosen script-src for first paint.

Thesis: When script-src is 'self', an inline theme-boot script never runs. First paint stays unthemed unless theme-dark (and color-scheme) already live on the static <html>.

What we shipped first

We shipped a client app shell under Amplify custom headers with script-src 'self' — no 'unsafe-inline'. The index still carried an inline theme-boot script that set theme-dark and color-scheme before paint. The browser blocked it. The shell looked unthemed on first paint even though the CSS and a later theme module were fine.

The wrong fix would have been to reopen 'unsafe-inline'. We removed the inline boot instead and put forest on the static HTML.

The working shape

Keep the CSP strict. Put theme-dark on <html> in the markup (and color-scheme: dark). Runtime theme code may still toggle later from an external file. First paint must not depend on an inline script.

<!-- Working shape: theme class is static HTML. No inline script. -->
<html class="h-full theme-dark" style="color-scheme: dark">
  <!-- CSP: script-src 'self' — external theme.js may still toggle later -->
</html>

<!-- Wrong green: inline boot under a strict CSP never runs -->
<!-- <script>document.documentElement.classList.add("theme-dark")</script> -->

Checklist

Try the lab

Observe the unthemed paint, name why the inline boot never ran, choose the static-theme fix, then prove. Commands: observe · why · fix · prove.

Full page: Open this lab · All labs

Related: late font faces must be optional. How we deliver: methodology · readiness.

Engineering commentary only — not audit, legal, or certification advice.