DenchClaw Widget Mode: At-a-Glance Metrics
How DenchClaw's widget mode turns your custom apps into compact dashboard cards showing live CRM metrics at a glance.
DenchClaw Widget Mode: At-a-Glance Metrics
DenchClaw's widget mode lets any Dench App run as a compact, auto-refreshing card in your workspace dashboard. Instead of opening a full app to check your pipeline status, today's tasks, or key metrics, you see them at a glance — always current, always visible, no click required.
What Is a Widget?#
A widget is a Dench App running in compact mode — a fixed-size card embedded in your DenchClaw dashboard. Widgets:
- Auto-refresh at a configurable interval (every 30 seconds, every 5 minutes, etc.)
- Show a summary view of the app's data — designed to be read at a glance
- Can be expanded to the full app with a click
- Support grid-based layout — arrange multiple widgets side by side
- Live-query your DuckDB data on every refresh
The dashboard page in DenchClaw is a grid of widgets. Think macOS menu bar apps, but for your CRM data.
Configuring Widget Mode#
Any Dench App becomes a widget by setting display: widget in its .dench.yaml manifest:
# pipeline-summary.dench.app/.dench.yaml
name: Pipeline Summary
slug: pipeline-summary
icon: trending-up
version: 1.0.0
display: widget
widget:
width: 2 # Grid columns (1-4)
height: 2 # Grid rows (1-4)
refreshMs: 60000 # Auto-refresh every 60 seconds
expandable: true # Click to open full app
permissions:
db: readGrid units: the dashboard uses a 4-column grid. A widget with width: 2 takes 2 of 4 columns (half the width). Height units are based on a standard row height (~150px per unit).
Building a Widget#
The index.html for a widget needs to render content that fits in the widget's dimensions. Unlike a full-app index.html, a widget should show summary information only.
Here's a simple pipeline summary widget:
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: system-ui;
padding: 12px;
background: var(--surface);
color: var(--text);
}
.metric {
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px 0;
border-bottom: 1px solid var(--border);
}
.metric-value {
font-size: 20px;
font-weight: 700;
color: var(--accent);
}
.title {
font-size: 13px;
font-weight: 600;
margin-bottom: 8px;
color: var(--text-muted);
}
</style>
</head>
<body>
<div class="title">Pipeline Summary</div>
<div id="metrics"></div>
<script>
async function load() {
const stages = await dench.db.query(`
SELECT "Stage", COUNT(*) as count, SUM(CAST("Deal Value" AS FLOAT)) as total
FROM v_deals
WHERE "Status" NOT IN ('Closed Won', 'Closed Lost')
GROUP BY "Stage"
ORDER BY total DESC
`);
const container = document.getElementById('metrics');
container.innerHTML = stages.map(s => `
<div class="metric">
<span>${s.Stage}</span>
<span class="metric-value">$${Math.round(s.total / 1000)}K</span>
</div>
`).join('');
}
load();
// dench.widget.onRefresh(load); // Called on each auto-refresh
</script>
</body>
</html>This widget shows your deal pipeline value by stage, refreshed every minute.
Widget CSS Variables#
Widgets receive theme CSS variables from the workspace so they automatically match dark/light mode:
var(--background) /* Main background */
var(--surface) /* Card/panel background */
var(--text) /* Primary text */
var(--text-muted) /* Secondary/muted text */
var(--accent) /* Accent color */
var(--border) /* Border color */
var(--success) /* Green */
var(--warning) /* Amber */
var(--error) /* Red */Using these variables means your widget looks correct in both light and dark mode without additional work.
Dashboard Layout#
The dashboard page shows a draggable grid of widgets. To configure your dashboard:
- Navigate to Dashboard in the DenchClaw sidebar (or press
G then H) - Widgets are arranged in a 4-column grid
- Drag to reorder
- Click the gear icon on any widget to configure refresh rate or remove it
- Click "+ Add Widget" to add a new app as a widget
Dashboard layout is saved to ~/.openclaw-dench/workspace/dashboard.yaml:
layout:
- slug: pipeline-summary
position: { col: 0, row: 0 }
width: 2
height: 2
- slug: tasks-today
position: { col: 2, row: 0 }
width: 2
height: 2
- slug: upcoming-renewals
position: { col: 0, row: 2 }
width: 4
height: 1Useful Widget Ideas#
Here are widgets worth building for a sales CRM:
Pipeline Value by Stage (2×2)
- Total open pipeline value
- Deal count per stage
- Biggest deal in each stage
Today's Tasks (2×2)
- List of tasks due today
- Overdue task count
- Click to expand full task list
Follow-up Queue (2×1)
- Count of contacts last-touched >14 days ago
- Quick link to the filtered view
Closing This Month (2×2)
- Deals closing this month
- Total potential close value
- Win rate this month vs. last
Recent Activity (4×1)
- Last 5 CRM events (entries created, stages changed)
- Timestamp for each
Widget Refresh and Performance#
The refreshMs setting controls how often the widget re-queries DuckDB and re-renders. Guidelines:
- 30 seconds: For widgets showing real-time data (active subagent status, incoming messages)
- 5 minutes: For most metric widgets (pipeline, tasks, follow-ups)
- 30 minutes: For slowly-changing summaries (monthly totals, quarterly trends)
- Manual: Set
refreshMs: 0for widgets that only refresh on user interaction
DuckDB queries are fast (milliseconds for typical CRM data volumes), so frequent refresh doesn't impact performance.
See also: DenchClaw App Builder for the full app development API, and DenchClaw Event System for real-time widget updates driven by CRM events.
Frequently Asked Questions#
Can a widget open a modal or take user input?#
Yes, within limits. Widgets can render buttons and input fields. Clicking a button can trigger a DuchDB write, call the AI, or emit an event. For complex interactions, configure the widget as expandable so users can open the full app.
How many widgets can I have on my dashboard?#
No fixed limit. Performance degrades gracefully if you have many widgets all refreshing frequently. In practice, 6-10 widgets with 5-minute refresh intervals are imperceptible to system performance.
Can a widget display a chart?#
Yes. Include Chart.js or any other charting library in your widget's HTML. Render the chart in a canvas element sized to fit the widget dimensions. Charts in widgets look identical to charts in full-screen apps.
What's the difference between a widget and a full app?#
A full app is a standalone window/tab with full screen space. A widget is a compact card in the dashboard grid. Most apps should be both: configure display: widget in .dench.yaml and design the index.html to be responsive — showing summary view at widget dimensions and full detail when expanded.
Do widgets work offline?#
Widgets query DuckDB, which is fully local. Widgets work offline as long as the DenchClaw server is running. Any widget feature that requires an internet connection (like an AI query or external API fetch) will fail gracefully with an error state when offline.
Ready to try DenchClaw? Install in one command: npx denchclaw. Full setup guide →
