Skip to main content

Widget SDK Reference

API reference for @radarboard/widget-sdk — template config, recipes, section helpers, and testing.

./types

DataSourceFormat

How a data value should be formatted when rendered.
  • "currency" — locale-aware currency (e.g. $1,234.56)
  • "number" — locale-aware number (e.g. 1,234)
  • "percent" — percentage with % suffix
  • "date" — date string
  • "relative-time" — “2 hours ago” style
  • "duration-seconds" — seconds → human-readable duration
type DataSourceFormat = "number" | "currency" | "percent" | "date" | "relative-time" | "duration-seconds"

DataSource

A pointer to a field in a resolved data source. This is the fundamental building block of the template system. Every section config uses DataSource to bind UI elements to data from your integration.
PropertyTypeDescription
sourceIdstring
fieldstring
format?DataSourceFormat | undefined
precision?number | undefined
compact?boolean | undefined
Example:
// Point to the "totalRevenue" field in the "revenue" data source
const source: DataSource = {
  sourceId: "revenue",
  field: "totalRevenue",
  format: "currency",
};

DataSourceDeclaration

Declares a data source ID that this widget template depends on. Listed in WidgetTemplateConfig.dataSources to register which resolvers need to run before the template can render.
PropertyTypeDescription
idstring

LayoutGap

Gap size between sections in a layout.
type LayoutGap = "none" | "sm" | "md"

AlertCondition

PropertyTypeDescription
sourceDataSource
operator"lt" | "gt" | "eq" | "neq" | "lte" | "gte"
valuestring | number | boolean

AlertSectionConfig

Alert/banner section — displays a warning, error, or info message.
PropertyTypeDescription
type"alert"
severity"error" | "warning" | "info" | "success" | "setup"
messagestring
source?DataSource | undefined
condition?AlertCondition | undefined
dismissible?boolean | undefined
action?{ label: string; href?: string; } | undefined

KPIMetricConfig

PropertyTypeDescription
labelstring
sourceDataSource
changeSource?DataSource | undefined
sparklineSource?DataSource | undefined
breakdownSource?DataSource | undefined
valueColorSource?DataSource | undefined
color?string | undefinedOptional colored dot rendered next to the label (e.g. to match a chart series).

KPIRowSectionConfig

A horizontal row of KPI metric cards.
PropertyTypeDescription
type"kpi-row"
columns1 | 2 | 3 | 4 | 5 | 6
variant?"default" | "compact" | undefined
metricsKPIMetricConfig[]
Example:
const kpis: KPIRowSectionConfig = {
  type: "kpi-row",
  columns: 3,
  metrics: [
    { label: "MRR", source: { sourceId: "rev", field: "mrr", format: "currency" } },
    { label: "Subscribers", source: { sourceId: "rev", field: "count" } },
    { label: "Churn", source: { sourceId: "rev", field: "churnRate", format: "percent" } },
  ],
};

SummaryQuadMetricSlotConfig

PropertyTypeDescription
kind"metric"
labelstring
sourceDataSource
subtitle?DataSource | undefined
subtitleText?string | undefined
footerStart?DataSource | undefined
footerEnd?DataSource | undefined
footerColor?DataSource | undefined
changeSource?DataSource | undefined
sparklineSource?DataSource | undefined
breakdownSource?DataSource | undefined
tooltip?string | undefined

SummaryQuadSparklineSlotConfig

PropertyTypeDescription
kind"sparkline"
labelstring
sourceDataSource
emptyMessage?string | undefined
positive?boolean | undefined

SummaryQuadEmptySlotConfig

PropertyTypeDescription
kind"empty"

SummaryQuadSlotConfig

type SummaryQuadSlotConfig = SummaryQuadMetricSlotConfig | SummaryQuadSparklineSlotConfig | SummaryQuadEmptySlotConfig

SummaryQuadSectionConfig

A 2x2 grid of metric slots (metric, sparkline, or empty).
PropertyTypeDescription
type"summary-quad"
slots[SummaryQuadSlotConfig, SummaryQuadSlotConfig, SummaryQuadSlotConfig, SummaryQuadSlotConfig]

HeadlineStatSectionConfig

