Skip to main content
ClaudeWave
Skill1.4k repo starsupdated today

interactive-dashboard

The interactive-dashboard skill builds real-time web dashboards, trackers, and visualizations served through a preview URL, enabling users to interact with dynamic financial data through filtering, drill-downs, and live updates. Use this skill when users request dashboards, portfolio monitors, sector heatmaps, or interactive web apps rather than static charts or reports.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/ginlix-ai/LangAlpha /tmp/interactive-dashboard && cp -r /tmp/interactive-dashboard/skills/interactive-dashboard ~/.claude/skills/interactive-dashboard
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Interactive Dashboard

Build interactive web dashboards inside the sandbox and expose them to the user via `GetPreviewUrl`. Use this skill for any request involving dashboards, trackers, monitors, live visualizations, or interactive web apps.

## When to Use

- User asks for a **dashboard**, **tracker**, **monitor**, or **interactive chart**
- User wants a **web app** or **live visualization** rather than a static image
- User requests something that benefits from interactivity: filtering, drill-downs, hover tooltips, tab switching
- User explicitly says "preview", "web view", or "interactive"

**Do NOT use if:** User wants a static chart image (use matplotlib/plotly `savefig` instead) or a document/report (use docx/pptx skills).

## Architecture

Choose the tier based on complexity:

| Tier | When | Stack | Serve command |
|------|------|-------|---------------|
| **Simple** | Static snapshot, few charts, no server-side logic | Self-contained HTML + CDN libs | `python -m http.server 8050 --bind 0.0.0.0` |
| **FastAPI + HTML** | Live data refresh, server-side logic, no React needed | FastAPI serves `static/` + `fetch()` polling | `bash start.sh` |
| **Complex** | Filtering, routing, component interactivity, multi-page | FastAPI backend + Vite/React frontend | `bash start.sh` |

**Decision rule:** Start with Simple. Escalate to FastAPI + HTML when user needs live data refresh or server-side logic. Escalate to Complex only when user needs React-level component interactivity, client-side routing, or a multi-page SPA.

**Port convention:** Use port **8050** (default). Range 8050-8059 for dashboards.

### CSP / Iframe Safety

The preview iframe enforces Content Security Policy (CSP). Certain patterns are **silently blocked** — no error banner, just dead UI elements. Always use the safe alternatives:

| Blocked pattern | Safe alternative |
|-----------------|-----------------|
| `<button onclick="fn()">` | `el.addEventListener('click', fn)` |
| `<div onmouseover="fn()">` | `el.addEventListener('mouseover', fn)` |
| Any `on*="..."` HTML attribute | `el.addEventListener(event, fn)` |
| `innerHTML` with `onclick` | `document.createElement()` + `addEventListener` |
| `eval("code")` | Direct function calls |
| `new Function("code")` | Named function declarations |
| `setTimeout("code string", ms)` | `setTimeout(fn, ms)` (function reference) |
| `<a href="javascript:...">` | `<a href="#" data-action="...">` + `addEventListener` |

**Quick self-check** — run before serving to catch violations:

```python
import subprocess
result = subprocess.run(
    ["grep", "-rnE", r'on(click|input|change|focus|blur|submit|load|error|mouse|key)\s*=',
     "work/dashboard/"],
    capture_output=True, text=True
)
if result.stdout.strip():
    raise RuntimeError(f"CSP-unsafe inline handlers found:\n{result.stdout}")
```

**Template literal hygiene** — when building HTML strings in JS template literals, CSS semicolons inside `${}` expressions cause silent parse failures:

```javascript
// BAD — semicolon inside ${} terminates the expression early
const el = `<div style="color:${positive ? 'green' : 'red'; font-weight:600}">`;

// GOOD — close the expression first, then continue the attribute string
const el = `<div style="color:${positive ? 'green' : 'red'};font-weight:600">`;
```

Rule: **never put a CSS semicolon inside `${}`** — always close `}` before the semicolon.

### How Preview Serving Works

`GetPreviewUrl` is a **platform-level tool** available only to the main agent runtime. It is NOT a Python function — do not `import` it or call it from `execute_code`. The agent invokes it as a tool call.

When you call `GetPreviewUrl(port, command, title)`:

1. The **command is persisted to the database** automatically
2. The platform starts the command in a dedicated sandbox session for that port
3. It polls until the port is listening, then generates a signed URL
4. If the port is **already reachable**, the command start is skipped entirely

**Sub-agent fallback:** Sub-agents cannot call `GetPreviewUrl`. Instead, build the dashboard files, start the server for verification, then return the serve details so the orchestrating agent can call `GetPreviewUrl`.

**All tiers** — use the Bash tool with `run_in_background=true` to start the server:

```bash
# Simple tier — Bash tool with run_in_background=true
cd work/<task> && python -m http.server 8050 --bind 0.0.0.0

# Docker tiers — Bash tool with run_in_background=true
cd work/<task> && bash start.sh
```

Then verify it's up in a separate (foreground) Bash call:

```bash
for i in $(seq 1 15); do curl -sf http://127.0.0.1:8050/ > /dev/null && echo "Server ready" && exit 0 || sleep 1; done; echo "FAIL"; exit 1
```

Then return **all three fields** to the orchestrating agent (it needs the command for DB persistence / restart recovery):

```
port: 8050
command: "cd work/<task> && python -m http.server 8050 --bind 0.0.0.0"  # or "bash work/<task>/start.sh"
title: "AAPL Stock Dashboard"
```

The orchestrating agent calls `GetPreviewUrl(port=8050, command="...", title="...")` which persists the command.

**On workspace restart** (user closes and reopens later):
- The sandbox filesystem persists (files, installed packages, Docker image cache all survive)
- Only processes die — the platform looks up the saved command and re-executes it
- The preview URL auto-recovers

**Implication:** Write commands that are **idempotent** — they must work whether run for the first time or re-run after a restart. The platform handles the rest. Docker image cache survives restart so rebuilds are fast (~2-5s with warm cache).

### Sandbox Capabilities

All pre-installed in the Daytona sandbox snapshot — no `pip install` or `apt-get` needed:

- **Python 3.12** + pandas, numpy, plotly, matplotlib, requests, httpx, yfinance
- **FastAPI + uvicorn** (available via `fastmcp` transitive dependency)
- **Node.js 24 + npm** (host sandbox) / **Node.js 20** (Docker `apt install nodejs`) — scaffold Vite/React