Data Handlers
A data handler is an async function, default-exported, in src/handlers/. It is called by the renderer before any JSX runs, and returns a plain object whose keys correspond to widget ids.
Location
src/handlers/HomeDataHandler.ts
The filename (without extension) must match the dataHandler field in the sitemap.
Example
// src/handlers/HomeDataHandler.ts
const getHomeData = async () => {
return {
status: 200, // required — signals render success
PageHead: {
// key = widget id from sitemap
title: "Hello",
},
HelloBanner: {
heading: "Hello World",
},
};
};
export default getHomeData; Rules
- Must be the default export
- Must return
{ status: 200, ...widgetData } - Each top-level key (other than
status) must match a widgetidin the sitemap - The value under each key is passed to the matching widget as
props.data - It is async — you can
awaitany database, CMS, or API call here - There is no implicit error handling — if it throws, the page fails to build
Data Flow
handler returns { status: 200, HelloBanner: { heading: "Hello" } }
↓
Streak renderer matches by widget id
↓
HelloBanner widget receives { data: { heading: "Hello" } }
↓
props.data.heading === "Hello"
Fetching External Data
Because handlers are async, they can call any external service:
const getHomeData = async () => {
const articles = await fetch("https://cms.example.com/api/articles").then((r) => r.json());
return {
status: 200,
ArticleList: {
items: articles,
},
};
};
export default getHomeData; Widget Data Mapping
Sitemap widget id:
{ "id": "HelloBanner", "type": "HelloBanner" } Handler return key:
HelloBanner: {
heading: "Hello World";
} Widget receives:
props.data === { heading: "Hello World" };
props.data.heading === "Hello World"; If the handler does not return a key for a widget, the widget receives { data: undefined }. Always use optional chaining (?.) and nullish coalescing (??) in widgets to handle this case safely.