A large featured number with a label — great for hero metrics.
PropertyTypeDescription
type"headline-stat"
sourceDataSource
labelstring
indicatorColor?string | undefined

OverviewPanelRowConfig

PropertyTypeDescription
labelstring
sourceDataSource
toneSource?DataSource | undefined

OverviewPanelSectionConfig

Overview panel with eyebrow, title, metric, badge, description, and detail rows.
PropertyTypeDescription
type"overview-panel"
eyebrow?string | undefined
title?string | undefined
titleSource?DataSource | undefined
metricLabel?string | undefined
metricSource?DataSource | undefined
metricToneSource?DataSource | undefined
badgeSource?DataSource | undefined
badgeToneSource?DataSource | undefined
descriptionSource?DataSource | undefined
rows?OverviewPanelRowConfig[] | undefined
footerStart?DataSource | undefined
footerEnd?DataSource | undefined

ListItemTemplate

PropertyTypeDescription
titleDataSource
subtitle?DataSource | undefined
value?DataSource | undefined
valueColor?DataSource | undefined
timestamp?DataSource | undefined
timestampColor?DataSource | undefined
status?DataSource | undefined
badge?RowListBadgeConfig | undefined

TemplateSelectionDialogConfig

PropertyTypeDescription
title?string | undefined
size?ModalSize | undefined
resizable?boolean | undefined

TemplateSelectionConfig

PropertyTypeDescription
selectionIdstring
keyFieldstring
detailRendererIdstring
source?DataSource | undefined
dialog?TemplateSelectionDialogConfig | undefined

InlineListHeaderColumnConfig

PropertyTypeDescription
slot"title" | "subtitle" | "value" | "timestamp"
labelstring
align?"left" | "right" | "center" | undefined

InlineListHeaderConfig

PropertyTypeDescription
title?string | undefined
subtitle?string | undefined
value?string | undefined
timestamp?string | undefined
gridTemplateColumns?string | undefined
columns?InlineListHeaderColumnConfig[] | undefined

ListSectionConfig

A scrollable list of items with title, subtitle, badge, and optional selection.
PropertyTypeDescription
type"list"
sourceDataSource
itemTemplateListItemTemplate
layout?"stacked" | "inline" | undefined
inlineHeader?InlineListHeaderConfig | undefined
maxItems?number | undefined
emptyMessage?string | undefined
hrefSource?DataSource | undefined
hrefTarget?"_blank" | "_self" | "_parent" | "_top" | undefined
selection?TemplateSelectionConfig | undefined
Example:
const issues: ListSectionConfig = {
  type: "list",
  source: { sourceId: "github", field: "issues" },
  itemTemplate: {
    title: { sourceId: "github", field: "title" },
    subtitle: { sourceId: "github", field: "author" },
    badge: { label: { sourceId: "github", field: "state" } },
  },
  emptyMessage: "No open issues",
};

RowListBadgeConfig

PropertyTypeDescription
labelDataSource
color?DataSource | undefined
normalize?"none" | "compact-project" | undefined

RowListStatusConfig

PropertyTypeDescription
sourceDataSource
display?"dot" | "severity-icon" | "named-icon" | "favicon" | undefined

RowListItemTemplate

PropertyTypeDescription
titleDataSource
subtitle?DataSource | undefined
badge?RowListBadgeConfig | undefined
value?DataSource | undefined
timestamp?DataSource | undefined
timestampColor?DataSource | undefined
status?RowListStatusConfig | undefined

RowListSectionConfig

Compact row list with status dots/icons, badges, and timestamps.
PropertyTypeDescription
type"row-list"
sourceDataSource
itemTemplateRowListItemTemplate
maxItems?number | undefined
emptyMessage?string | undefined
hrefSource?DataSource | undefined
hrefTarget?"_blank" | "_self" | "_parent" | "_top" | undefined
selection?TemplateSelectionConfig | undefined

StreamListSectionConfig

Real-time event stream with log levels, search, and auto-scroll.
PropertyTypeDescription
type"stream-list"
variant?"compact" | "expanded" | undefined
defaultLevel?"error" | "info" | "all" | "debug" | "warn" | undefined
maxItems?number | undefined
autoScroll?boolean | undefined
defaultLive?boolean | undefined
showSearch?boolean | undefined
showLiveToggle?boolean | undefined
emptyMessage?string | undefined

