Problem
After the published Askr packages were upgraded in #30, the generated documentation HTML includes ak-style-* class names but does not include the corresponding server-rendered style registry. The browser receives the layout classes before their CSS, and hydration injects the missing rules after the first paint.
The current SSG configuration passes renderDocument directly:
The documented @askrjs/themes SSR/SSG contract requires wrapping that renderer with withThemeStyles(renderDocument).
Production evidence
URL: https://askrjs.com/docs/getting-started/
A Lighthouse 13.3.0 navigation captured one layout shift with CLS 0.1776625. Replaying the same load showed the main .docs-channel container changing from the unstyled full viewport width to the styled 1152 px container when the client-injected registry appeared.
The report's unusually shallow 2560 x 150 viewport magnified the score. On a fast load, 1440 x 900 produced CLS 0 and 390 x 844 produced approximately 0.00003. The missing initial CSS is nevertheless deterministic and can produce a visible flash or shift when hydration or JavaScript delivery is slower.
Root cause and ownership
Required outcome
- Import
withThemeStyles from @askrjs/themes/ssr.
- Configure SSG with
document: withThemeStyles(renderDocument).
- Extend
scripts/verify-static-output.ts so a generated document fails verification when it contains ak-style-* classes without a non-empty initial style registry.
- Verify that hydration adopts the server registry rather than creating a duplicate.
Acceptance criteria
- Generated docs HTML contains the registered theme rules before client JavaScript runs.
- No generated layout class is emitted without its initial registry CSS.
- Hydration leaves exactly one adopted registry.
- A browser trace shows no container shift caused by late generated-style injection.
npm run check passes.
References
Problem
After the published Askr packages were upgraded in #30, the generated documentation HTML includes
ak-style-*class names but does not include the corresponding server-rendered style registry. The browser receives the layout classes before their CSS, and hydration injects the missing rules after the first paint.The current SSG configuration passes
renderDocumentdirectly:document: renderDocumentThe documented
@askrjs/themesSSR/SSG contract requires wrapping that renderer withwithThemeStyles(renderDocument).Production evidence
URL: https://askrjs.com/docs/getting-started/
A Lighthouse 13.3.0 navigation captured one layout shift with CLS 0.1776625. Replaying the same load showed the main
.docs-channelcontainer changing from the unstyled full viewport width to the styled 1152 px container when the client-injected registry appeared.The report's unusually shallow 2560 x 150 viewport magnified the score. On a fast load, 1440 x 900 produced CLS 0 and 390 x 844 produced approximately 0.00003. The missing initial CSS is nevertheless deterministic and can produce a visible flash or shift when hydration or JavaScript delivery is slower.
Root cause and ownership
ssg.config.tsuses the raw document renderer.style[data-askr-style-registry].Required outcome
withThemeStylesfrom@askrjs/themes/ssr.document: withThemeStyles(renderDocument).scripts/verify-static-output.tsso a generated document fails verification when it containsak-style-*classes without a non-empty initial style registry.Acceptance criteria
npm run checkpasses.References