Stat View
The stat view renders a responsive grid of KPI cards. Values are computed server-side and embedded in the spec — the UI only formats and displays them.
Spec
const spec = new StatView()
.stat({ label: 'Revenue', value: 48290.50, format: 'currency' })
.stat({ label: 'Active Users', value: 1204, description: 'active this month' })
.stat({ label: 'Conversion', value: 0.0312, format: 'percent' })
.stat({ label: 'Storage Used', value: 5368709120, format: 'bytes' })
.title('Dashboard Overview')
.build();How it works
The SPA navigates to #/{resource}/stats and fetches a StatSpec from GET /api/ui/{resource}/stats. Each Stat object carries a pre-computed value — there is no client-side data fetching for individual metrics.
Basic setup (JS)
import { StatView } from '@retrofit-ui/builder-zod';
const spec = new StatView()
.stat({ label: 'Revenue', value: 48290.50, format: 'currency' })
.stat({ label: 'Active Users', value: 1204, description: 'active this month' })
.stat({ label: 'Conversion', value: 0.0312, format: 'percent' })
.stat({ label: 'Storage Used', value: 5368709120, format: 'bytes' })
.title('Dashboard Overview')
.build();
// URL prefix below is arbitrary — pick anything and match `apiBase` to it.
app.get('/dashboard/stats', (_req, res) => {
res.json(spec);
});Value formats
The format field controls how numeric values are displayed. String values are always rendered as-is.
format | Input | Output |
|---|---|---|
'number' (default) | 1204 | 1,204 |
'currency' | 48290.50 | $48,290.50 |
'percent' | 0.0312 | 3.1% |
'bytes' | 5368709120 | 5 GB |
Currency defaults to USD. Override with the currency field:
.stat({ label: 'Revenue', value: 48290.50, format: 'currency', currency: 'EUR' })
// → €48,290.50Locale formatting uses Intl.NumberFormat with the browser's locale — numbers, currency symbols, and decimal separators adapt automatically.
Description text
Each card accepts an optional description rendered below the label in muted text — useful for context like "vs last month" or units.
Spec
new StatView()
.stat({ label: 'Revenue', value: 9800.50, format: 'currency', description: 'vs last month' })
.stat({ label: 'Open Issues', value: 42, description: '↑ 3 since yesterday' })
.build();Stat with trend
Include a trend indicator in the description string to give at-a-glance context alongside the main value.
Spec
// The description field renders as muted plain text below the label.
// Include the arrow symbol in the string to convey trend direction.
new StatView()
.stat({ label: 'Revenue', value: 48290, format: 'currency',
description: '▲ 12% vs last month' })
.stat({ label: 'Conversion', value: 0.031, format: 'percent',
description: '▼ 0.4% vs last week' })
.stat({ label: 'Active Users', value: 1204,
description: '▲ 48 since yesterday' })
.build()Page title
Use .title() to render a heading above the grid:
new StatView()
.stat({ label: 'Revenue', value: 48290.50, format: 'currency' })
.title('Dashboard Overview')
.build();String values
If your metric is already formatted (e.g. from an external service), pass a string — it renders as-is:
.stat({ label: 'Uptime', value: '99.98%' })
.stat({ label: 'Build', value: 'Passing' })Using the standalone renderer
The stat view can be embedded outside the SPA using the renderer bundle:
<script src="retrofit-ui.iife.js"></script>
<!-- declarative island — auto-mounted by init() -->
<div data-retrofit='{"kind":"stat","stats":[{"label":"Revenue","value":48290.50,"format":"currency"},{"label":"Users","value":1204}],"metadata":{"title":"Overview"}}'></div>
<!-- or mount explicitly in JS -->
<div id="dashboard"></div>
<script>
const ui = RetrofitUI.init({ rootElement: document.body, apiBase: '/api' });
ui.mount(
{
kind: 'stat',
stats: [
{ label: 'Revenue', value: 48290.50, format: 'currency' },
{ label: 'Users', value: 1204 },
],
metadata: { title: 'Overview' },
},
document.getElementById('dashboard'),
);
</script>