FilterBarSelectControlConfig

PropertyTypeDescription
type"select"
idstring
labelstring
allLabel?string | undefined
options?{ value: string; label: string; }[] | undefined
optionsSource?DataSource | undefined

FilterBarRangeControlConfig

PropertyTypeDescription
type"range"
idstring
labelstring
minnumber
maxnumber
stepnumber
accentColorstring
format?"number" | "rank" | undefined

FilterBarToggleControlConfig

PropertyTypeDescription
type"toggle"
idstring
labelstring
accentColorstring

FilterBarControlConfig

type FilterBarControlConfig = FilterBarSelectControlConfig | FilterBarRangeControlConfig | FilterBarToggleControlConfig

FilterBarSectionConfig

Filter bar with select, range, and toggle controls.
PropertyTypeDescription
type"filter-bar"
stateIdstring
persistKey?string | undefined
controlsFilterBarControlConfig[]

DenseRankedTableFilterRule

PropertyTypeDescription
controlIdstring
fieldstring
kind"select" | "range" | "toggle"
operator?"eq" | "neq" | undefined
value?string | number | boolean | undefined

DenseRankedTableColumnConfig

PropertyTypeDescription
keystring
headerstring
variant"number" | "rank" | "text" | "bar" | "delta" | "flag"
field?string | undefined
color?string | undefined
align?"left" | "right" | "center" | undefined
sortable?boolean | undefined
width?number | undefined

DenseRankedTableSectionConfig

Dense ranked table with sorting, filtering, and compact/expanded variants.
PropertyTypeDescription
type"dense-ranked-table"
sourceDataSource
variant?"compact" | "expanded" | undefined
columnsDenseRankedTableColumnConfig[]
maxItems?number | undefined
emptyMessage?string | undefined
stateKey?string | undefined
defaultSort?{ key: string; direction: "asc" | "desc"; } | undefined
filterStateId?string | undefined
filterPersistKey?string | undefined
filterRules?DenseRankedTableFilterRule[] | undefined
gridTemplateColumns?string | undefined
selection?TemplateSelectionConfig | undefined
filterPlaceholder?string | undefined

TableColumnConfig

PropertyTypeDescription
keystring
headerstring
sortable?boolean | undefined
format?DataSourceFormat | undefined
width?number | undefined

TableSectionConfig

A data table with sortable columns and optional search.
PropertyTypeDescription
type"table"
sourceDataSource
columnsTableColumnConfig[]
searchable?boolean | undefined
defaultSort?{ key: string; direction: "asc" | "desc"; } | undefined
emptyMessage?string | undefined
selection?TemplateSelectionConfig | undefined

CardListMetaConfig

PropertyTypeDescription
labelstring
sourceDataSource

CardListSectionConfig

A grid of cards with title, image, badge, and optional search.
PropertyTypeDescription
type"card-list"
sourceDataSource
titleSourceDataSource
subtitleSource?DataSource | undefined
descriptionSource?DataSource | undefined
imageSource?DataSource | undefined
badgeSource?DataSource | undefined
meta?CardListMetaConfig[] | undefined
columns?1 | 2 | 3 | 4 | undefined
minCardWidth?number | undefined
searchable?boolean | undefined
filterPlaceholder?string | undefined
emptyMessage?string | undefined
maxItems?number | undefined
selection?TemplateSelectionConfig | undefined
hrefSource?DataSource | undefined
hrefTarget?"_blank" | "_self" | "_parent" | "_top" | undefined

ChartSeriesConfig

PropertyTypeDescription
dataKeystring
namestring
color?string | undefined
format?"number" | "percent" | "compact" | "decimal" | undefined

ChartSectionConfig

A chart section — area, line, bar, or sparkline.
PropertyTypeDescription
type"chart"
variant"sparkline" | "bar" | "area" | "line"
sourceDataSource
height?number | undefined
xKey?string | undefined
yKey?string | undefined
color?string | undefined
series?ChartSeriesConfig[] | undefinedMulti-series mode: each entry maps to a Line in the chart.
normalize?boolean | undefinedWhen true, normalize each series to 0-100 for geometry; tooltips show raw values.
fillHeight?boolean | undefinedWhen true, the chart section grows to fill remaining parent height via flex-1.
Example:
const visitors: ChartSectionConfig = {
  type: "chart",
  variant: "area",
  source: { sourceId: "analytics", field: "dailyVisitors" },
  height: 200,
  color: "var(--chart-1)",
};

