Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions components/mdx.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import defaultMdxComponents from 'fumadocs-ui/mdx';
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
import { Card, Cards } from 'fumadocs-ui/components/card';
import { Step, Steps } from 'fumadocs-ui/components/steps';
import { Tabs, TabItem } from './mdx-tabs';
import type { MDXComponents } from 'mdx/types';

export function getMDXComponents(components?: MDXComponents) {
return {
...defaultMdxComponents,
Accordion,
Accordions,
Card,
Cards,
Step,
Steps,
Tabs,
TabItem,
...components,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Use both decorators:

The runtime registration path is:

- decorator metadata -> introspection (`SolidIntrospectService`) -> registry (`SolidRegistry`) -> runtime resolver (`DashboardRuntimeService`)
- Decorator metadata -> introspection (`SolidIntrospectService`) -> registry (`SolidRegistry`) -> runtime resolver (`DashboardRuntimeService`)

## Provider Template

Expand Down Expand Up @@ -92,8 +92,8 @@ export class ExampleDashboardWidgetProvider implements IDashboardWidgetDataProvi

The framework now includes a canonical reference implementation for a fully custom queue-focused widget:

- backend provider: `MqDashboardQueueSlaHeatmapProvider`
- frontend widget: `QueueSlaHeatmapWidget`
- Backend provider: `MqDashboardQueueSlaHeatmapProvider`
- Frontend widget: `QueueSlaHeatmapWidget`

The provider output contract is intentionally explicit:

Expand Down Expand Up @@ -126,9 +126,9 @@ The provider output contract is intentionally explicit:
```

This RI is useful because it shows the recommended split:
- the provider owns data access and runtime contract design,
- the frontend widget owns the final visual treatment,
- and metadata binds the two together.
- The provider owns data access and runtime contract design.
- The frontend widget owns the final visual treatment.
- Metadata binds the two together.

## Recommended Implementation Practices

Expand All @@ -140,9 +140,17 @@ This RI is useful because it shows the recommended split:

## Quick Validation Path

1. Start service.
2. Call definition endpoint and verify widget exists.
3. Call widget data endpoint:
<Steps>
<Step>
Start service.
</Step>
<Step>
Call the definition endpoint and verify the widget exists.
</Step>
<Step>
Call the widget data endpoint.
</Step>
</Steps>

```bash
curl -X POST "$BASE_URL/dashboard/<module>/<dashboard>/widgets/<widgetId>/data" \
Expand All @@ -151,4 +159,4 @@ curl -X POST "$BASE_URL/dashboard/<module>/<dashboard>/widgets/<widgetId>/data"
-d '{"variables": {}}'
```

4. Verify `meta.providerName` and `data` payload shape.
Then verify `meta.providerName` and the `data` payload shape.
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Dashboard definitions are authored in module metadata under the root-level `dash
<Callout type="info" title="Mental Model">

The dashboard schema has a small set of core players:
- the <strong>dashboard definition</strong> describes the screen itself,
- <strong>variables</strong> describe the inputs a user can use to filter or parameterise the dashboard,
- <strong>widgets</strong> describe the individual building blocks on the page,
- <strong>provider bindings</strong> connect those widgets to backend data,
- and the <strong>default layout</strong> describes how the widgets should initially be arranged.
- The <strong>dashboard definition</strong> describes the screen itself.
- <strong>Variables</strong> describe the inputs a user can use to filter or parameterise the dashboard.
- <strong>Widgets</strong> describe the individual building blocks on the page.
- <strong>Provider bindings</strong> connect those widgets to backend data.
- The <strong>default layout</strong> describes how the widgets should initially be arranged.

</Callout>

Expand Down Expand Up @@ -134,9 +134,9 @@ Each widget binds to a backend provider using `dataProvider`.

`providerContext` is a metadata-authored input passed through to the provider at runtime. It is useful for keeping provider classes reusable. For example:

- a KPI provider can use `providerContext.metric` to decide which aggregate to compute,
- a chart provider can use `providerContext.bucket` to choose `hour` vs `day`,
- a table provider can use `providerContext.columns` and `providerContext.sort` to shape the output.
- A KPI provider can use `providerContext.metric` to decide which aggregate to compute.
- A chart provider can use `providerContext.bucket` to choose `hour` vs `day`.
- A table provider can use `providerContext.columns` and `providerContext.sort` to shape the output.

For custom frontend rendering, add `componentName`.

Expand Down Expand Up @@ -176,9 +176,9 @@ Dashboards should be exposed via metadata-driven menu/action pairs.

Recommended pattern:

- action type `custom`
- action path matching dashboard route
- menu item referencing the action
- Action type `custom`
- Action path matching dashboard route
- Menu item referencing the action

The action route should follow the canonical dashboard route pattern defined in [solidRoutes.tsx](/Users/harishpatel/Code/javascript/solid-core-ui/src/routes/solidRoutes.tsx), which is:

Expand Down Expand Up @@ -216,15 +216,15 @@ The dashboard widget permission format is:

Where:

- the first segment is always `dashboard`
- the second segment is the dashboard name
- the third segment is the widget matcher
- The first segment is always `dashboard`
- The second segment is the dashboard name
- The third segment is the widget matcher

The widget matcher supports:

- exact widget names
- Exact widget names
- `*` for all widgets in a dashboard
- regex-style patterns in the widget segment
- Regex-style patterns in the widget segment

Examples from the queue-health reference implementation:

Expand Down Expand Up @@ -252,26 +252,58 @@ The permission check is enforced on the backend first.

When a user does **not** have permission for a widget:

1. the backend does **not** invoke that widget's data provider at all
2. the backend returns a normalized unauthorized widget envelope
3. the frontend still renders the widget card in the grid
4. the widget body shows a compact `Unauthorized` state
<Steps>
<Step>
The backend does **not** invoke that widget's data provider at all.
</Step>
<Step>
The backend returns a normalized unauthorized widget envelope.
</Step>
<Step>
The frontend still renders the widget card in the grid.
</Step>
<Step>
The widget body shows a compact `Unauthorized` state.
</Step>
</Steps>

This behavior is intentional because it preserves layout consistency while keeping protected widget data entirely server-side.

To make dashboard permissions effective in a real project:

1. declare the explicit permission strings in module metadata
2. attach those permissions to one or more roles
3. assign those roles to users
<Steps>
<Step>
Declare the explicit permission strings in module metadata.
</Step>
<Step>
Attach those permissions to one or more roles.
</Step>
<Step>
Assign those roles to users.
</Step>
</Steps>

That flow is standard SolidX RBAC behavior and dashboards follow the same model.

## Authoring Checklist

1. Define dashboard in `dashboards[]`.
2. Define variables with clear names and labels.
3. Bind each widget to a valid backend `dataProvider`.
4. Define a complete `defaultLayout` for all widgets.
5. Add action/menu entries for discoverable navigation.
6. Add explicit dashboard widget permissions and bind them to the right roles.
<Steps>
<Step>
Define the dashboard in `dashboards[]`.
</Step>
<Step>
Define variables with clear names and labels.
</Step>
<Step>
Bind each widget to a valid backend `dataProvider`.
</Step>
<Step>
Define a complete `defaultLayout` for all widgets.
</Step>
<Step>
Add action and menu entries for discoverable navigation.
</Step>
<Step>
Add explicit dashboard widget permissions and bind them to the right roles.
</Step>
</Steps>
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,17 @@ Registered in:

At runtime, rendering follows this order:

1. If metadata provides explicit component override (`componentName`), resolve it.
2. Else derive default renderer from widget type/runtime payload.
3. If no renderer is found, use `DefaultDashboardUnknownWidget`.
<Steps>
<Step>
If metadata provides explicit component override (`componentName`), resolve it.
</Step>
<Step>
Else derive the default renderer from widget type and runtime payload.
</Step>
<Step>
If no renderer is found, use `DefaultDashboardUnknownWidget`.
</Step>
</Steps>

This makes custom rendering **optional** while preserving consistent baseline behavior.

Expand Down
59 changes: 36 additions & 23 deletions content/docs/developer-docs/dashboarding/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,56 @@
title: Intro
icon: "layout-dashboard"
description: Build metadata-driven dashboards in SolidX using backend data providers, frontend widget extensions, and user-specific layouts.
summary: This section explains the complete SolidX dashboarding architecture, including metadata authoring, provider registration, runtime APIs, widget rendering contracts, Gridstack layout persistence, and practical templates for creating new widgets end to end.
summary: Covers dashboard metadata, backend widget providers, frontend widget registration, layout persistence, and implementation patterns for dashboard features.
sidebar_position: 2.6
---

SolidX dashboarding is a **metadata-driven framework capability** for building operational and analytical dashboard experiences without hard-coding each screen.
## Dashboard Overview

It is designed around four principles:
SolidX dashboarding is a metadata-driven system for building operational and analytical dashboards without hard-coding each screen.

- metadata-first dashboard definitions,
- backend provider-driven data resolution,
- frontend extension-driven widget rendering,
- and per-user layout personalization.
The dashboarding model is organized around four layers:

The queue health reference dashboard also includes a canonical custom widget example, `QueueSlaHeatmapWidget`, which demonstrates the intended model:
- backend data providers remain mandatory,
- custom frontend rendering stays optional,
- and explicit widget overrides are only introduced when the default framework widget set is not enough.
- Metadata-defined dashboard composition.
- Backend provider-driven data resolution.
- Frontend extension-driven widget rendering.
- Per-user layout personalization.

The queue health reference dashboard also includes a representative custom widget example, `QueueSlaHeatmapWidget`, which shows the intended model:
- Backend data providers remain mandatory.
- Custom frontend rendering stays optional.
- Explicit widget overrides are only introduced when the default framework widget set is not enough.

<Callout type="info" title="Mental Model">

Think of a SolidX dashboard as a composition of four layers:
- <strong>metadata</strong> defines the dashboard, variables, widgets, and default layout,
- <strong>backend providers</strong> resolve the actual widget data,
- <strong>frontend widgets</strong> decide how that data is rendered,
- and <strong>user layout persistence</strong> personalizes the arrangement without changing the dashboard definition itself.
SolidX dashboarding is composed of four layers:
- Metadata defines the dashboard, variables, widgets, and default layout.
- Backend providers resolve widget data at runtime.
- Frontend widgets determine the rendering contract.
- User layout persistence personalizes arrangement without mutating the dashboard definition itself.

</Callout>

## Sample Dashboard

![Dashboard Architecture Placeholder](/img/dashboarding/dashboard-architecture-overview.png)
## Dashboard Capabilities

<Cards>
<Card title="Dashboard Metadata" href="/docs/developer-docs/dashboarding/dashboard-metadata-authoring-guide">
Define dashboards, variables, widgets, layout items, and navigation metadata from the platform side.
</Card>
<Card title="Widget Data Provider" href="/docs/developer-docs/dashboarding/build-a-custom-dashboard-widget-provider">
Implement and register backend providers that resolve the runtime data required by each widget.
</Card>
<Card title="Widget UI" href="/docs/developer-docs/dashboarding/frontend-dashboard-widget-extension-contract">
Understand the frontend rendering contract and when custom widget components are necessary.
</Card>
<Card title="Implementation Templates" href="/docs/developer-docs/dashboarding/agent-ready-templates">
Use the templates as implementation starting points for dashboard-related backend and frontend work.
</Card>
</Cards>

## Pages
## Sample Dashboard

- [Metadata Schema](./dashboard-metadata-authoring-guide.mdx): how to define dashboards, variables, widgets, layouts, and navigation metadata.
- [Widget Data Provider](./build-a-custom-dashboard-widget-provider.mdx): how backend providers are implemented, registered, and bound to widgets.
- [Widget UI](./frontend-dashboard-widget-extension-contract.mdx): how default rendering works and how custom widget components are introduced when needed.
![Dashboard architecture overview](/img/dashboarding/dashboard-architecture-overview.png)

<Callout type="info" title="Source of Truth">

Expand Down
Loading