--- name: interactive-dashboard description: "Interactive web dashboards: stock trackers, sector heatmaps, portfolio monitors — served via preview URL" --- # 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 Use this skill for a **live, served web app** — one that needs a running server, not a single file: - User asks for a **dashboard**, **tracker**, or **monitor** that **refreshes live data** (polling, auto-update) - The app needs **server-side logic** — filtering/screening over a large dataset, on-demand fetches, computed endpoints - **Multi-page / routed** apps, or anything that needs React-level component interactivity - The dataset is **too large to embed** in a single HTML file - User explicitly says "preview", "web view", "web app", or wants it running at a URL **Do NOT use if:** - User wants a **self-contained HTML report** — even an *interactive* one (sortable tables, tabs, hover/zoom charts) over a **data snapshot**. That's `.agents/skills/html-report/SKILL.md`: one file in `results/`, keepable, printable, PDF-exportable, share-linkable. Interactivity by itself does **not** require a dashboard. - User wants a **static chart image** → matplotlib/plotly `savefig`. - User wants an **in-chat figure** → `inline-widget` (`ShowWidget`). ### Dashboard vs. HTML Report Both can be interactive, so the divide is **live served app vs. self-contained snapshot file**, not static vs. interactive: | | interactive-dashboard (this skill) | html-report | |---|---|---| | Delivery | A **running server**, exposed via `GetPreviewUrl` | One **`.html` file** in `results/` | | Data | **Live / refreshing**, fetched from a backend; large datasets OK | A **snapshot** embedded in the file | | Interactivity | Full app — routing, server-side filtering, live updates | Client-side over the snapshot — sort, filter, tabs, chart hover/zoom | | Keep / print / share | A URL, live only while the workspace runs | Downloadable, PDF-exportable, share-linkable as one artifact | | Pick when | Data must be live, or compute/scale needs a server | The answer is a deliverable the user keeps | ## Architecture Choose the tier based on complexity: | Tier | When | Stack | Serve command | |------|------|-------|---------------| | **Simple** | Snapshot-at-load data, few charts, no backend logic (still served via preview URL) | 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 | |-----------------|-----------------| | `