ActivityChartSegmentConfig

PropertyTypeDescription
keystring
colorstring

ActivityChartSectionConfig

GitHub-style contribution heatmap with colored segments.
PropertyTypeDescription
type"activity-chart"
sourceDataSource
segmentsActivityChartSegmentConfig[]
heightClassName?string | undefined
minBarPercent?number | undefined

TabConfig

PropertyTypeDescription
idstring
labelstring
icon?"pull-request" | "issue" | undefined
accentColor?string | undefined
countSource?DataSource | undefined
sectionsSectionConfig[]

TabsSectionConfig

Tabbed content — switches between different section sets.
PropertyTypeDescription
type"tabs"
tabsTabConfig[]
defaultTab?string | undefined
variant?"compact" | "expanded" | undefined
queryParam?string | undefined

StackLayoutConfig

Vertical stack layout — sections arranged top to bottom.
PropertyTypeDescription
type"stack"
sectionsSectionConfig[]
gap?LayoutGap | undefined

GridLayoutConfig

Grid layout — sections arranged in columns.
PropertyTypeDescription
type"grid"
sectionsSectionConfig[]
columns1 | 2 | 3 | 4
gap?LayoutGap | undefined

SplitLayoutConfig

Split layout — left rail + right content area.
PropertyTypeDescription
type"split"
left?SectionConfig[] | undefined
rightSectionConfig[]
leftWidth?number | undefined
gap?LayoutGap | undefined
divider?boolean | undefined

SectionConfig

Union of all possible section types in a widget template. Sections are the building blocks of widget layouts. Combine them in WidgetTemplateConfig.sections or use recipe helpers like createSummaryListRecipe() to compose common patterns.
type SectionConfig = AlertSectionConfig | HeadlineStatSectionConfig | OverviewPanelSectionConfig | KPIRowSectionConfig | SummaryQuadSectionConfig | ListSectionConfig | RowListSectionConfig | StreamListSectionConfig | FilterBarSectionConfig | DenseRankedTableSectionConfig | TableSectionConfig | CardListSectionConfig | ChartSectionConfig | ActivityChartSectionConfig | TabsSectionConfig | StackLayoutConfig | GridLayoutConfig | SplitLayoutConfig

WidgetTemplateConfig

Top-level configuration for a template-driven widget. This is the primary config type that widget authors define. It declares which data sources to resolve and which sections to render in the compact and expanded views.
PropertyTypeDescription
version?number | undefined
dataSourcesDataSourceDeclaration[]
sectionsSectionConfig[]
expandedSections?SectionConfig[] | undefined
recipe?TemplateRecipeModel | undefined
expandedRecipe?TemplateRecipeModel | undefined
Example:
const config: WidgetTemplateConfig = {
  version: 1,
  dataSources: [{ id: "my-widget" }],
  sections: [
    kpiRow("my-widget", [{ label: "Total", field: "count" }]),
    list("my-widget", "items", { title: "name", subtitle: "status" }),
  ],
  expandedSections: [
    // Full table in expanded view
  ],
};

CreateTemplateDescriptorOptions

PropertyTypeDescription
catalogCategory?string | undefined
capabilities?WidgetCapability[] | undefinedCapability ownership declared by the widget. Use this for canonical or specialized shared surfaces.
requiredIntegrations?string[] | undefined
defaultSlot?GridSlot | undefined
auth?WidgetAuth | WidgetAuth[] | undefined
expandedSize?ModalSize | undefined
defaultPollInterval?number | undefined
pollingSourceIds?string[] | undefined
variants?{ id: string; name: string; config: WidgetTemplateConfig; isDefault?: boolean; }[] | undefined

./widget-types

WidgetModalSize

Size of the expanded widget overlay: “sm”, “md”, or “lg”.
type WidgetModalSize = "sm" | "md" | "lg"

GridSlot

