Dynamic UI Skill
Render dynamic visual content (tables, charts, stats, cards, dashboards) as images using HTML templates and wkhtmltoimage.
Triggers
- "render", "visualize", "chart", "dashboard", "dynamic-ui"
Usage
# Basic usage
./scripts/render.sh <template> --data '<json>'
# With options
./scripts/render.sh table --data '{"columns":["A","B"],"rows":[["1","2"]]}' --style dark --output out.png
# From stdin
echo '{"labels":["Q1","Q2"],"values":[100,200]}' | ./scripts/render.sh chart-bar --style modern
Templates
| Template |
Description |
Input Schema |
table |
Data tables |
{"columns": [...], "rows": [[...], ...]} |
chart-bar |
Bar charts |
{"labels": [...], "values": [...], "title": "..."} |
chart-line |
Line charts |
{"labels": [...], "values": [...], "title": "...", "subtitle": "...", "y_suffix": "%"} |
stats |
KPI cards |
{"stats": [{"label": "...", "value": "...", "change": "..."}]} |
card |
Info card |
{"title": "...", "subtitle": "...", "body": "...", "status": "green|yellow|red"} |
dashboard |
Composite |
{"title": "...", "widgets": [{"type": "stat|table|chart", ...}]} |
Options
| Option |
Description |
Default |
--data, --input |
JSON data (or use stdin) |
- |
--style |
Theme: modern, dark, minimal |
modern |
--output, -o |
Output path |
stdout (base64) |
--width |
Image width in pixels |
800 |
Themes
- modern — Purple/blue gradients, shadows, rounded corners
- dark — Dark background, light text, subtle borders
- minimal — Clean white, thin borders
Examples
# Render a table
./scripts/render.sh table --data '{"columns":["Name","Score"],"rows":[["Alice","95"],["Bob","87"]]}' -o table.png
# Render a bar chart
./scripts/render.sh chart-bar --data '{"labels":["Jan","Feb","Mar"],"values":[120,150,180],"title":"Monthly Sales"}' --style dark -o chart.png
# Render a line chart (single series)
./scripts/render.sh chart-line --data '{"labels":["W1","W2","W3","W4"],"values":[10,12,15,25],"title":"Growth","subtitle":"Week over week","y_suffix":"%"}' --style dark -o line.png
# Render a line chart (multi-series)
./scripts/render.sh chart-line --data '{"labels":["Q1","Q2","Q3","Q4"],"datasets":[{"label":"Revenue","values":[100,150,200,350]},{"label":"Costs","values":[80,90,100,120]}],"title":"Revenue vs Costs"}' -o multi.png
# Render stats
./scripts/render.sh stats --data '{"stats":[{"label":"Users","value":"12.5K","change":"+12%"},{"label":"Revenue","value":"$45K","change":"+8%"}]}' -o stats.png
💡 Sending Images to Users
After rendering an image, you'll typically want to send it to the user. Here's the recommended workflow:
Recommended Workflow:
# 1. Render to ~/.openclaw/media/ (recommended path)
./scripts/render.sh table --data '...' -o ~/.openclaw/media/my-table.png
# 2. Send inline via message tool
message(action=send, filePath=/home/ubuntu/.openclaw/media/my-table.png, caption="Caption", channel=telegram, to=<user_id>)
Tips:
- Save to
~/.openclaw/media/ — this path works reliably for inline sending
- Use descriptive captions — helps users understand the visual
- Consider the context — sometimes saving to disk is fine if the user requested it
Example (complete flow):
# Render
echo '{"title":"My Data","columns":["A","B"],"rows":[["1","2"]]}' | \
./scripts/render.sh table -o ~/.openclaw/media/data.png
# Send
message(action=send, filePath=/home/ubuntu/.openclaw/media/data.png, caption="Here's your data", channel=telegram, to=USER_ID)
Dependencies
/usr/bin/wkhtmltoimage — HTML to image conversion
jq — JSON parsing
1---2name: dynamic-ui3description: Render tables, charts, stats, cards, and dashboards as images using HTML templates and wkhtmltoimage.4---56# Dynamic UI Skill78Render dynamic visual content (tables, charts, stats, cards, dashboards) as images using HTML templates and wkhtmltoimage.910## Triggers11- "render", "visualize", "chart", "dashboard", "dynamic-ui"1213## Usage1415```bash16# Basic usage17./scripts/render.sh <template> --data '<json>'1819# With options20./scripts/render.sh table --data '{"columns":["A","B"],"rows":[["1","2"]]}' --style dark --output out.png2122# From stdin23echo '{"labels":["Q1","Q2"],"values":[100,200]}' | ./scripts/render.sh chart-bar --style modern24```2526## Templates2728| Template | Description | Input Schema |29|----------|-------------|--------------|30| `table` | Data tables | `{"columns": [...], "rows": [[...], ...]}` |31| `chart-bar` | Bar charts | `{"labels": [...], "values": [...], "title": "..."}` |32| `chart-line` | Line charts | `{"labels": [...], "values": [...], "title": "...", "subtitle": "...", "y_suffix": "%"}` |33| `stats` | KPI cards | `{"stats": [{"label": "...", "value": "...", "change": "..."}]}` |34| `card` | Info card | `{"title": "...", "subtitle": "...", "body": "...", "status": "green\|yellow\|red"}` |35| `dashboard` | Composite | `{"title": "...", "widgets": [{"type": "stat\|table\|chart", ...}]}` |3637## Options3839| Option | Description | Default |40|--------|-------------|---------|41| `--data`, `--input` | JSON data (or use stdin) | - |42| `--style` | Theme: modern, dark, minimal | modern |43| `--output`, `-o` | Output path | stdout (base64) |44| `--width` | Image width in pixels | 800 |4546## Themes4748- **modern** — Purple/blue gradients, shadows, rounded corners49- **dark** — Dark background, light text, subtle borders50- **minimal** — Clean white, thin borders5152## Examples5354```bash55# Render a table56./scripts/render.sh table --data '{"columns":["Name","Score"],"rows":[["Alice","95"],["Bob","87"]]}' -o table.png5758# Render a bar chart59./scripts/render.sh chart-bar --data '{"labels":["Jan","Feb","Mar"],"values":[120,150,180],"title":"Monthly Sales"}' --style dark -o chart.png6061# Render a line chart (single series)62./scripts/render.sh chart-line --data '{"labels":["W1","W2","W3","W4"],"values":[10,12,15,25],"title":"Growth","subtitle":"Week over week","y_suffix":"%"}' --style dark -o line.png6364# Render a line chart (multi-series)65./scripts/render.sh chart-line --data '{"labels":["Q1","Q2","Q3","Q4"],"datasets":[{"label":"Revenue","values":[100,150,200,350]},{"label":"Costs","values":[80,90,100,120]}],"title":"Revenue vs Costs"}' -o multi.png6667# Render stats68./scripts/render.sh stats --data '{"stats":[{"label":"Users","value":"12.5K","change":"+12%"},{"label":"Revenue","value":"$45K","change":"+8%"}]}' -o stats.png69```7071## 💡 Sending Images to Users7273After rendering an image, you'll typically want to send it to the user. Here's the recommended workflow:7475### Recommended Workflow:76```bash77# 1. Render to ~/.openclaw/media/ (recommended path)78./scripts/render.sh table --data '...' -o ~/.openclaw/media/my-table.png7980# 2. Send inline via message tool81message(action=send, filePath=/home/ubuntu/.openclaw/media/my-table.png, caption="Caption", channel=telegram, to=<user_id>)82```8384### Tips:85- **Save to `~/.openclaw/media/`** — this path works reliably for inline sending86- **Use descriptive captions** — helps users understand the visual87- **Consider the context** — sometimes saving to disk is fine if the user requested it8889### Example (complete flow):90```bash91# Render92echo '{"title":"My Data","columns":["A","B"],"rows":[["1","2"]]}' | \93 ./scripts/render.sh table -o ~/.openclaw/media/data.png9495# Send96message(action=send, filePath=/home/ubuntu/.openclaw/media/data.png, caption="Here's your data", channel=telegram, to=USER_ID)97```9899## Dependencies100- `/usr/bin/wkhtmltoimage` — HTML to image conversion101- `jq` — JSON parsing