gDom — The Extended Window
Inside every Script children function, the first argument (gDom) is window extended with a small set of helpers Streak's client runtime registers on startup. It is not a separate object — it is literally window.
The entire client runtime is a single inline script injected at the end of every generated page. It registers four functions on window and then walks a list of lazy widget ids, loading each one in turn. There is no Web Worker involved anywhere in this pipeline — every fetch and DOM insertion happens directly on the main thread.
Full Interface
interface GDom extends Window {
addResourceToBody: (
src: string,
options?: { async?: boolean },
callback?: () => void,
) => void;
loadPackage: (name: string) => Promise<void>;
loadDynamicComponent: (id: string, callback?: () => void) => void;
addWidgetToBody: (id: string, callback?: () => void) => void;
} Method Reference
addResourceToBody
addResourceToBody(
src: string,
options?: { async?: boolean },
callback?: () => void,
): void Appends a real <script src="..."> (if src ends in .js) or <link rel="stylesheet" href="..."> (if src ends in .css) directly to document.body. callback fires once the tag has loaded.
In-flight and already-loaded requests are cached in a promise map keyed by src — calling addResourceToBody again with the same src reuses that promise instead of appending a second tag or re-fetching, and still calls the new callback once it resolves.
gDom.addResourceToBody("/assets/js/motion.js", { async: true }, () => {
console.info("motion.js loaded");
}); loadPackage
loadPackage(name: string): Promise<void> Loads a JS or CSS file from public/assets/. Internally this is just addResourceToBody(/assets/$name, { async: true }) — name is resolved relative to /assets/, so "js/motion.js" fetches /assets/js/motion.js.
Because it's built on addResourceToBody, repeat calls for the same path reuse the cached promise rather than re-fetching.
await gDom.loadPackage("js/motion.js"); See loadPackage for full usage details.
loadDynamicComponent
loadDynamicComponent(id: string, callback?: () => void): void Fetches the HTML that was stripped out of a <Dynamic id="..."> block at build time and swaps it into the placeholder element ([component-id="<id>"][component-type="c"]) via outerHTML. Any <script> tags bundled with that content are appended to the document. Calls callback once done.
gDom.loadDynamicComponent("my-panel", () => {
console.info("panel injected");
}); See Dynamic Components for the full build-time/runtime flow.
addWidgetToBody
addWidgetToBody(id: string, callback?: () => void): void Same fetch-and-inject mechanism as loadDynamicComponent, but for a lazy widget's placeholder ([component-id="<id>"][component-type="w"]) instead of a Dynamic block. This is what the runtime calls on startup for every id listed in the w-m registry — see below.
gDom.addWidgetToBody("HelloMessage", () => {
console.info("widget injected");
}); See Lazy Widgets for how widgets end up in the w-m list.
The w-m Widget Registry
Every generated page includes a hidden JSON element listing the ids of its lazy widgets, in order:
<script type="application/json" id="w-m">["HelloMessage", "Testimonials"]</script> On startup, the client runtime reads this array and calls addWidgetToBody for each id sequentially — each widget is fetched and injected only after the previous one finishes, via chained callbacks. Widgets without loadingStrategy: "lazy" never appear in this list; their HTML is already inline in the page.