The 9 content grid slots (3x3). Chrome widgets (TopBar, Tabs, KPIs, Ticker) are not slotted.
type GridSlot = "slot1" | "slot2" | "slot3" | "slot4" | "slot5" | "slot6" | "slot7" | "slot8" | "slot9"

WidgetRenderProps

Props every widget module component receives.
PropertyTypeDescription
widgetId?string | undefinedWidget registry identifier for observability and debug events.
projectSlugstring | nullActive project filter. null = “All” projects.
timeRange?TimeRange | undefinedActive dashboard time range.
configTConfigPer-instance configuration.
selectedDetailId?string | null | undefinedExternally controlled selected detail item ID (for URL state).
onSelectedDetailIdChange?((id: string | null) => void) | undefinedCalled when the selected detail changes (for URL state sync).
onFetchedAt?((fetchedAt: number | null) => void) | undefinedCalled by the widget to report its current data-fetch timestamp (unix seconds). WidgetSlot forwards this to WidgetCard for display in the header.
onRefetch?((refetch: (() => Promise<void>) | null) => void) | undefinedCalled by the widget to register its refetch function. WidgetSlot forwards this to WidgetCard as the refresh button handler.
activeVariantId?string | undefinedThe currently active variant id, resolved from instance config.
onConnectService?((serviceId: string) => void) | undefinedOpen Settings → Integrations for a specific service.

WidgetOAuthConfig

OAuth-specific config for providers that need the redirect flow.
PropertyTypeDescription
providerstringProvider key used in route paths (e.g., “github”, “google”).
scopesstring[]Scopes to request during authorization.
setupInstructions?string | undefinedInstructions for creating the OAuth app, shown above client credential fields. Use as placeholder.
normalizeOrigin?boolean | undefinedWhether to normalize *.localhost subdomains to plain localhost when building the callback URL shown in setup instructions. Set true for Google (rejects custom subdomains), false/omit for GitHub (accepts *.localhost as-is).

WidgetAuth

How a widget authenticates with its external API.
PropertyTypeDescription
id?string | undefinedUnique service identifier (required when a widget connects to multiple services).
name?string | undefinedDisplay name for this service (e.g., “Vercel”, “Linear”).
description?string | undefinedShort description of this service shown on onboarding cards.
type"none" | "api_key" | "oauth"Auth method: “api_key” = manual token entry, “oauth” = OAuth redirect flow, “none” = no auth.
fields?WidgetAuthField[] | undefinedFor api_key and oauth: fields to show in the credential input UI (client ID/secret for OAuth).
testEndpoint?string | undefinedAPI route path to test credentials (POST with ).
docsUrl?string | undefinedURL to the service’s docs for obtaining credentials.
oauth?WidgetOAuthConfig | undefinedOAuth-specific config. Required when type === “oauth”.

WidgetAuthField

A single credential input field in the widget card’s Connection section.
PropertyTypeDescription
keystringStorage key within the credential record (e.g., “authToken”).
labelstringDisplay label (e.g., “Auth Token”).
optional?boolean | undefinedWhether the field is optional in the generic save/test UI.
type"text" | "password" | "textarea" | "file"”password” = masked, “text” = visible, “textarea” = multi-line, “file” = file upload.
placeholder?string | undefinedPlaceholder text.
helpText?string | undefinedHelp text below the input.
accept?string | undefinedAccepted file extensions for type “file” (e.g., “.p8,.pem”).

WidgetDisplayContext

Context passed to dynamic widget functions like getDisplayName and getSourceIds.
PropertyTypeDescription
projectSlugstring | null
projectsProject[]
configTConfig

WidgetPollingConfig

PropertyTypeDescription
sourceIds?string[] | undefined
getSourceIds?((context: WidgetDisplayContext<TConfig>) => PollingSourceId[]) | undefined

WidgetTemplateVisualEditorBinding

PropertyTypeDescription
kind"template"
getConfig(context: WidgetDisplayContext<TConfig>) => unknown | null
setConfig(args: { config: TConfig; editorConfig: unknown; context: WidgetDisplayContext<TConfig>; }) => TConfig

WidgetVisualEditorBinding

type WidgetVisualEditorBinding = WidgetTemplateVisualEditorBinding<TConfig>

