Skip to Content
This documentation is provided with the HEAT environment and is relevant for this HEAT instance only.
RunnersSystem UtilsArbex API referenceLayout and ComposableChart

Layout and ComposableChart

heat.layout builds v2 layoutConfiguration JSON for heat-system-next-dimension. Layout channels arrays must list the same string ids you used in heat.dataservice channel specs.

Two ways to supply layout:

ApproachWhereBest for
ProductionlayoutConfiguration on the dimension nodeStable dashboards, template review
IterationsuggestedLayoutConfiguration on arbex buildRoot() + dimension layoutFromParentOutput: truePrototyping in script without editing dimension JSON

Layout builder basics

const layout = heat.layout .createBuilder({ version: "1.0.0", realms: ["default"], configuration: { enableGlobalPlaybackControls: true, enableLiveDataPolling: false, defaultRealm: "default", showRealmFilterDropdown: false, }, }) .addRow() .addColumn("BarChart", { name: "Pods", titleContent: "Pod counts", channels: ["cluster-kpis"], colspan: 6, barChartItem: { /* widget-specific keys */ }, }) .build();
APIWhy
createBuilder(options?)Page-level playback, realm filter, default realm
addRow(opts?)New grid row (category, tab, title, collapsible, …)
addColumn(componentId, config)Single-widget columns (BarChart, MapDisplay, StatsSummary, …)
build()Final layout object

Each widget type uses a dedicated config key (barChartItem, mapDisplayItem, flightPathItem, …). See Next dashboard components for per-widget contracts.


ComposableChart (preferred for multi-lane charts)

Why ComposableChart: one column, shared time (or index) axis, multiple stacked slices (area, events lane, ranges lane, legend, static values), each bound to dataservice channel ids.

Fluent flow:

.addComposableChart({ name: "MainChart", titleContent: "Metrics", channels: ["synthetic-metric"], // must match ds channel id(s) colspan: 12, }) .anchor("time") // "time" | "index" | "none" .xAxis({ timeLabelMode: "elapsed" }) // optional .addAreaSlice({ label: "Series", height: 220, order: 1 }) .addSeries({ id: "line-1", label: "Synthetic metric", channel: "synthetic-metric", color: "#38BDF8", render: "line", }) .yAxis({ domain: [0, 100] }) .endComposableChart()

Slice helpers

MethodUse for
addAreaSliceLine or step series (addSeries, yAxis)
addScatterSliceScatter points
addEventsLaneSliceBoolean events (addEventSeries)
addRangesLaneSliceInterval bands
addLegendSliceLegend items (addLegendItem)
addSpanningLinesSliceVertical markers (times([...]))
addStaticSliceValue channels (KPI-style)
addPlaybackSlice()Throws in production; use page-level enableGlobalPlaybackControls

Return to the row builder with endComposableChart().


Ship layout with data from one run

const ds = heat.dataservice.createBuilder({ defaultRealm: "default" }); ds.addGroup("demo", "Demo"); ds.series({ id: "synthetic-metric", name: "Metric", groupId: "demo" }, points); const layout = heat.layout.createBuilder({ version: "1.0.0", realms: ["default"] }) .addRow() .addComposableChart({ name: "c", titleContent: "Chart", channels: ["synthetic-metric"], colspan: 12 }) .anchor("time") .addAreaSlice({ height: 220, order: 1 }) .addSeries({ id: "s1", label: "Metric", channel: "synthetic-metric" }) .endComposableChart(); return ds.buildRoot({ suggestedLayoutConfiguration: layout });

Enable on the arbex node:

{ "dataserviceOutput": { "enabled": true, "persistence": "dataservice-root", "layoutOutput": { "enabled": true, "require": true } } }

On heat-system-next-dimension: layoutFromParentOutput: true. Preset: sample-arbex-composable-dashboard. Script: sample-arbex-composable-dashboard.js.


Deprecated widgets

TimelineChart via addColumn("TimelineChart", …) is deprecated for new layouts. Prefer ComposableChart. See TimelineChart.