[data-reveal]{opacity:1!important;transform:none!important}
CMS Interfaces

Charts and Widgets

Overview

The chart module and the three card modules cover dashboard surfaces: a chart of a series, a single figure with a delta, a ranked list, and the period selector the others read their date range from. Each one is a builder that produces a component description; each one either carries its data inline (staticDataset, staticItems, staticValue) or names a fetchUrl the frontend calls.

All of them are exported from the package root; the charts also have their own subpath.

import {
  ChartArea,
  ChartCard,
  KpiCard,
  PeriodSelector,
  TopListCard,
} from "@antelopejs-private/cms/interfaces/cms-base";
// charts only
import { ChartLine, ChartType } from "@antelopejs-private/cms/interfaces/cms-base/chart";

A Dashboard in One Page

The widgets compose through the layout builders from Layout and Containers. One PeriodSelector declares a scope id; every widget that names the same periodScope follows its range.

import {
  PageController,
  pagesCategory,
  RegisterPage,
} from "@antelopejs-private/cms/interfaces/cms/page";
import {
  ChartArea,
  ChartCard,
  KpiCard,
  PeriodSelector,
  TopListCard,
} from "@antelopejs-private/cms/interfaces/cms-base";
import { Grid, GridRow } from "@antelopejs-private/cms/interfaces/cms-base/grid";
import { DefaultLayout } from "@antelopejs-private/cms/interfaces/cms-base/layouts";

const SCOPE_ID = "ai-overview";

@RegisterPage()
export class OverviewPage extends PageController(
  "overview",
  { displayName: "Overview", icon: "i-ph-chart-line", category: pagesCategory },
  DefaultLayout({ fullWidth: true }),
) {
  static periodSelector = PeriodSelector({
    id: SCOPE_ID,
    align: "right",
    defaultPreset: "last-7-days",
    defaultComparison: "previous-period",
    presets: ["today", "last-7-days", "last-30-days"],
  });

  static kpis = Grid({ gap: "1rem" }).child(
    "kpiRow",
    GridRow().child(
      "actions",
      KpiCard({
        title: "Actions",
        icon: "i-ph-lightning",
        fetchUrl: "/ai/metrics/kpi/actions",
        periodScope: SCOPE_ID,
        valueFormat: "compact",
        compareLabel: "vs previous period",
      }),
    ),
  );

  static activityRow = Grid({ gap: "1rem" }).child(
    "row",
    GridRow()
      .child(
        "activityChart",
        ChartCard({
          title: "AI activity",
          description: "Actions over the selected period",
          icon: "i-ph-chart-line",
          fetchUrl: "/ai/metrics/series",
          periodScope: SCOPE_ID,
          valueFormat: "compact",
          chart: ChartArea({ xaxisType: "datetime" }),
        }),
        { colSpan: 2 },
      )
      .child(
        "topSkills",
        TopListCard({
          title: "Top skills",
          fetchUrl: "/ai/metrics/top-skills?limit=5",
          periodScope: SCOPE_ID,
        }),
      ),
  );
}

Chart Builders

There is one builder per chart type. Each takes its own props with the type discriminant optional — the builder fills it in — and returns a ComponentBuilder for that props type.

BuilderChartTypeProps interface
ChartLineLINELineChartProps
ChartAreaAREAAreaChartProps
ChartRangeAreaRANGE_AREARangeAreaChartProps
ChartBarBARBarChartProps
ChartColumnCOLUMNColumnChartProps
ChartScatterSCATTERScatterChartProps
ChartMixedMIXEDMixedChartProps
ChartRadarRADARRadarChartProps
ChartCandlestickCANDLESTICKCandlestickChartProps
ChartDonutDONUTDonutChartProps
ChartPiePIEPieChartProps
ChartRadialBarRADIAL_BARRadialBarChartProps
ChartHeatmapHEATMAPHeatmapChartProps

ChartType is the enum behind the discriminant: LINE, AREA, RANGE_AREA, BAR, COLUMN, SCATTER, DONUT, PIE, MIXED, RADAR, RADIAL_BAR, HEATMAP, CANDLESTICK. AnyChartProps is the union of all thirteen props interfaces.