WidgetVariant

A named layout variant preset defined by the widget author.
PropertyTypeDescription
idstringStable identifier (e.g., “queries”, “overview”).
namestringDisplay name shown in the variant picker (e.g., “Queries”, “Overview”).
configTConfigThe full template config for this variant.
isDefault?boolean | undefinedMark one variant as the default when no activeVariant is set. First variant is used if omitted.

CustomVariant

A user-created variant stored in the per-instance widget config.
PropertyTypeDescription
idstring
namestring
configRecord<string, unknown>

WidgetExpandAction

Controls what happens when the user clicks the expand button on a widget.
type WidgetExpandAction = { type: "expanded-view"; } | { type: "open-plugin"; pluginId: string; }

WidgetDescriptor

Describes a widget template in the registry. Extends: ExtensionMeta
PropertyTypeDescription
idstringUnique identifier. Used as registry key and WidgetCard widgetId.
namestringDisplay name shown in WidgetCard header and settings UI.
descriptionstringShort description for settings UI (Phase 2).
version?string | undefinedSemver version string.
catalogCategory?string | undefinedCatalog grouping used by settings/widget library surfaces.
capabilities?WidgetCapability[] | undefinedCanonical or specialized capability ownership for this widget, plus the integration/action providers it supports.
requiredIntegrationsstring[]Integration keys that must be present on the active project for this widget to be relevant. Empty array = always available. When “All” projects is selected, all integrations are assumed present.
defaultSlotGridSlotDefault grid slot assignment.
componentComponentType<WidgetRenderProps<TConfig>>Compact view component. Rendered inside WidgetCard in the grid.
expandedComponent?ComponentType<WidgetRenderProps<TConfig>> | undefinedExpanded view component. Rendered inside ExpandedPortal when the widget is expanded. Optional.
defaultConfigTConfigDefault config for new instances.
variants?WidgetVariant<TConfig>[] | undefinedNamed layout variant presets. When defined, the config panel shows a variant picker. The variant with isDefault: true (or the first) is used when no activeVariant is set. Users can also duplicate variants for customization via the visual editor.
getDisplayName?((context: WidgetDisplayContext<TConfig>) => string) | undefinedOptional dynamic display name used in runtime surfaces like headers and config dialogs.
getDisplayDescription?((context: WidgetDisplayContext<TConfig>) => string) | undefinedOptional dynamic description used in config dialogs.
visualEditor?WidgetVisualEditorBinding<TConfig> | undefinedOptional visual editor binding for structured config editing.
auth?WidgetAuth | WidgetAuth[] | undefinedAuth requirements. Omit for widgets that don’t need external API access.
defaultPollInterval?number | undefinedDefault polling interval in milliseconds. Shown in the widget header next to the refresh button. Individual widgets can override this via their SWR refreshInterval. Omit for widgets that don’t poll (e.g. static data, logs with SSE).
polling?WidgetPollingConfig<TConfig> | undefinedOptional refresh-interval settings metadata for standard polling widgets.
expandedSize?ModalSize | undefinedOptional size override for the expanded overlay. Omit this to use the centralized widget default size (“md”). - “lg”: full viewport − 16px margin - “md”: centered, 90vw max-w-7xl × 80vh - “sm”: centered, 75vw max-w-3xl × 65vh
expandAction?WidgetExpandAction | undefinedControls what happens when the user clicks the expand button. - { type: "expanded-view" } (default): opens the in-place ExpandedPortal - { type: "open-plugin", pluginId }: navigates to the plugin overlay instead

Capability Governance

Use capabilities to describe widget ownership of shared Radarboard surfaces:
  • role: "canonical" means the widget is the primary surface for that capability.
  • role: "specialized" means the widget intentionally overlaps an existing capability without owning it.
  • providers must point at real integration/action pairs.
  • requiredIntegrations does not replace capabilities; it only controls relevance and availability filtering.
Canonical widgets can use capability metadata to resolve a provider at runtime. The Revenue and Observability widgets are the reference implementations.

./recipes

stackLayout()

Create a vertical stack layout from sections.
function stackLayout(sections: SectionConfig[], options?: { gap?: LayoutGap; } | undefined): StackLayoutConfig

