Runtime Contract
JavaScript Runtime
The generator keeps Hugo-rendered HTML as the source of truth and adds behavior
through small CDN scripts. Shared browser behavior lives under window.QL.
Runtime Surface
window.QL.layout.ready()waits for DOM readiness, stylesheet settlement, fonts when available, and one animation frame.window.QL.layout.whenReady(fn, { scope })runs first-paint layout work after the page is safe to measure.window.QL.layout.schedule(name, fn, { phase, priority })coalesces layout tasks. Preferlayout-readfor measurement andlayout-writefor CSS/DOM writes.window.QL.layout.observePersistent(selector, fn)observes persistent chrome that may be replaced during SPA navigation.window.QL.runtime.register({ name, selector, init })is the preferred shape for new DOM components. Existingwindow.QlWidgetRuntimehelpers remain supported as compatibility aliases.- Set
window.QL.debug = trueon local/dev hosts to log slow layout tasks, slow component initialization, and duplicate component registration.
Migration Rules
- Do not read layout during initial script execution or raw
DOMContentLoaded. UseQL.layout.whenReady. - Keep pointer, resize, and animation-frame measurements local when they are already user-driven or frame-driven.
- Keep Nowtype/PDF pagination domain-owned. The shared layout runtime may trigger editor refreshes, but it must not replace editor-specific measurement, typing suppression, focus restoration, or overlay positioning.
- New SPA-aware widgets should consume
QL.runtimeand the existing SPA events through the runtime instead of creating another lifecycle vocabulary.
Smoke Test
Run npm run browser:smoke:js-runtime -- <origin> against a running local site.
The smoke asserts that the shared runtime exists, SPA navigation works, local
prefetches do not fail, PhotoSwipe opens when present, and layout-related console
warnings do not recur.