Every builder gives the component a display name from title, falling back to the chart's own name ("Line Chart", "Donut Chart", …), and a matching icon.

Common Options

Every chart props interface extends BaseComponentProps and adds:

OptionTypeDescription
titlestringChart title, also the component display name.
descriptionstringChart description.
colorChartColorOne colour or a colour list.
heightstringCSS height.
widthnumberWidth.
showTooltipbooleanShow the value tooltip.
showLegendbooleanShow the series legend.
fetchUrlstringURL the chart loads its data from.
fetchUrlMethodHttpMethodMethod for fetchUrl.
periodScopestringId of the PeriodSelector whose range this chart follows.
realtimeTopicstring | string[]Realtime topics to subscribe the page to.
rawOptionsKeyValuePair[]Escape hatch: extra key/value options passed through to the chart renderer.
rawCssKeyValuePair[]Escape hatch: extra key/value CSS declarations.

KeyValuePair is { key: string; value: string }.

When realtimeTopic is set, the builder registers each topic against the page it is declared on, using RegisterPageTopic from the cms interface.

Cartesian Charts

LineChartProps, AreaChartProps, RangeAreaChartProps, BarChartProps, ColumnChartProps, ScatterChartProps, MixedChartProps, RadarChartProps and CandlestickChartProps share a second layer of options on top of the common ones:

OptionTypeDescription
staticDatasetChartSeries[]Inline data, as an alternative to fetchUrl.
showGridbooleanDraw the background grid.
yRange{ min: number; max: number }Fixed Y bounds.
comparisonStyleComparisonStyleHow the comparison series is drawn: "dashed", "solid" or "dimmed".
smoothbooleanSmooth the line between points.
curveChartCurveLine interpolation, honoured by the line, area, rangeArea and mixed types. Takes precedence over smooth when both are set.
annotationsChartAnnotation[]Horizontal reference lines on the Y axis.
syncGroupstringCharts sharing a group name share their crosshair and tooltip position.
xaxisType"category" | "datetime" | "numeric"Interpretation of the X values.

And each adds its own:

PropsExtra options
LineChartPropsstrokeWidth?: number
AreaChartPropsfillOpacity?: number, stacked?: boolean
RangeAreaChartPropsfillOpacity?: number
BarChartPropsstacked?: boolean, barWidth?: number, roundedCorners?: boolean, orientation?: AxeOrientation
ColumnChartPropsstacked?: boolean, columnWidth?: number, roundedCorners?: boolean
ScatterChartPropspointSize?: number, showLabels?: boolean
MixedChartPropsseriesDefs?: MixedChartSeriesDef[]
RadarChartPropsfillOpacity?: number
CandlestickChartProps

MixedChartSeriesDef declares how one series of a mixed chart is drawn: { name: string; type: ChartType.LINE | ChartType.AREA | ChartType.COLUMN | ChartType.RANGE_AREA; color?: ChartColorValue }.

ChartCurve is "smooth" | "straight" | "stepline". Prefer it to smooth, which only chooses between the first two.

ChartAnnotation draws a horizontal reference on the Y axis — a spend cap, a max bound, a volume capacity:

FieldTypeDescription
ynumberValue the line sits at. Required.
y2numberSet it to shade the band between y and y2 instead of drawing a line.
labelstringText on the annotation.
colorChartColorValueAnnotation colour.
dashedbooleanDraw the line dashed.

syncGroup is what turns a grid of separate metrics into one readable timeline: give every chart on the page the same group name and hovering one moves the crosshair on all of them.

Circular Charts

CircularChartProps extends the common options with staticDataset?: DonutRecord[] — a flat list of { label: string; value: number } rather than series.

PropsExtra options
DonutChartPropscentralLabel?: string, centralSubLabel?: string, arcWidth?: number
PieChartProps
RadialBarChartPropshollowSize?: string, showTotal?: boolean

Heatmap

HeatmapChartProps extends the common options directly — not the cartesian layer — with staticDataset?: ChartSeries[], shadeIntensity?: number and distributed?: boolean.

Series and Points

