Problem
Askr collects request-local SSR style registrations in context.styles and passes them to the application's document renderer, but generation still succeeds if that renderer ignores a non-empty style collection.
That failure mode produces valid-looking HTML whose elements reference generated classes without their CSS. It is silent until a browser paints the document, where it can appear as a flash of unstyled content or a hydration layout shift.
A first-party production example occurred in askrjs/website after its package upgrade: the site emitted ak-style-* classes without an initial registry because its SSG configuration used a raw document renderer instead of the theme serialization wrapper. Hydration then supplied the missing rules. The package contract itself is fixed and documented in askrjs/askr-themes#22; this issue is about making omissions diagnosable at the Askr document boundary.
Minimal failure shape
// A route/component registers an SSR style and renders its class.
document: ({ appHtml }) =>
`<!doctype html><html><head></head><body>${appHtml}</body></html>`
If context.styles is non-empty, this renderer drops the registrations, but SSR/SSG currently returns successfully.
Desired outcome
Provide a deterministic diagnostic or validation path when a document renderer drops non-empty registered SSR styles.
The mechanism should stay generic rather than depending on @askrjs/themes selectors. Possible designs include an explicit document-render result contract, a validation hook, or a development/build warning with an intentional opt-out. The exact API is open; the important property is that a missing style serialization step is no longer silent.
Acceptance criteria
- Add positive and negative SSR/SSG coverage for non-empty registered styles.
- A document renderer that represents the registrations remains valid.
- A renderer that silently drops them emits an actionable warning or error in the selected mode.
- Applications can explicitly opt out when omission is intentional.
- Validation remains request-local and does not introduce cross-request style leakage.
- Existing
withThemeStyles integrations continue to work unchanged.
References
Problem
Askr collects request-local SSR style registrations in
context.stylesand passes them to the application's document renderer, but generation still succeeds if that renderer ignores a non-empty style collection.That failure mode produces valid-looking HTML whose elements reference generated classes without their CSS. It is silent until a browser paints the document, where it can appear as a flash of unstyled content or a hydration layout shift.
A first-party production example occurred in askrjs/website after its package upgrade: the site emitted
ak-style-*classes without an initial registry because its SSG configuration used a raw document renderer instead of the theme serialization wrapper. Hydration then supplied the missing rules. The package contract itself is fixed and documented in askrjs/askr-themes#22; this issue is about making omissions diagnosable at the Askr document boundary.Minimal failure shape
If
context.stylesis non-empty, this renderer drops the registrations, but SSR/SSG currently returns successfully.Desired outcome
Provide a deterministic diagnostic or validation path when a document renderer drops non-empty registered SSR styles.
The mechanism should stay generic rather than depending on
@askrjs/themesselectors. Possible designs include an explicit document-render result contract, a validation hook, or a development/build warning with an intentional opt-out. The exact API is open; the important property is that a missing style serialization step is no longer silent.Acceptance criteria
withThemeStylesintegrations continue to work unchanged.References