Skip to content
Twilight React Playground
ثيم رائدaren

WidgetHead

componentAdvancedserverbrowser

An invisible component with the head hook slots and the equal-height GTM push; TwilightProvider already renders it on every page.

import { WidgetHead } from '@salla.sa/twilight-theme-engine/components/layout';

In plain words

Some things belong to the page as a whole rather than to one section: tags that apps and themes add, or tracking settings. WidgetHead renders nothing you can see. It provides the head:start, head and head:end hook slots and passes one store setting to Google Tag Manager.

TwilightProvider already renders it on every page, so a theme uses the slots, not the component.

Signature

const WidgetHead: LazyExoticComponent<() => JSX.Element>   // no props, no visible output

Example

app/hooks/index.tsx
import { hookRegistry, HookName } from '@salla.sa/twilight-theme-engine/hooks';

// Rendered by the WidgetHead that TwilightProvider mounts on every page.
// React 19 moves the <meta> into <head>.
hookRegistry.register(HookName.HEAD_END, () => <meta name="theme-color" content="#004d40" />);

How it behaves

  • It renders <HookSlot name="head:start" ssr />, head and head:end (with ssr, their slot elements are in the server HTML), and, in an effect, calls pushEqualHeightConfig(store.settings) whenever the store id or its settings change.

  • TwilightProvider renders an internal, eager copy before the layout, once it is ready.

  • The slots render where WidgetHead is: inside <body>, at the top of the provider. React 19 hoists <title>, <meta> and <link> elements into <head>; a plain <script> or <style> stays where it rendered.

  • Static head tags (favicon, theme colors, hreflang, the merchant's custom CSS and JS) come from the root route's head(), not from here.

  • This export is lazy (code-split).

Gotchas

  • Rendering it yourself duplicates it: every head-slot handler renders twice and the equal-height config is pushed twice.

Related

Source and docs