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.
git clone --depth 1 https://github.com/ginlix-ai/LangAlpha /tmp/interactive-dashboard && cp -r /tmp/interactive-dashboard/skills/interactive-dashboard ~/.claude/skills/interactive-dashboardSKILL.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/ReactIntegrated 3-statement financial model: linked income statement, balance sheet, and cash flow
Create and manage scheduled and price-triggered automations.
Event tracker: earnings dates, economic releases, conferences, regulatory events
Investment deck QC: number consistency, data-narrative alignment, IB language, formatting audit
Financial model audit: structural checks, formula validation, integrity testing
Competitive landscape analysis: positioning, scorecards, moat assessment, market share trends
Comparable company analysis: operating metrics, valuation multiples, peer benchmarking
DCF valuation: free cash flow projections, WACC, terminal value, sensitivity analysis