Layouts
A layout is a TSX component, default-exported, in src/layouts/. It returns the entire HTML document — <html>, <head>, <body> and all. Its only job is structural; it contains no business logic.
Location
src/layouts/MainLayout.tsx
The filename (without extension) must match the rootLayout field in the sitemap.
Example
// src/layouts/MainLayout.tsx
import { WidgetPlaceholder } from "streak-forge/components";
const MainLayout = () => {
console.info("Rendering Main Layout"); // runs on the server, each time the page renders
return (
<html dir="ltr" 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; Rules
- Must be the default export
- Must return the full HTML document —
<html>,<head>,<body> - Every widget in
streak.sitemap.jsonwidgets[]needs a matchingWidgetPlaceholderhere idandtypeonWidgetPlaceholdermust both be present and must match the sitemap entry exactlyconsole.infoinside a layout runs on the server, not in the browser- The layout renders once per page render — in
streak-forge buildthat's once per sitemap entry; instreak-forge devit renders again on every matching request
WidgetPlaceholder
WidgetPlaceholder from streak-forge/components marks where a widget's HTML will be injected.
<WidgetPlaceholder id="HelloBanner" type="HelloBanner" /> When the page renders, Streak replaces this element with the fully rendered HTML of the matching widget. The id links it to the handler data; the type links it to the widget file.
Widget Placement in Head vs Body
Widgets can be placed in <head> as well as <body>. A common pattern is a PageHead widget that renders <title>, <meta>, and <link> tags:
<html dir="ltr" lang="en">
<head>
<WidgetPlaceholder id="PageHead" type="PageHead" />
</head>
<body>
<WidgetPlaceholder id="NavBar" type="NavBar" />
<WidgetPlaceholder id="HeroBanner" type="HeroBanner" />
<WidgetPlaceholder id="Footer" type="Footer" />
</body>
</html> What Layouts Should NOT Do
Layouts should not contain business logic, data fetching, or conditional rendering based on data. All of that belongs in:
- Data handlers (data fetching)
- Widgets (conditional rendering based on data)