Skip to main content
View as Markdown

KPI Cards

The kpi component — a single summary metric, with an optional comparison, sparkline and thresholds.

A KPI card states one number. It aggregates the records its dataSource binds and formats the result.

Path Kind Values Default Description
label string Descriptive text displayed above the KPI metric value
icon string Lucide icon name displayed alongside the KPI metric (e.g., dollar-sign)

dataSource

Path Kind Values Default Description
dataSource object Data binding for the KPI: a DB table (aggregated client-side) OR a system read endpoint (pre-computed scalar value-path)
dataSource.table string Table to bind to: a declared name (validated against app.tables), or a $param.<name> route reference declared by the page path
dataSource.fields array Specific fields to fetch from the table
dataSource.fields[] string One field name, spelled as the bound table declares it
dataSource.mode enum list, single, search Data fetching mode: 'list' (multiple), 'single' (one record), 'search' (interactive)
dataSource.filter array Filter conditions applied with AND logic
dataSource.filter[] object (truncated) Single filter condition for data source queries
dataSource.sort array Sort rules applied in order
dataSource.sort[] object (truncated) Single sort rule for data source queries
dataSource.pagination object Pagination configuration for data source
dataSource.pagination.pageSize number Number of records per page
dataSource.pagination.style enum numbered, loadMore, infinite How pagination controls are displayed (default: numbered). infinite is accepted but not implemented and pages as numbered.
dataSource.param string Route parameter name for single mode (e.g., slug, id)
dataSource.searchEngine enum client, fts, trigram, hybrid Search backend for this data source (default: 'client'). Only 'client' is dispatched today; the other three validate and search as 'client' does.
dataSource.searchFields array Fields to search across in search mode
dataSource.searchFields[] string One field name the search term is matched against
dataSource.debounceMs number Debounce delay for search input (ms)
dataSource.limit number Maximum number of results to return
dataSource.targetId string Publisher-side identifier for cross-component references — addressable by a FilterAction (targetDataSource) and by a sibling subscriber's bindTo (shared filter/period state)
dataSource.bindTo string ID of a publisher component whose value drives this data source (cross-component binding). By default a search-input whose query string drives the search; when sharedFilter is also set, a shared filter/period selector whose published params are merged into every request
dataSource.sharedFilter object Companion to bindTo: the bound publisher is a shared filter/period selector whose published params are merged into every request this data source issues. One selector can drive many sibling subscribers. Inert without bindTo.
dataSource.sharedFilter.params array (truncated) Request-param keys this subscriber consumes from the shared publisher's value bag (omit to merge the full bag verbatim)
dataSource.refreshMode enum none, poll, realtime Data refresh strategy for this binding (default: 'none'). 'poll' uses pollIntervalMs; 'realtime' subscribes to live change events.
dataSource.pollIntervalMs number 30000 Polling interval in milliseconds for refreshMode: poll (min 1000, max 300000). Defaults to 30000 when omitted, and is ignored unless refreshMode is 'poll'.
dataSource.system object Read-endpoint binding: read a single pre-computed scalar (or a value template) from a system endpoint instead of aggregating a DB table
dataSource.system.endpoint string Read endpoint path to fetch the scalar from (e.g. /api/admin/overview)
dataSource.system.valuePath string Dotted path to a single scalar in the fetched envelope
dataSource.system.valueTemplate string Template interpolating {dotted.path} tokens from the fetched envelope
dataSource.system.query object Static query params merged into the request to the endpoint

autoSave

Path Kind Values Default Description
autoSave object Configuration for automatic persistence of edits. Applies to table, form, kanban, and calendar components.
autoSave.saveMode enum auto, onBlur, manual Save trigger strategy: 'auto' (debounced), 'onBlur' (field blur), 'manual' (button). Default: 'manual'.
autoSave.autoSaveDebounceMs number Debounce delay for auto-save in milliseconds (default: 500, min: 100)
autoSave.showSaveIndicator boolean Display a save status indicator (Saving... / Saved / Error). Default: true when saveMode is auto or onBlur.
autoSave.saveIndicatorPosition enum inline, toast, toolbar Where the save status indicator appears
Path Kind Values Default Description
search object Shared search bar configuration for data-bound components (table, kanban, calendar)
search.enabled boolean Enable search bar (default: true)
search.placeholder string Search input placeholder text
search.debounceMs number Debounce delay for search input in ms (default: 300)
search.highlight boolean Highlight matched search terms in results (default: false)

