DashboardConfig
The JSON contract that drives a dashboard — fully serializable, validated with
Zod. parseDashboardConfig()
throws on an invalid shape; safeParseDashboardConfig() returns a result object
instead.
Top level
interface DashboardConfig {
$schema?: string;
version: string;
settings: DashboardSettings;
globalFilters: GlobalFilter[];
calculatedFields: CalculatedField[];
columnLabels: Record<string, string>;
widgets: Widget[];
}
settings
interface DashboardSettings {
title: string;
description?: string;
layout: { columns: number; rowHeight: number; gutter: number; responsiveBreakpoints?: Record<string, number> };
theme?: {
mode?: 'light' | 'dark' | 'auto';
primaryColor?: string;
fontFamily?: string;
borderRadius?: string;
echartsTheme?: string | Record<string, unknown>;
};
numberFormat?: { locale?: string; currencySymbol?: string };
}
globalFilters
Date-range, multi/single-select, text, or number-range controls that any widget can bind to via dataQuery.filterRefIds.
interface GlobalFilter {
id: string;
field: string;
type: 'date_range' | 'multi_select' | 'single_select' | 'text' | 'number_range';
label: string;
defaultValue?: unknown;
}
calculatedFields
Derived columns computed per-row from a small, deliberately non-Turing-complete arithmetic
grammar (+ - * / ( ), field references, numeric literals) — no eval.
interface CalculatedField {
id: string;
label: string;
formula: string; // e.g. "amount - previous_amount"
format?: 'number' | 'currency' | 'percentage';
}
columnLabels
A dataset-wide display name per field (e.g. created_at → "Order Date"), used as
the table header / chart axis / legend / tooltip label anywhere that field appears, across
every widget. Set once in Settings instead of relabeling the same field everywhere.
dataQuery (on a widget)
interface DataQuery {
dimensions?: { field: string; granularity?: 'second'|'minute'|'hour'|'day'|'week'|'month'|'quarter'|'year' }[];
metrics?: { field: string; aggregation: 'sum'|'avg'|'min'|'max'|'count'|'none'; alias?: string }[];
sort?: { field: string; direction: 'asc' | 'desc' }[];
pagination?: { pageSize: number };
filterRefIds?: string[];
}
See Widgets & charts for each widget's renderConfig shape.