gridLayout()

Create a multi-column grid layout from sections.
function gridLayout(sections: SectionConfig[], options: { columns: 1 | 2 | 3 | 4; gap?: LayoutGap; }): GridLayoutConfig

splitLayout()

Create a split layout with a left rail and right content area.
function splitLayout(options: { left?: SectionConfig[]; right: SectionConfig[]; leftWidth?: number; gap?: LayoutGap; divider?: boolean; }): SplitLayoutConfig

createSummaryContentRecipe()

Recipe: KPI summary strip + rich content area below.
function createSummaryContentRecipe(config: { summary: SectionConfig[]; content?: SectionConfig | SectionConfig[]; gap?: LayoutGap; }): SectionConfig[]

createSummaryOnlyRecipe()

Recipe: KPI metrics only — no content below. Good for status displays.
function createSummaryOnlyRecipe(config: { summary: SectionConfig[]; gap?: LayoutGap; }): SectionConfig[]

createContentOnlyRecipe()

Recipe: Content only — no KPI summary strip. Good for lists, tables, charts.
function createContentOnlyRecipe(config: { content: SectionConfig | SectionConfig[]; gap?: LayoutGap; }): SectionConfig[]

createSummaryListRecipe()

Recipe: KPI strip + scrollable list. The most common widget pattern.
function createSummaryListRecipe(config: { summary: SectionConfig[]; list: SectionConfig; gap?: LayoutGap; }): SectionConfig[]

createSummaryChartListRecipe()

Recipe: KPI strip + chart + scrollable list. Good for analytics dashboards.
function createSummaryChartListRecipe(config: { summary: SectionConfig[]; chart: SectionConfig; list: SectionConfig; gap?: LayoutGap; }): SectionConfig[]

createRailContentRecipe()

Recipe: Side rail + main content area. Good for detail views with navigation.
function createRailContentRecipe(config: { rail?: SectionConfig[]; content: SectionConfig | SectionConfig[]; railWidth?: number; gap?: LayoutGap; divider?: boolean; }): SectionConfig[]

createRailListRecipe()

Recipe: Side rail + scrollable list. Good for category browsing.
function createRailListRecipe(config: { rail?: SectionConfig[]; list: SectionConfig; railWidth?: number; gap?: LayoutGap; divider?: boolean; }): SectionConfig[]

createFeedListRecipe()

Recipe: Activity feed / timeline. Alias for content-only with feed semantics.
function createFeedListRecipe(config: { content: SectionConfig | SectionConfig[]; gap?: LayoutGap; }): SectionConfig[]

./section-helpers

kpiRow()

Create a KPI row with multiple metric cards.
function kpiRow(sourceId: string, metrics: { label: string; field: string; format?: DataSourceFormat; changeField?: string; sparklineField?: string; }[], options?: { columns?: KPIRowSectionConfig["columns"]; variant?: KPIRowSectionConfig["variant"]; } | undefined): KPIRowSectionConfig
Example:
kpiRow("revenue", [
  { label: "MRR", field: "mrr", format: "currency" },
  { label: "Subscribers", field: "subscriberCount" },
])

headlineStat()

Create a headline stat section — a large featured number.
function headlineStat(sourceId: string, field: string, label: string, options?: { format?: DataSourceFormat; indicatorColor?: string; } | undefined): HeadlineStatSectionConfig
Example:
headlineStat("health", "uptimePercent", "Uptime", { format: "percent" })

list()

Create a scrollable list section.
function list(sourceId: string, field: string, template: { title: string; subtitle?: string; value?: string; timestamp?: string; badge?: string; emptyMessage?: string; maxItems?: number; }): ListSectionConfig
Example:
list("github", "pullRequests", {
  title: "title",
  subtitle: "author",
  badge: "status",
  emptyMessage: "No open PRs",
})

rowList()

Create a row-list section (compact rows with status dots/icons).
function rowList(sourceId: string, field: string, template: { title: string; subtitle?: string; badge?: string; value?: string; timestamp?: string; emptyMessage?: string; maxItems?: number; }): RowListSectionConfig
Example:
rowList("sentry", "issues", {
  title: "title",
  subtitle: "culprit",
  badge: "level",
  timestamp: "lastSeen",
})