kpiAggregate

Path Kind Values Default Description
kpiAggregate object Aggregate function configuration for KPI metric computation
kpiAggregate.function enum count, sum, avg, min, max Aggregate function applied to compute the KPI metric value
kpiAggregate.field string Field to aggregate (omit for count)

trend

Path Kind Values Default Description
trend object Trend comparison showing change direction and percentage from a previous period
trend.comparisonPeriod enum previousDay, previousWeek, previousMonth, previousQuarter, previousYear Time period to compare the current metric value against
trend.direction enum up, down, flat Direction of change compared to the previous period
trend.changePercent number Percentage change from the comparison period
trend.color enum green, red, yellow, gray Color indicating whether the trend is positive, negative, or neutral

kpiFormat

Path Kind Values Default Description
kpiFormat object Display formatting configuration for the KPI metric value
kpiFormat.type enum number, currency, percentage, compact, bytes Display format for the KPI metric value
kpiFormat.options object Additional format options (e.g., { currency: "USD" })

thresholds

Path Kind Values Default Description
thresholds array Conditional color thresholds for KPI value
thresholds[] object Conditional color threshold — applied when the metric value meets or exceeds the boundary
thresholds[].value number Threshold boundary value
thresholds[].color enum red, green, yellow, blue, gray Colour applied when the metric value meets this boundary

sparkline

Path Kind Values Default Description
sparkline object Mini line chart showing recent trend for the KPI metric
sparkline.field string Field to plot in the sparkline
sparkline.groupBy string Date field for grouping data points
sparkline.interval enum day, week, month Date grouping interval for sparkline data points
sparkline.days number Number of trailing days of data to show

label is the metric's name and icon draws beside the value. kpiAggregate is { function, field }function is required, and field is omitted for count. kpiFormat is { type, options }, where type is number, currency, percentage, compact or bytes. thresholds are { value, color } entries that recolour the card once a value is crossed, over red, green, yellow, blue and gray.

app.yaml
tables:
  - name: orders
    fields:
      - { name: total, type: currency, currency: EUR }
      - { name: created_at, type: created-at }
pages:
  - name: Revenue
    path: /revenue
    components:
      - type: kpi
        label: Revenue this month
        icon: banknote
        dataSource: { table: orders }
        kpiAggregate: { function: sum, field: total }
        kpiFormat: { type: currency, options: { currency: EUR } }
        trend: { comparisonPeriod: previousMonth, direction: up, changePercent: 12.4, color: green }
        sparkline: { field: total, groupBy: created_at, interval: day, days: 30 }

trend

All three of comparisonPeriod, direction and changePercent are required once trend is present. comparisonPeriod is previousDay, previousWeek, previousMonth, previousQuarter or previousYear; direction is up, down or flat; changePercent is the change as a number; and color is green, red, yellow or gray.

direction and color are independent on purpose. Revenue up is green; churn up is red. Sovrium will not guess which of your metrics improve by rising, so state the colour you mean.

sparkline

All four properties are required once sparkline is present: field is plotted along the line, groupBy buckets the points, interval is day, week or month, and days is how far back the line covers.

Behaviour

KPI Card

  • type: 'kpi' is a valid component type in page components
  • dataSource with aggregate (count/sum/avg/min/max) computes metric value
  • label displays descriptive text above the metric value
  • format.type (number/currency/percentage/compact) controls display format
  • icon renders a Lucide icon name alongside the metric
  • trend shows comparison arrow (up/down), percentage change, and color
  • A metric takes a threshold's colour only once it meets that boundary
  • A threshold colour outside the drawable vocabulary is refused
  • User can complete full KPI card workflow (regression)

KPI Grid Layout

  • Multiple KPI cards render in a responsive grid layout
  • Grid column count adapts per breakpoint (1 mobile, 2-4 desktop)
  • sparkline renders a mini line chart showing recent trend for the metric
  • thresholds apply conditional color to the metric value based on thresholds
  • A sparkline on a system binding is refused outright rather than drawn empty
  • User can complete full KPI grid workflow (regression)

KPI on Public Pages (Anonymous Visitors)

  • KPI label is server-rendered as visible text in the SSR HTML (not only inside data-island-props)
  • Anonymous visitor on a public page sees the label and a graceful value; no KpiError region replaces it
  • User can complete the full public/anonymous KPI workflow (regression)

Last updated September 23, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.

Built with Sovrium