Esc

Components API

Streak ships four built-in components. All are imported from streak/components:

import { WidgetPlaceholder, Script, Dynamic, Preload } from "streak/components";

WidgetPlaceholder

Marks the position in a layout where a widget's rendered HTML will be injected at build time.

Props

PropTypeRequiredDescription
idstringYesMust match the widget id in the sitemap and the handler return key
typestringYesMust match the widget filename in src/widgets/ (case-sensitive)
dummybooleanNoUsed inside Dynamic content where a placeholder is needed without a widget binding

Usage

WidgetPlaceholder is used only inside layout files:

const MainLayout = () => (
  <html lang="en">
    <head>
      <WidgetPlaceholder id="PageHead" type="PageHead" />
    </head>
    <body>
      <WidgetPlaceholder id="HelloBanner" type="HelloBanner" />
      <WidgetPlaceholder id="HelloMessage" type="HelloMessage" />
    </body>
  </html>
);

export default MainLayout;

Every widget in the sitemap widgets[] array must have a corresponding WidgetPlaceholder in the layout. The id and type values must match exactly.


Script

Serializes a function body to a string at build time and emits it as an inline <script> tag that executes as an IIFE in the browser.

Props

PropTypeRequiredDescription
idstringYesMust be unique on the page
optionsobjectNoPlain JSON-serializable object passed as the second IIFE argument
childrenfunctionYesFunction body to serialize — receives (gDom, options)

Usage

<Script id="banner-init" options={{ color: "#818cf8", delay: 800 }}>
  {(gDom: any, options: any) => {
    document.getElementById("banner-heading").style.color = options.color;
  }}
</Script>

The rendered output is an IIFE:

((function(gDom, options) {
  document.getElementById("banner-heading").style.color = options.color;
})(window, {"color":"#818cf8","delay":800}));

Serialization Rules

RuleDetail
No closuresThe function is converted with .toString(). Outer-scope variables are not captured.
No importsES module imports inside the function body will not work. Use gDom.loadPackage() instead.
Options must be JSON-serializableThe options object is passed through JSON.stringify. Functions, undefined, and circular references are dropped.
gDom is windowThe first argument is window extended with Streak helpers (loadPackage, loadDynamicComponent, onVisible, etc.).

Dynamic

Strips its children from the initial HTML at build time. The content is injected on demand at runtime via gDom.loadDynamicComponent().

Props

PropTypeRequiredDescription
idstringYesIdentifier used by loadDynamicComponent() to find and inject this content
childrenJSXYesThe content to defer — removed from initial HTML, injected on demand

Usage

Dynamic is always paired with a Script that triggers the injection:

<Dynamic id="nav-submenu">
  <ul>
    <li>Item A</li>
    <li>Item B</li>
  </ul>
</Dynamic>

<Script id="nav-submenu-trigger">
  {(gDom: any) => {
    document.getElementById("nav-btn")
      ?.addEventListener("click", () => {
        gDom.loadDynamicComponent("nav-submenu", () => {
          console.info("submenu injected");
        });
      });
  }}
</Script>

How It Works

  1. Build time: children are stripped. A placeholder element is emitted with component-type="__dynamicWidgetType__" and component-id="<id>".
  2. Runtime:gDom.loadDynamicComponent(id, callback) finds the placeholder, injects the original HTML, and calls callback.

Dynamic vs Lazy Comparison

HTML in initial payloadJS loadedTriggered by
loadingStrategy: "lazy"YesAfter page is interactiveAutomatic
<Dynamic>NoOn demandgDom.loadDynamicComponent()

Use lazy when the HTML should be visible immediately but JS can wait. Use Dynamic when the HTML itself should be excluded from the initial payload.


Preload

Renders a <link rel="preload"> tag. Tells the browser to begin fetching a resource before the parser discovers it naturally.

Props

PropTypeRequiredDescription
hrefstringYesURL of the resource to preload
as"image" | "font" | "style" | "script" | "video"YesResource type hint for the browser
mediastringNoCSS media query string; use "" for unconditional preload

Usage

Use Preload inside a widget that renders in <head>:

<Preload href="/images/hero.jpg" as="image" media="(min-width: 768px)" />
<Preload href="/styles/tailwind.css" as="style" media="" />
<Preload href="/assets/fonts/inter.woff2" as="font" />

Rendered Output

<link rel="preload" href="/images/hero.jpg" as="image" media="(min-width: 768px)">
<link rel="preload" href="/styles/tailwind.css" as="style" media="">

When to Use

  • LCP images — preload the largest above-the-fold image to reduce Largest Contentful Paint time.
  • Critical fonts — preload web fonts to avoid flash of unstyled text.
  • Above-the-fold CSS — preload stylesheets not discovered early in the document.