chart()

Create a chart section (area, line, bar, or sparkline).
function chart(sourceId: string, field: string, options?: { variant?: ChartSectionConfig["variant"]; height?: number; xKey?: string; yKey?: string; color?: string; series?: ChartSectionConfig["series"]; fillHeight?: boolean; } | undefined): ChartSectionConfig
Example:
chart("analytics", "dailyVisitors", { variant: "area", height: 200, color: "var(--accent)" })

cardList()

Create a card grid section for rich card layouts.
function cardList(sourceId: string, field: string, template: { title: string; subtitle?: string; description?: string; image?: string; badge?: string; columns?: CardListSectionConfig["columns"]; emptyMessage?: string; maxItems?: number; searchable?: boolean; }): CardListSectionConfig
Example:
cardList("store", "apps", {
  title: "name",
  subtitle: "developer",
  description: "summary",
  image: "iconUrl",
  columns: 2,
})

summaryQuad()

Create a 2x2 summary quad section.
function summaryQuad(sourceId: string, slots: ({ label: string; field: string; format?: DataSourceFormat; changeField?: string; sparklineField?: string; } | { kind: "empty"; })[]): SummaryQuadSectionConfig
Example:
summaryQuad("revenue", [
  { label: "MRR", field: "mrr" },
  { label: "ARR", field: "arr" },
  { label: "Churn", field: "churnRate" },
  { label: "LTV", field: "ltv" },
])

alert()

Create an alert/banner section.
function alert(severity: "error" | "warning" | "info" | "success" | "setup", message: string, options?: { source?: DataSource; dismissible?: boolean; action?: { label: string; href?: string; }; } | undefined): AlertSectionConfig
Example:
alert("warning", "API rate limit approaching 80%", { dismissible: true })

tabs()

Create a tabbed content section.
function tabs(tabConfigs: { id: string; label: string; sections: SectionConfig[]; countSource?: DataSource; }[], options?: { defaultTab?: string; variant?: "compact" | "expanded"; } | undefined): TabsSectionConfig
Example:
tabs([
  { id: "issues", label: "Issues", sections: [list("github", "issues", { title: "title" })] },
  { id: "prs", label: "Pull Requests", sections: [list("github", "prs", { title: "title" })] },
])

./testing

extractDataSources()

Extract all DataSource references from a section config tree. Returns a map of sourceId -> Set&lt;field&gt;.
function extractDataSources(sections: SectionConfig[]): Map<string, Set<string>>

createMockWidgetData()

Generate mock data that matches a WidgetTemplateConfig’s data source shape. Analyzes the section configs to determine which fields are arrays vs scalars, then generates appropriate mock data for each field.
function createMockWidgetData(config: WidgetTemplateConfig, itemCount?: number): Record<string, MockDataShape>
Example:
const mockData = createMockWidgetData(MY_TEMPLATE_CONFIG);
// { totalCount: 42, activeCount: 28, items: [{ title: "Item 1", ... }, ...] }

createEmptyWidgetData()

Generate empty data that matches a WidgetTemplateConfig’s shape. Arrays become [], numbers become 0, strings become "".
function createEmptyWidgetData(config: WidgetTemplateConfig): Record<string, MockDataShape>

createWidgetPreviewStates()

Generate all standard preview states for a widget. Use these to visually test your widget in every possible state — happy path, empty, loading, error, and unconfigured.
function createWidgetPreviewStates(config: WidgetTemplateConfig, overrides?: { happy?: T; } | undefined): WidgetPreviewStates<T>
Example:
const states = createWidgetPreviewStates(MY_CONFIG, {
  happy: myFetchedData,
});
// Iterate over states to render previews
for (const [name, data] of Object.entries(states)) {
  console.log(`${name}:`, data);
}

MockDataShape

Describes the shape of mock data generated for a data source.

WidgetPreviewStates

Standard widget preview states for visual testing.
PropertyTypeDescription
happyTHappy path — real or mock data.
emptyTEmpty state — all arrays empty, numbers 0.
loading{ loading: true; }Loading state indicator.
error{ error: string; }Error state indicator.
unconfigured{ data: null; }Unconfigured state — null data.