import type {
  ChartCandlePoint,
  ChartSeries,
  ChartSeriesPoint,
} from "@antelopejs-private/cms/interfaces/cms-base/chart";

const series: ChartSeries[] = [
  {
    name: "Actions",
    data: [
      { x: "2026-07-01", y: 12 },
      { x: "2026-07-02", y: 18 },
      { x: "2026-07-03", y: null },
    ],
  },
];
TypeShape
ChartSeriesname: string, data: Array<ChartSeriesPoint | ChartCandlePoint | ChartRangePoint | number>, type?: ChartType, color?: ChartColorValue
ChartSeriesPointx: string | number | Date, y: number | null, label?: string
ChartCandlePointx: string | number | Date, y: [number, number, number, number]
ChartRangePointx: string | number | Date, y: [number, number] — the low and high bound a range area fills between
DonutRecordlabel: string, value: number

A null y marks a gap. ChartSeries.type overrides the chart's own type for that series, which is what a mixed chart uses.

Colours and Formats

TypeValues
ColorName"primary", "secondary", "success", "info", "warning", "error", "neutral", "accent"
ChartColorValueColorName or a #…, rgb… or hsl… string
ChartColorChartColorValue | ChartColorValue[]
ComparisonStyle"dashed", "solid", "dimmed"
ValueFormat"number", "currency", "percent", "compact"

ColorName is the chart palette and is distinct from the Color enum in Shared Types: it adds accent and it is a string union rather than an enum. ValueFormat is used by the three card components rather than by the charts themselves.

Chart Events

Namespace memberValue
ChartEvents.SEGMENT_CLICK"CmsComponent.Chart.SegmentClick"
ChartEvents.POINT_CLICK"CmsComponent.Chart.PointClick"

ChartCard

ChartCard wraps a chart in a card that owns the title, the fetch URL and the delta display, and holds the chart as a child under the id "chart".

import { ChartArea, ChartCard } from "@antelopejs-private/cms/interfaces/cms-base";

const card = ChartCard({
  title: "Revenue",
  description: "Billed amount over the selected period",
  icon: "i-ph-currency-eur",
  fetchUrl: "/metrics/revenue",
  periodScope: "finance",
  valueFormat: "currency",
  currencyCode: "EUR",
  showDelta: true,
  chart: ChartArea({ xaxisType: "datetime" }),
});

ChartCardBuilderOptions is ChartCardProps plus one required field, chart: Component. The chart is taken out of the options and attached as the card's child, so the serialized card options are exactly ChartCardProps.

ChartCardProps extends BaseComponentProps:

OptionTypeDescription
titlestringCard title. Required; also the component display name.
descriptionstringCard description.
iconstringCard icon. Defaults to "i-ph-chart-line" for the component metadata.
fetchUrlstringURL the card loads its data from.
fetchUrlMethodHttpMethodMethod for fetchUrl.
periodScopestringId of the PeriodSelector to follow.
valueFormatValueFormatHow the headline value is formatted.
currencyCodestringCurrency for valueFormat: "currency".
showDeltabooleanShow the change against the comparison period.
showLegendbooleanShow the legend.
primaryLabelstringLabel of the primary series.
comparisonLabelstringLabel of the comparison series.

KpiCard

KpiCard shows a single figure with an optional delta and sparkline.

import { KpiCard } from "@antelopejs-private/cms/interfaces/cms-base";

const denied = KpiCard({
  title: "Denied",
  icon: "i-ph-prohibit",
  fetchUrl: "/ai/metrics/kpi/denied",
  valueFormat: "compact",
  invert: true,
  compareLabel: "vs previous period",
});

KpiCardProps extends BaseComponentProps:

OptionTypeDescription
titlestringCard title. Required; also the component display name.
variant"default" | "stat""stat" is the compact look: mono uppercase label, bare icon.
descriptionstringCard description.
iconstringCard icon. Defaults to "i-ph-trend-up" for the component metadata.
fetchUrlstringURL the card loads its value from.
fetchUrlMethodHttpMethodMethod for fetchUrl.
periodScopestringId of the PeriodSelector to follow.
valueFormatValueFormatHow the value is formatted.
currencyCodestringCurrency for valueFormat: "currency".
showDeltabooleanShow the change against the comparison period.
showSparklinebooleanShow the sparkline.
sparklineAccentChartColorValue | "auto"Sparkline colour.
invertbooleanTreat an increase as bad — for metrics where lower is better.
compareLabelstringLabel next to the delta.
staticValuenumberInline value, as an alternative to fetchUrl.
staticDeltanumberInline delta.
staticSparklinenumber[]Inline sparkline points.

