Dashboards
Eight ready-made dashboard screens — a skin-dependent home plus five dedicated views — composed from the widget library, charts, and the token system.
Overview
The template ships eight dashboard screens. They are not one configurable dashboard — each is a hand-composed page that demonstrates a different layout idiom and data-visualization style:
| Screen | Route | Chart libs | What it shows |
|---|---|---|---|
CRM (CrmDashboard) | / (default home) | none (motion bars) | StatCard KPI grid, a sales-pipeline funnel (animated width bars), lead sources, a recent-deals table. |
Bento (BentoDashboard) | / (when skin = bento) | none (motion bars) | A greeting hero + a mixed-size tile grid (oversized revenue tile, metric tiles, chart tile, traffic, activity, top products). |
Console (ConsoleDashboard) | / (when skin = console) | none (motion bars) | A command-prompt bar, dense left-accent KPI cells, a terminal-styled log feed, live system metrics, and an orders table — the bespoke dashboard for the Console design. |
| Analytics | /dashboards/analytics | ECharts (+ Chart.js) | Sparkline KPI strip, a traffic-by-channel stacked area with 7d/30d/12m tabs, a realtime card, a user-flow Sankey, acquisition breakdown, an engagement scatter, devices donut, a GitHub-style calendar heatmap, top countries, a bento "Highlights" grid, and a rich top-pages table with filter toolbar. |
| eCommerce | /dashboards/ecommerce | ECharts + ApexCharts | KPI strip, a revenue + orders dual-axis combo, a sales funnel, a category treemap, traffic donut, store-goals radialBar, top products (photos + progress), order-status breakdown, a recent-orders Panel table with row actions, and an activity timeline. |
| Project | /dashboards/projects | ApexCharts + ECharts | KPI strip, a project-timeline Gantt (rangeBar), sprint burndown, completion gauge, priority breakdown, a team-workload radar, activity feed, a Kanban board strip fed by the real scrumboard seed, per-member workload, and a milestones timeline. |
| Finance | /dashboards/finance | Chart.js + ApexCharts | Welcome hero + 8 mini stat tiles, gradient KPI strip, a report panel, a net-profit bubble chart, expense donut, revenue-vs-expenses grouped bars, a transactions Panel with an Apex heatmap, a payment-schedule mini calendar + alerts rail, and an insights row (budget gauge, income sources, cash flow, revenue streams, top clients). |
| Marketing | /dashboards/marketing | Chart.js | KPI strip, a sessions + conversions grouped-bar trend with week/month/quarter tabs, channels donut, conversion-goal gauge, weekly-clicks mini bars, audience breakdown, a campaigns Panel table (owner avatars, budget progress, ROAS trend pills), and an activity timeline. |
The home route (/) is skin-dependent — the same URL renders a different dashboard depending on
the active design skin (see Configuration). The five dedicated
dashboards are always reachable from the sidebar (Dashboard section) and are React.lazy-loaded
so their chart libraries split out of the main bundle. None of the dashboards use Recharts — it is
demoed on /charts/recharts only (see Charts).
Architecture & files
The eight dashboards are page components composed from a shared widget library, with the Bento home also drawing on a small bento-grid layer.
Dashboard screens (src/pages/dashboards/)
| File | Responsibility |
|---|---|
CrmDashboard.tsx | Default home (/) — KPI + funnel, no charts library. |
BentoDashboard.tsx | Bento-skin home — bento tile grid. |
ConsoleDashboard.tsx | Console-skin home — terminal styling. |
AnalyticsDashboard.tsx | /dashboards/analytics (lazy) — ECharts + widget cards. |
EcommerceDashboard.tsx | /dashboards/ecommerce (lazy) — ECharts + ApexCharts. |
ProjectDashboard.tsx | /dashboards/projects (lazy) — ApexCharts + ECharts. |
FinanceDashboard.tsx | /dashboards/finance (lazy) — Chart.js + ApexCharts. |
MarketingDashboard.tsx | /dashboards/marketing (lazy) — Chart.js. |
Shared building blocks
| File | Responsibility |
|---|---|
src/components/widgets/ | The reusable widget cards the dashboards compose (see Widgets doc). |
src/components/bento/BentoGrid.tsx | The responsive grid wrapper. |
src/components/bento/Tile.tsx | A single bento tile (span / rowSpan / tone). |
src/components/bento/index.ts | Barrel — { BentoGrid, Tile, TileTone }. |
Home selection lives in src/App.tsx:
// src/pages/HomeRoute.tsx (shape)
export function HomeRoute() {
const {skin} = useLayout()
const el =
skin === 'bento' ? <BentoDashboard /> : skin === 'console' ? <ConsoleDashboard /> : <CrmDashboard />
return <Suspense fallback={<PageLoader />}>{el}</Suspense>
}The / index is handled directly in App.tsx (not as an appRoutes entry) precisely because it is
skin-dependent. The five dedicated dashboards are registered in src/routes.tsx:
// src/routes.tsx (excerpt)
{path: '/dashboards/analytics', element: <AnalyticsDashboard />},
{path: '/dashboards/ecommerce', element: <EcommerceDashboard />},
{path: '/dashboards/projects', element: <ProjectDashboard />},
{path: '/dashboards/finance', element: <FinanceDashboard />},
{path: '/dashboards/marketing', element: <MarketingDashboard />},Building blocks
Every dashboard is composed from the same shared pieces — there is no dashboard-specific framework:
- The widget library (
src/components/widgets/, barrelindex.ts) does most of the work on the dedicated dashboards:KpiTile(the KPI strips — each dashboard picks a different variant: Analyticsflat+tint, Marketingminimal, Financegradient, Projectglass, eCommercebackgroundIcon),DonutWidget/GaugeWidget(Chart.js doughnuts),BreakdownWidget,BarStatWidget,StatListChartWidget,ReportPanelWidget,WelcomeWidget,ActivityFeedWidget,TimelineWidget,PeopleListWidget,MiniCalendarWidget,NotificationsWidget, plus theTrendPill/Sparkline/MiniBarChartprimitives. See Widgets. - Bespoke inline charts where a widget doesn't fit: each dashboard defines small chart components
at the top of its own file (e.g. Analytics'
TrafficArea/FlowSankey/EngagementScatter/ActivityCalendaron ECharts, Finance'sRevExpChart/NetProfitCharton Chart.js andTxnHeatmapon ApexCharts, Project'sGanttCharton ApexCharts). All pull colors fromuseChartTokens()(src/hooks/useChartTokens.ts), which reads the raw--*CSS variables (including a categoricalseriespalette) and re-reads on theme/skin change — so every chart stays theme- and skin-aware. Chart.js animations branch onuseReducedMotion(). Card/CardBody(src/components/ui) for chart cards; the big data tables (Finance transactions, Marketing campaigns, eCommerce recent orders) sit in aPanelwithfill+refreshable(see Panel).StatCard(src/components/ui) is the KPI tile on the CRM home (label, animated value, delta, hint). KPI strips carry the marker classstat-grid(the Prism skin colours each.stat-icona different hue via that class).- Interactive controls on the richer dashboards: segmented
Tabsfor chart periods (Analytics 7d/30d/12m, Finance month/quarter/year, Marketing week/month/quarter), and the Analytics top-pages toolbar (Selectchannel filter,DateRangePicker, exportButton, overflowDropdownwith toast-backed actions). eCommerce order rows have a portaledDropdownaction menu. - Motion — sections are
Stagger/StaggerItemgrids; CRM/Bento/Console draw bars with animated-width/scalemotiondivs; count-ups useAnimatedNumber(src/components/motion). - Dates and i18n — labels are keys in the
dashboardnamespace; axis/date labels come from the Intl helpers insrc/lib/dates.ts(monthsShort,monthDayShort,relTimeShort) fedi18n.language, never from i18n keys. - Cross-app data reuse — the Project dashboard's Kanban strip and team-workload card read the real
scrumboard seed (
initialBoard(),members,labelKeyFor,formatDueDatefromsrc/data/scrumboard.ts), so it always matches the Scrumboard app. - Decorative art — the Analytics tinted cards use small illustration PNGs from
public/illustrations/(hl-*.png,aria-hidden), country rows reuse the language-menu flag SVGs inpublic/flags/, and eCommerce product imagery comes frompublic/photos/.
The Bento tile system
BentoDashboard uses two components from src/components/bento/:
<BentoGrid>— the responsive CSS grid wrapper.<Tile span rowSpan tone>— a single tile.spanis1 | 2 | 3 | 4,rowSpanis1 | 2, andtoneis aTileTone:'surface' | 'accent' | 'sage' | 'butter' | 'sky' | 'blush'. The tint tones (sage/butter/sky/blush) map to--tint-*tokens defined under[data-skin="bento"], so they only render as intended within the Bento skin (harmless elsewhere).
Usage
The dashboards are reached through the sidebar or by navigating to their routes. To see the
skin-dependent home, switch skins from the Layout Customizer, the ⌘K palette, the header
DesignSystemMenu, or the Layout Settings page.
The most common customization is editing the seed arrays at the top of a dashboard file — every
dashboard keeps its demo data in module-level const arrays (KPIS, TRAFFIC, TRANSACTIONS,
CAMPAIGNS, GANTT, TOP_PRODUCTS, …) whose text fields are i18n keys resolved at render
(proper nouns / numbers stay literal). Period-switchable charts keep one dataset per period in a
keyed record (e.g. Finance's REVEXP.month/quarter/year) selected by the segmented-tabs state.
API / Props
The dashboards are route screens with no props. The reusable pieces they compose:
| Component | Source | Purpose |
|---|---|---|
KpiTile, DonutWidget, GaugeWidget, … | src/components/widgets | The widget cards the dedicated dashboards are built from — see Widgets for props tables. |
TrendPill / Sparkline / MiniBarChart | src/components/widgets/primitives | Delta pill, inline sparkline (line/bar/area), mini weekly bars. |
StatCard | src/components/ui | CRM KPI tile — label, value, delta, prefix/suffix/decimals, hint, icon. |
Card / CardHeader / CardBody, Panel | src/components/ui | Content panels; Panel adds the portlet toolbar (fill, refreshable, …). |
Stagger / StaggerItem / AnimatedNumber | src/components/motion | Entrance stagger + count-up. |
BentoGrid | src/components/bento | Bento grid wrapper. |
Tile | src/components/bento | Bento tile — span?: 1..4, rowSpan?: 1..2, tone?: TileTone. |
useChartTokens() | src/hooks/useChartTokens.ts | Theme/skin-aware chart colors (raw --* tokens + a categorical series palette). |
SectionHeading (src/components/ui/SectionHeading.tsx)
The house section-divider heading for grouping panels inside a page's Stagger grid — an
icon chip + title with a muted hint over a bottom border. It renders a StaggerItem, so it drops
straight into the grid as a full-width row. Exported from the src/components/ui barrel; the form
pages (src/pages/forms/*) use it throughout, and it is the primitive to reach for when a dashboard
page needs labelled section groups.
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | — (required) | The heading text. |
hint | ReactNode | — | Muted one-line description under the title. |
icon | ReactNode | — | Optional leading icon, shown in a primary-tinted chip. |
className | string | 'lg:col-span-2' | Wrapper class — override for non-2-col grids (e.g. lg:col-span-3). |
PageHeader vs. direct title: the CRM, Console, and dedicated dashboards render <PageHeader title … breadcrumbs … action /> (which sets the tab title automatically; the action slot holds an Export
button). Bento has its own greeting hero instead, so it calls useDocumentTitle(...) directly.
Configuration & customization
- Change which dashboard is home — edit
HomeRoute()insrc/pages/HomeRoute.tsx, or simply switch the active skin (Bento →BentoDashboard, Console →ConsoleDashboard, any other skin →CrmDashboard). - Edit the numbers/labels — the seed arrays live at the top of each dashboard file; the labels are
dashboard:i18n keys (add or edit them insrc/locales/en/dashboard.json). - Recolour charts — never hardcode a hex. Pull from
useChartTokens()so light/dark/skins stay in sync. See Charts. - Swap a KPI strip's look — change the
KpiTilevariant(flat/minimal/gradient/glass/backgroundIcon/…); the data props stay identical. - Add a new dashboard — create
src/pages/dashboards/MyDashboard.tsx, add a lazyappRoutesentry insrc/routes.tsx, a menu leaf insrc/data/menu.ts, and anav:label. See Architecture & Routing.
Examples
A minimal dashboard following the current house pattern — a KpiTile strip plus a token-themed
ECharts card:
import {useTranslation} from '@/platform/i18n'
import ReactECharts from 'echarts-for-react'
import {Activity, Users} from 'lucide-react'
import {PageHeader} from '@/layout/PageHeader'
import {Card, CardBody} from '@/components/ui'
import {Stagger, StaggerItem} from '@/components/motion'
import {KpiTile} from '@/components/widgets'
import {useChartTokens} from '@/hooks/useChartTokens'
const KPIS = [
{labelKey: 'anSessions', value: 84200, icon: Activity, tone: 'info', delta: 7.8},
{labelKey: 'anUsers', value: 21400, icon: Users, tone: 'primary', delta: 4.3},
] as const
export function MyDashboard() {
const {t} = useTranslation(['dashboard', 'nav'])
const tk = useChartTokens() // theme/skin-aware colors
return (
<>
<PageHeader title={t('nav:analyticsDashboard')} />
<Stagger className="stat-grid grid grid-cols-1 gap-5 sm:grid-cols-2 xl:grid-cols-4">
{KPIS.map((k) => (
<KpiTile key={k.labelKey} label={t(k.labelKey)} value={k.value} icon={k.icon}
variant="flat" tone={k.tone} delta={k.delta} />
))}
</Stagger>
<Stagger className="mt-5 grid grid-cols-1">
<StaggerItem>
<Card>
<CardBody>
<ReactECharts
notMerge
style={{height: 300, width: '100%'}}
option={{
backgroundColor: 'transparent',
xAxis: {type: 'category', data: ['Mon', 'Tue', 'Wed'],
axisLabel: {color: tk.mutedForeground}},
yAxis: {type: 'value', splitLine: {lineStyle: {color: tk.border}}},
series: [{type: 'line', data: [220, 340, 290], smooth: true,
lineStyle: {color: tk.primary}, itemStyle: {color: tk.primary},
areaStyle: {opacity: 0.2, color: tk.primary}}],
}}
/>
</CardBody>
</Card>
</StaggerItem>
</Stagger>
</>
)
}A Bento tile grid:
import {BentoGrid, Tile} from '@/components/bento'
import {AnimatedNumber} from '@/components/motion'
<BentoGrid>
<Tile span={2} rowSpan={2} tone="accent">
<AnimatedNumber value={48210} prefix="$" />
</Tile>
<Tile tone="sky">…</Tile>
<Tile tone="sage">…</Tile>
<Tile span={3} rowSpan={2} tone="surface">…</Tile>
</BentoGrid>Best practices
- Keep demo data in module-level
constarrays with i18n keys for text — never hardcode user-facing strings inline. Dates/months come fromsrc/lib/dates.ts(never i18n keys). - Pull chart colors from
useChartTokens(); never a raw hex or a Tailwind palette color. Gate Chart.jsanimationonuseReducedMotion()(see Finance/Marketing chart components). - Reach for a widget (
src/components/widgets/) before hand-building a card; write a bespoke inline chart component only when no widget fits, and keep it co-located in the dashboard file. - Put big data tables in a
Panel(fill+refreshable), not a bareCard. - Lazy-load any new heavy (chart-driven) dashboard so it splits out of the main bundle.
- For KPI tiles, group them in a
.stat-gridStaggerso the entrance stagger and the Prism-skin per-icon coloring both work. - Give every chart card the equal-height flex-fill chain (
Card className="flex h-full flex-col"→CardBody className="flex flex-1 flex-col"→ chart wrapperflex-1) so grid rows stay level.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| Home shows the wrong dashboard | The active skin drives / — Bento/Console skins swap the home. Switch skin or edit HomeRoute(). |
| Chart colors don't follow the theme | You hardcoded colors. Read them from useChartTokens() instead. |
| Chart colors stale after switching skin | Ensure the component calls useChartTokens() in render — it re-reads the CSS vars on theme/skin change. |
| ApexCharts tooltip/labels stay light in dark mode | Pass theme: {mode: isDark ? 'dark' : 'light'} from the .dark class on <html> (see TxnHeatmap, GanttChart, StoreGoals). |
| Bento tint tiles look grey | The sage/butter/sky/blush tints resolve only under the Bento skin's --tint-* tokens. |
| Project board strip is empty/stale | It renders initialBoard() from src/data/scrumboard.ts (the seed, not the user's persisted board) — edit the seed to change it. |
| New dashboard 404s | Add an appRoutes entry in src/routes.tsx (and a menu leaf + nav: label). |
FAQ
Why is / handled in App.tsx and not routes.tsx? Because the home is skin-dependent — the same
URL renders CrmDashboard, BentoDashboard, or ConsoleDashboard depending on the active skin.
Which dashboards use which chart library? Analytics and eCommerce lean on ECharts (area/Sankey/
scatter/calendar-heatmap; combo/funnel/treemap), Project mixes ApexCharts (Gantt) with ECharts
(burndown/gauge/radar), Finance mixes Chart.js (bars/bubble) with ApexCharts (heatmap), and
Marketing is Chart.js. The widget cards they all share (DonutWidget, GaugeWidget, Sparkline,
MiniBarChart) render with Chart.js or plain SVG. CRM, Bento, and Console draw their bars with
animated motion divs (no chart dependency). Recharts is demoed only on the /charts/* showcase
pages — see Charts.
Can I make a dashboard the default that isn't tied to a skin? Yes — change the fallback in
HomeRoute() (the <CrmDashboard /> fallback).
Are the interactive controls wired to real data? The period tabs really switch datasets, and the
Panel refresh spins a simulated async refresh; the export buttons, dropdown row actions, and the
Analytics channel/date filters are presentational (they fire toasts) — swap in src/lib/api.ts calls
to make them live.
Notes for designers & content editors
- All dashboard copy (labels, headings, table columns) lives in the
dashboard:andnav:i18n namespaces — editsrc/locales/en/dashboard.jsonto reword, not the component files. - Numbers, company names, and product names in the seed arrays are literal demo content; localize only
through the
*Keyfields. Dates/weekday/month labels localize automatically viaIntl. - The Analytics page's tinted "engage" cards pair each section with a small illustration from
public/illustrations/hl-*.pngand a semantic tone tint (bg-primary/10,bg-info/10, …) — reuse that pattern (imagearia-hidden, tint + matchingring) when adding sections there. - The Bento and Console dashboards carry the personality of their designs — Bento uses the display font and warm tints; Console uses the monospace font and terminal styling. They are meant to be shown when those skins are active.
Related
Widgets
The widget cards the dashboards are built from.
Charts & data-viz
Recharts, ApexCharts, ECharts, and Chart.js — theme-aware.
Design skins
What swaps the home dashboard (Bento / Console).
Layout System
The configurable shell the dashboards render inside.
Components
StatCard, Card, Badge, Progress, and the Panel portlet.
Was this page helpful?
