From studio-skills
Defines YAML format for grid dashboards rendered via preview_grid_dashboard: page structure, 6 cell types (kpi, gauge, scores, table, chart, markdown), grid layout rules, cell merging syntax, and incremental build workflow.
npx claudepluginhub treasure-data/td-skills --plugin treasure-work-skillsThis skill uses the workspace's default tool permissions.
Build visual dashboards rendered in the artifact panel via `preview_grid_dashboard`. The agent writes a YAML file defining pages of grid cells; the MCP App renders them with a page selector.
Generates self-contained interactive HTML dashboards with KPI cards, charts, filters, and tables from queries, CSVs, or samples for reports and monitoring.
Guides data dashboard design: select KPIs for audience, structure layouts, apply visual hierarchy and principles, recommend BI tools like Tableau or Power BI. Use before chart coding or SQL.
Creates interactive charts, dashboards, and data visualizations using Recharts for React/Next.js, Chart.js for Vue/Angular, and D3.js for custom needs.
Share bugs, ideas, or general feedback.
Build visual dashboards rendered in the artifact panel via preview_grid_dashboard. The agent writes a YAML file defining pages of grid cells; the MCP App renders them with a page selector.
(IMPORTANT): Include all analysis findings in the dashboard — do not omit relevant insights, metrics, or supporting facts. Build incrementally (see "Building YAML Incrementally" below).
The YAML is page-based: top-level pages object where each key is a page identifier (e.g., URL, label) and each value defines a grid with cells.
pages:
"Page A":
title: "Page A Dashboard" # optional — shown as header
description: "Brief description" # optional — shown below title
grid:
columns: 3 # number of columns
rows: 3 # number of rows
cells:
- pos: "1-1" # row-column (1-based)
type: kpi # cell type
title: "Cell Title" # optional — uppercase label above content
kpi: # type-specific config
value: "1,234"
change: "+12%"
trend: up
"Page B":
title: "Page B Dashboard"
grid:
columns: 4
rows: 8
cells:
- pos: "1-1"
type: kpi
# ...
The UI renders a select box at the top to switch between pages.
CRITICAL: Large dashboards MUST be built incrementally. Do NOT attempt to write the entire YAML in a single tool call — this causes output truncation mid-generation.
Multi-page dashboards — build one page at a time:
pages: header and the first page's complete grid + cellspreview_grid_dashboard once at the endSingle pages with many cells (12+ rows) — build in row batches:
pages: header, grid config, and the first 4–6 rows of cellscells arraypreview_grid_dashboard once at the endEach tool call should produce a manageable amount of YAML. Never write more than ~6 grid rows in a single tool call.
This is NOT a CSS framework 12-column grid (like Bootstrap). columns is the literal number of columns displayed. If you want 3 columns, set columns: 3 — do NOT set columns: 12 and merge cells to simulate 3 columns. The tool validates cell positions and will return errors for invalid formats.
grid.columns and grid.rows must be numbers matching the actual cell count (not strings, not auto). Do not declare more rows/columns than cells occupypos: "row-col" — 1-based coordinates (e.g., "1-1" = top-left)pos: ["1-1", "1-3"] merges from row 1 col 1 to row 1 col 3. MUST be a YAML array of two stringspos: ["3-1", "3-4"])Correct pos format:
pos: "1-1" # single cell at row 1, column 1
pos: ["1-1", "1-3"] # merged cell from (1,1) to (1,3)
pos: ["3-1", "5-4"] # merged cell spanning rows 3-5 and columns 1-4
WRONG — these will cause tool errors:
pos: "1-1:1-3" # ✗ colon separator
pos: "1-1to1-3" # ✗ "to" separator
pos: "1-1,1-3" # ✗ comma in string
pos: [1, 1] # ✗ numbers instead of "row-col" strings
Common grid sizes:
kpi — Metric CardLarge number with optional trend indicator. Use for headline metrics in the top row.
- pos: "1-1"
type: kpi
title: "Total Revenue"
kpi:
value: "$1.2M" # string or number — displayed large
change: "+15.3%" # optional — shown below value
trend: up # optional — up | down | flat (colors the change)
subtitle: "vs. last quarter" # optional — small text below change
gauge — Half-Circle MeterScore visualization with color thresholds. Use for scores, completion rates, health indicators.
- pos: "2-1"
type: gauge
title: "Health Score"
gauge:
value: 72 # current value
max: 100 # maximum value
label: "B" # optional — displayed in center (defaults to value)
thresholds: # optional — color breakpoints (use hex values, NOT color names)
- { limit: 40, color: "#ef4444" }
- { limit: 70, color: "#f59e0b" }
- { limit: 100, color: "#22c55e" }
scores — Progress Bar ListLabeled horizontal bars showing value/max ratios. Use for dimension breakdowns, skill assessments, category comparisons.
- pos: "2-2"
type: scores
title: "Score Breakdown"
scores:
- label: "Content Structure"
value: 14
max: 26
- label: "Structured Data"
value: 8
max: 26
- label: "E-E-A-T Signals"
value: 16
max: 21
Bar colors: green (≥75%), yellow (40–74%), red (<40%).
table — Sortable TableStructured data with click-to-sort columns. Two formats accepted:
Format 1 — Flat arrays (compact):
- pos: ["3-1", "3-4"] # merged across columns 1-4
type: table
title: "Top Keywords"
table:
headers: ["Keyword", "Position", "Impressions", "CTR"]
rows:
- ["what is cdp", 11.2, 1840, "1.8%"]
- ["cdp vs dmp", 8.5, 920, "3.2%"]
sortable: true # optional — defaults to true
Format 2 — Column definitions (readable, preferred for many columns):
- pos: "3-1"
type: table
title: "Top Keywords"
table:
columns:
- key: query
label: "Keyword"
- key: position
label: "Position"
- key: impressions
label: "Impressions"
- key: ctr
label: "CTR"
rows:
- query: "what is cdp"
position: 11.2
impressions: 1840
ctr: "1.8%"
- query: "cdp vs dmp"
position: 8.5
impressions: 920
ctr: "3.2%"
sortable: true
chart — Chart.js ChartPass standard Chart.js config (type, data, options).
Standard types: bar, line, pie, doughnut, radar, polarArea, bubble, scatter
Plugin types (also available): sankey, treemap, matrix, wordCloud, candlestick, ohlc
YAML constraint: Never use JS function strings for callbacks or scriptable options — they are passed as plain strings and will be stripped. Use declarative alternatives:
key to specify the value field. Put backgroundColor and label inside each tree item (not at dataset level). Use labels: { display: true } to show labels.{x, y, v}. Width, height, scales, and tooltip are auto-configured. For multi-color heatmaps, use colorScale on the dataset: colorScale: [{limit: 20, color: "#3b82f6"}, {limit: 50, color: "#10b981"}, ...]. Omit for single-color alpha gradient from backgroundColor.- pos: "3-2"
type: chart
title: "Traffic Trend"
chart:
type: line
data:
labels: ["Jan", "Feb", "Mar", "Apr"]
datasets:
- label: "Impressions"
data: [1200, 1900, 3000, 2500]
borderColor: "#4a6cf7"
fill: false
options: # optional — Chart.js options
scales:
y:
beginAtZero: true
markdown — Rich TextGFM markdown content. Use content or markdown key — must be a top-level string, NOT a nested object.
- pos: "4-1"
type: markdown
title: "Summary"
content: |
### Key Finding
**Impact**: High — content depth is 1/6 of competitors
WRONG — markdown.content nested object will cause a tool error:
markdown:
content: | # ✗ nested under markdown — must be a top-level key
Some text
Write the YAML file and call:
preview_grid_dashboard({ file_path: "/absolute/path/to/dashboard.yaml" })
The dashboard renders in the artifact panel with light/dark theme support and a page selector dropdown.
When preview_grid_dashboard is not available (CLI mode), output the same information as formatted markdown instead.
pos: ["3-1", "3-4"] for data tables