Use existing widgets
WebMCP Auto-UI ships with 26+ ready-to-use widget types. This tutorial shows you how to use them, customize them, and make them interact with each other. No need to create anything — everything is already there.
Discover and use the native widgets to build rich interfaces without writing custom components.
Prerequisites
Section titled “Prerequisites”- The boilerplate is installed (see Getting started)
- Basic Svelte 5 knowledge (
$state,{#each})
What you will build
Section titled “What you will build”An interactive dashboard using stat, chart-rich, data-table, timeline, and profile — with dynamic updates and interaction handling.
Widget catalog
Section titled “Widget catalog”Simple widgets
Section titled “Simple widgets”| Widget | Description | Typical use |
|---|---|---|
stat | Key statistic (KPI) | Number with trend |
kv | Key-value pairs | Metadata, properties |
list | Ordered list | Text items |
chart | Simple bar chart | Quick comparisons |
alert | Notification/alert | Important messages |
code | Code block with syntax highlighting | Code snippets |
text | Text paragraph | Written content |
actions | Action buttons | Calls to action |
tags | Badges/tags | Filters, categories |
Rich widgets
Section titled “Rich widgets”| Widget | Description | Typical use |
|---|---|---|
stat-card | Enhanced KPI with delta and color | Financial dashboard |
data-table | Sortable table with columns | Data lists |
timeline | Event chronology | Project history |
profile | Profile card with avatar | Contact page |
trombinoscope | Portrait grid | Teams |
json-viewer | Interactive JSON tree | Debug, API |
hemicycle | Parliamentary composition | Politics |
chart-rich | Multi-series (bar, line, area, pie) | Comparative analysis |
cards | Card grid | Catalogs |
grid-data | Grid with cell highlights | Matrices |
sankey | Flow diagram | Financial flows |
map | Interactive Leaflet map | Geolocation |
log | Log stream | Monitoring |
gallery | Image gallery with lightbox | Portfolios |
carousel | Slide carousel | Presentations |
d3 | D3.js visualizations | Advanced charts |
js-sandbox | Custom JavaScript sandbox | Interactive code |
graph TD subgraph Simple stat[stat] kv[kv] list[list] chart[chart] alert[alert] code[code] text[text] actions[actions] tags[tags] end
subgraph Rich statcard[stat-card] datatable[data-table] timeline[timeline] profile[profile] chartrich[chart-rich] map[map] gallery[gallery] sankey[sankey] end
BlockRenderer --> Simple BlockRenderer --> RichStep 1: Import BlockRenderer
Section titled “Step 1: Import BlockRenderer”BlockRenderer is the entry point for displaying any widget. It automatically resolves the Svelte component matching the widget type:
<script lang="ts"> import { BlockRenderer } from '@webmcp-auto-ui/ui'; import { canvas } from '@webmcp-auto-ui/sdk/canvas';</script>BlockRenderer takes three main props:
type: the widget name ('stat','data-table', etc.)data: the data in the format expected by the widgetid: (optional) unique identifier for interactions
Step 2: Create widgets programmatically
Section titled “Step 2: Create widgets programmatically”The canvas store provides methods to add widgets:
<script lang="ts"> function addStatWidget() { canvas.addWidget('stat', { label: 'Total sales', value: '$12,450', trend: '+12%', trendDir: 'up', }); }
function addChartWidget() { canvas.addWidget('chart', { title: 'Monthly sales', bars: [ ['January', 120], ['February', 190], ['March', 150], ], }); }
function addTableWidget() { canvas.addWidget('data-table', { title: 'Active customers', columns: [ { key: 'name', label: 'Name' }, { key: 'email', label: 'Email' }, { key: 'status', label: 'Status' }, ], rows: [ { name: 'Alice Dupont', email: 'alice@example.com', status: 'Active' }, { name: 'Bob Martin', email: 'bob@example.com', status: 'Suspended' }, { name: 'Charlie Lenoir', email: 'charlie@example.com', status: 'Active' }, ], }); }</script>
<button onclick={addStatWidget}>Add KPI</button><button onclick={addChartWidget}>Add chart</button><button onclick={addTableWidget}>Add table</button>Checkpoint: click each button and verify the corresponding widget appears.
Step 3: Display widgets
Section titled “Step 3: Display widgets”Loop through the canvas blocks and render them with BlockRenderer:
<div class="widgets-grid"> {#each canvas.blocks as block (block.id)} <BlockRenderer id={block.id} type={block.type} data={block.data} /> {/each}</div>
<style> .widgets-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; padding: 1rem; }</style>Widget gallery with examples
Section titled “Widget gallery with examples”Enhanced KPI (stat-card)
Section titled “Enhanced KPI (stat-card)”<script lang="ts"> canvas.addWidget('stat-card', { label: 'Conversion rate', value: '3.2', unit: '%', trend: 'up', delta: '+0.5%', variant: 'success', // 'success' | 'warning' | 'danger' | 'info' });</script>Rich multi-series chart (chart-rich)
Section titled “Rich multi-series chart (chart-rich)”5 chart types in a single widget:
<script lang="ts"> canvas.addWidget('chart-rich', { title: 'Quarterly performance', type: 'bar', // 'bar' | 'line' | 'area' | 'pie' | 'donut' labels: ['Q1', 'Q2', 'Q3', 'Q4'], data: [ { label: 'Sales', values: [120, 190, 150, 180], color: '#3b82f6' }, { label: 'Profit', values: [80, 140, 110, 150], color: '#10b981' }, ], });</script>Event timeline (timeline)
Section titled “Event timeline (timeline)”<script lang="ts"> canvas.addWidget('timeline', { title: 'Project history', events: [ { title: 'Kickoff', date: '2024-01-15', status: 'done', description: 'Project launched' }, { title: 'First release', date: '2024-02-28', status: 'done', description: 'MVP delivered' }, { title: 'Optimizations', date: '2024-04-01', status: 'active', description: 'In progress' }, { title: 'Public launch', date: '2024-05-01', status: 'pending', description: 'Scheduled' }, ], });</script>Profile card (profile)
Section titled “Profile card (profile)”<script lang="ts"> canvas.addWidget('profile', { name: 'Alice Dupont', subtitle: 'Senior Developer', badge: { text: 'Online', variant: 'success' }, fields: [ { label: 'Team', value: 'Backend' }, { label: 'Location', value: 'Paris, France' }, { label: 'Since', value: '2021' }, ], stats: [ { label: 'Projects', value: '12' }, { label: 'Contributors', value: '45' }, ], });</script>Interactive map (map)
Section titled “Interactive map (map)”<script lang="ts"> canvas.addWidget('map', { title: 'Office locations', center: { lat: 46.6, lng: 2.3 }, zoom: 6, markers: [ { lat: 48.86, lng: 2.35, label: 'Paris (HQ)' }, { lat: 43.60, lng: 1.44, label: 'Toulouse' }, { lat: 45.76, lng: 4.84, label: 'Lyon' }, ], });</script>Code with syntax highlighting (code)
Section titled “Code with syntax highlighting (code)”<script lang="ts"> canvas.addWidget('code', { lang: 'typescript', content: `interface User { id: number; name: string; email: string;}`, });</script>JSON viewer (json-viewer)
Section titled “JSON viewer (json-viewer)”<script lang="ts"> canvas.addWidget('json-viewer', { title: 'Data structure', data: { user: { id: 123, name: 'Alice', tags: ['admin', 'developer'] }, }, maxDepth: 3, expanded: true, });</script>Handling interactions
Section titled “Handling interactions”Some widgets emit events when the user interacts with them. Use the oninteract prop to capture them:
<BlockRenderer id={block.id} type={block.type} data={block.data} oninteract={(type, action, payload) => { console.log(`Widget ${type} -- action: ${action}`, payload); }}/>Events emitted by widgets:
| Widget | Action | Payload |
|---|---|---|
data-table | rowclick | Row object |
timeline | eventclick | Event object |
cards | cardclick | Card object |
gallery | imageclick | {image, index} |
tags | tagclick | {tag, index} |
actions | click | {action, index} |
Dynamic updates
Section titled “Dynamic updates”Modify a widget after creation using canvas methods:
<script lang="ts"> function updateStat(blockId: string) { canvas.updateBlock(blockId, { value: '$15,000', trend: '+20%', trendDir: 'up', }); }
function removeWidget(blockId: string) { canvas.removeBlock(blockId); }
function clearAll() { canvas.clearBlocks(); }</script>Theme and customization
Section titled “Theme and customization”Wrap your widgets in a ThemeProvider to apply a consistent theme:
<script lang="ts"> import { ThemeProvider } from '@webmcp-auto-ui/ui';</script>
<ThemeProvider defaultMode="light" overrides={{ 'color-accent': '#2d6a4f', 'color-bg': '#f4f1eb',}}> <div class="widgets-grid"> {#each canvas.blocks as block (block.id)} <BlockRenderer id={block.id} type={block.type} data={block.data} /> {/each} </div></ThemeProvider>All native widgets respect theme tokens. Changing color-accent updates the accent color across all charts, progress bars, and buttons.
Complete use case: Dynamic dashboard
Section titled “Complete use case: Dynamic dashboard”<script lang="ts"> import { BlockRenderer } from '@webmcp-auto-ui/ui'; import { canvas } from '@webmcp-auto-ui/sdk/canvas'; import { onMount } from 'svelte';
function buildDashboard(data: any) { canvas.clearBlocks(); canvas.addWidget('stat-card', { label: 'Monthly revenue', value: data.revenue.toLocaleString('en-US'), unit: '$', trend: 'up', variant: 'success', }); canvas.addWidget('chart-rich', { title: 'Trend', type: 'line', labels: data.months, data: [{ label: 'Revenue', values: data.values }], }); canvas.addWidget('data-table', { title: 'Latest transactions', columns: [ { key: 'date', label: 'Date' }, { key: 'amount', label: 'Amount' }, { key: 'status', label: 'Status' }, ], rows: data.transactions, }); }
onMount(async () => { const data = await fetch('/api/dashboard').then(r => r.json()); buildDashboard(data); });</script>
<div class="dashboard"> {#each canvas.blocks as block (block.id)} <BlockRenderer id={block.id} type={block.type} data={block.data} /> {/each}</div>sequenceDiagram participant Page participant API participant Canvas participant BR as BlockRenderer
Page->>API: GET /api/dashboard API-->>Page: {revenue, months, values, transactions} Page->>Canvas: clearBlocks() Page->>Canvas: addWidget('stat-card', ...) Page->>Canvas: addWidget('chart-rich', ...) Page->>Canvas: addWidget('data-table', ...) Canvas-->>BR: reactive blocks BR-->>Page: widgets renderedTroubleshooting
Section titled “Troubleshooting”| Problem | Likely cause | Solution |
|---|---|---|
| Widget shows as raw JSON | Unrecognized type | Check spelling (e.g., data-table, not datatable) |
| Empty table | rows missing or empty | Ensure rows is an array of objects |
| Invisible chart | labels or data missing | Both properties are required for chart-rich |
| Theme not applied | No ThemeProvider | Wrap your widgets in a <ThemeProvider> |
Going further
Section titled “Going further”- Create your own widgets: follow Create a custom widget
- Advanced theming: see Build a themed demo
- Cross-widget interactions: use the FONC bus or Svelte reactive filters to connect widgets