TopListCard

TopListCard shows a ranked list of items, each with a value and optionally a delta, a sparkline and an avatar.

import { TopListCard } from "@antelopejs-private/cms/interfaces/cms-base";

const topSkills = TopListCard({
  title: "Top skills",
  description: "Most-used tools over the selected period",
  fetchUrl: "/ai/metrics/top-skills?limit=5",
  periodScope: "ai-overview",
  showRank: true,
  highlightTopN: 3,
});

TopListCardProps extends BaseComponentProps:

OptionTypeDescription
titlestringCard title. Required; also the component display name.
descriptionstringCard description.
fetchUrlstringURL the card loads its items from.
fetchUrlMethodHttpMethodMethod for fetchUrl.
periodScopestringId of the PeriodSelector to follow.
valueFormatValueFormatHow each item's value is formatted.
currencyCodestringCurrency for valueFormat: "currency".
showRankbooleanShow the rank number.
highlightTopNnumberHow many leading items are highlighted.
rankColorChartColorValueColour of the rank marker.
showDeltabooleanShow each item's delta.
showSparklinebooleanShow each item's sparkline.
sparklineAccentChartColorValue | "auto"Sparkline colour.
invertbooleanTreat an increase as bad.
badgeColorChartColorValueColour of the value badge.
maxHeightstringCSS max-height before the list scrolls.
staticItemsTopListItem[]Inline items, as an alternative to fetchUrl.
emptyLabelstringText shown when there are no items.

TopListItem is the item shape, the element type of staticItems:

FieldTypeDescription
idstring | numberItem identifier. Required.
titlestringItem label. Required.
valuenumberItem value. Required.
descriptionstringSecondary line.
deltanumber | nullChange against the comparison period.
sparklinenumber[]Sparkline points.
iconstringLeading icon.
avatarTopListItemAvatarLeading avatar, { src: string; alt?: string }.
tostringLink target for the item.

PeriodSelector

PeriodSelector owns a date range and a comparison mode, and publishes them under its id. Every widget carrying the same value in periodScope uses that range.

import { PeriodSelector } from "@antelopejs-private/cms/interfaces/cms-base";

const selector = PeriodSelector({
  id: "finance",
  align: "right",
  defaultPreset: "this-month",
  defaultComparison: "previous-year",
  presets: ["this-month", "last-month", "ytd", "custom"],
  presetLabels: { ytd: "Year to date" },
  showRangeLabel: true,
});

PeriodSelectorProps extends BaseComponentProps:

OptionTypeDescription
idstringScope identifier other widgets name in periodScope. Required.
defaultPresetPeriodPresetPreset selected initially.
defaultComparisonPeriodComparisonComparison selected initially.
presetsPeriodPreset[]Presets offered.
comparisonsPeriodComparison[]Comparisons offered.
presetLabelsPartial<Record<PeriodPreset, string>>Overrides for preset labels.
comparisonLabelsPartial<Record<PeriodComparison, string>>Overrides for comparison labels.
alignPeriodAlign"left", "center" or "right".
size"xs" | "sm" | "md" | "lg" | "xl"Control size.
showRangeLabelbooleanShow the resolved date range as text.
variantPeriodSelectorVariant"default" or "segmented".

PeriodPreset is "last-hour", "last-24h", "today", "yesterday", "last-7-days", "last-30-days", "last-90-days", "this-month", "last-month", "this-quarter", "last-quarter", "ytd", "last-year" or "custom". PeriodComparison is "none", "previous-period", "previous-year" or "custom". PeriodAlign is "left" | "center" | "right".

PeriodSelectorVariant is "default" | "segmented". segmented renders the presets as inline pills for one-click range switching; the custom range stays in its popover calendar either way.

Next Steps