Exploratory Data Analysis
spacering-net/codeg
Perform comprehensive exploratory data analysis on scientific data files across 200+ file formats.
Interactive web dashboards: stock trackers, sector heatmaps, portfolio monitors, served via preview URL
$ npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ginlix-ai/LangAlpha interactive-dashboard --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/ginlix-ai/LangAlpha.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/langalpha_deliverables/skills/interactive-dashboard .claude/skills/interactive-dashboard && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "interactive-dashboard" agent skill from https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboard into .claude/skills/interactive-dashboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "interactive-dashboard", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboardType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ginlix-ai/LangAlpha interactive-dashboard --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ginlix-ai/LangAlpha.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/langalpha_deliverables/skills/interactive-dashboard .agents/skills/interactive-dashboard && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "interactive-dashboard" agent skill from https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboard into .agents/skills/interactive-dashboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "interactive-dashboard", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ginlix-ai/LangAlpha interactive-dashboard --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ginlix-ai/LangAlpha.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/langalpha_deliverables/skills/interactive-dashboard .cursor/skills/interactive-dashboard && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "interactive-dashboard" agent skill from https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboard into .cursor/skills/interactive-dashboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "interactive-dashboard", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/ginlix-ai/LangAlpha.git --path plugins/langalpha_deliverables/skills/interactive-dashboard--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ginlix-ai/LangAlpha interactive-dashboard --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ginlix-ai/LangAlpha.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/langalpha_deliverables/skills/interactive-dashboard .gemini/skills/interactive-dashboard && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "interactive-dashboard" agent skill from https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboard into .gemini/skills/interactive-dashboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "interactive-dashboard", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install ginlix-ai/LangAlpha interactive-dashboardInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ginlix-ai/LangAlpha.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/langalpha_deliverables/skills/interactive-dashboard .github/skills/interactive-dashboard && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "interactive-dashboard" agent skill from https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboard into .github/skills/interactive-dashboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "interactive-dashboard", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ginlix-ai/LangAlpha interactive-dashboard --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ginlix-ai/LangAlpha.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/langalpha_deliverables/skills/interactive-dashboard .opencode/skills/interactive-dashboard && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "interactive-dashboard" agent skill from https://github.com/ginlix-ai/LangAlpha/tree/main/plugins/langalpha_deliverables/skills/interactive-dashboard into .opencode/skills/interactive-dashboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "interactive-dashboard", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
interactive-dashboardInteractive web dashboards: stock trackers, sector heatmaps, portfolio monitors, served via preview URL
Interactive Dashboard is an agent skill from ginlix-ai/LangAlpha. Interactive web dashboards: stock trackers, sector heatmaps, portfolio monitors, served via preview URL
Its SKILL.md is about 8.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 11 other files, including reference files (for example `references/chart-patterns.md`, `references/server-main.fastapi-html.py` and `references/server-main.py`).
It sits in Data & Analytics. The repository describes itself as: Claude Code for Financial Market. The licence is Apache-2.0.
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 111a0f6. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (Python, Shell and JavaScript), which the agent can run.
Shell commands in SKILL.md call:
npmpythonbashdockernodeuvuvicornpipaptFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
cdn.jsdelivr.netcdn.plot.lyunpkg.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Interactive Dashboard loads about 8.4k tokens when it runs, and up to ~33k if it reads all its reference files. Until then it costs about 31 tokens; SKILL.md has 3,122 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from ginlix-ai/LangAlpha at commit 111a0f6, republished under its Apache-2.0 licence (© ginlix-ai). 3,122 words, ~8,355 tokens.
.claude/skills/interactive-dashboard/SKILL.md (or your agent's skills folder). This skill also uses 10 other files; get the full folder from GitHub.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.
Use this skill for a live, served web app — one that needs a running server, not a single file:
Do NOT use if:
.agents/skills/html-report/SKILL.md: one file in the task directory, keepable, printable, PDF-exportable, share-linkable. Interactivity by itself does not require a dashboard.savefig.inline-widget (ShowWidget).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 <task_name>/ |
| 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 |
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.
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:
import subprocess
result = subprocess.run(
["grep", "-rnE", r'on(click|input|change|focus|blur|submit|load|error|mouse|key)\s*=',
"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:
// 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.
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):
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:
# Simple tier — Bash tool with run_in_background=true
cd <task> && python -m http.server 8050 --bind 0.0.0.0
# Docker tiers — Bash tool with run_in_background=true
cd <task> && bash start.shThen verify it's up in a separate (foreground) Bash call:
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 1Then return all three fields to the orchestrating agent (it needs the command for DB persistence / restart recovery):
port: 8050
command: "cd <task> && python -m http.server 8050 --bind 0.0.0.0" # or "bash <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):
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).
All pre-installed in the Daytona sandbox snapshot — no pip install or apt-get needed:
fastmcp transitive dependency)apt install nodejs) — scaffold Vite/React projects with npm create vite@latestBefore writing any code:
Use YF MCP servers as the default financial data source (no API keys needed):
from tools.yf_price import get_stock_history, get_multiple_stocks_history
from tools.yf_fundamentals import get_company_info, compare_valuations
from tools.yf_analysis import get_analyst_price_targets, get_news
from tools.yf_market import get_sector_info, screen_stocksAlways fetch and validate data before writing any HTML/React code. Check for empty responses.
Use pandas to clean, aggregate, and compute derived metrics:
import pandas as pd
import json
# Fetch
history = get_stock_history("AAPL", period="1y", interval="1d")
info = get_company_info("AAPL")
# Process
df = pd.DataFrame(history)
df['change_pct'] = df['close'].pct_change() * 100
# Prepare for frontend
chart_data = json.dumps({
"dates": df['date'].tolist(),
"prices": df['close'].tolist(),
"volumes": df['volume'].tolist(),
})Simple tier — write a self-contained HTML file:
html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AAPL Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
<style>
/* See references/ui-components.md for the theme foundation CSS */
</style>
</head>
<body>
<script>const DATA = {chart_data};</script>
<script>
/* Chart rendering code */
</script>
</body>
</html>"""
with open("dashboard/index.html", "w") as f:
f.write(html)FastAPI + HTML tier — write a FastAPI server with API routes + StaticFiles mount, and a single static/index.html with fetch() polling (see FastAPI + HTML Tier section below).
Complex tier — scaffold a FastAPI + Vite/React project (see Complex Tier section below).
Tier 1 — Syntax check (required, < 1 second)
Extract <script> blocks from the HTML and check with node --check:
import re, subprocess, tempfile, os
with open("dashboard/index.html") as f:
html = f.read()
scripts = re.findall(r'<script(?![^>]*src)[^>]*>(.*?)</script>', html, re.DOTALL)
for i, src in enumerate(scripts):
with tempfile.NamedTemporaryFile(suffix=".js", mode="w", delete=False) as tmp:
tmp.write(src)
tmp_path = tmp.name
result = subprocess.run(["node", "--check", tmp_path], capture_output=True, text=True)
os.unlink(tmp_path)
if result.returncode != 0:
raise RuntimeError(f"JS syntax error in script block {i+1}:\n{result.stderr}")
print("Syntax check passed")Also run the CSP self-check grep from the CSP section above.
Tier 2 — Browser verification (recommended for interactive dashboards)
Run when the dashboard has buttons, filters, or tabs. Skip for static data displays.
After GetPreviewUrl starts the server, run a Playwright check to catch runtime errors:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
js_errors = []
page.on("pageerror", lambda exc: js_errors.append(str(exc)))
page.goto("http://127.0.0.1:8050/", wait_until="networkidle", timeout=20000)
assert not js_errors, f"JS runtime errors: {js_errors}"
assert len(page.locator("body").inner_text().strip()) > 20, "Page appears blank"
page.screenshot(path="dashboard/verify-screenshot.png", full_page=True)
browser.close()
print("Browser verification passed")See references/verification.md for extended templates with button-click testing and API response validation.
# Simple tier
GetPreviewUrl(port=8050, command="cd dashboard && python -m http.server 8050 --bind 0.0.0.0", title="AAPL Dashboard")
# FastAPI + HTML tier / Complex tier
GetPreviewUrl(port=8050, command="bash dashboard/start.sh", title="Stock Dashboard")Local verification before GetPreviewUrl — if you need the server running for Playwright verification, use the Bash tool with run_in_background=true (see sub-agent fallback above for the pattern). Do NOT use subprocess.Popen from execute_code — the process becomes a zombie when the tool-call shell exits.
After the user sees the preview, adjust layout, data, or charts based on feedback.
Default data sources for common dashboard needs:
| Need | MCP Server | Function | Key params |
|---|---|---|---|
| Price history | yf_price | get_stock_history | ticker, period="1y", interval="1d" |
| Multi-stock prices | yf_price | get_multiple_stocks_history | tickers=["AAPL","MSFT"] |
| Dividends & splits | yf_price | get_dividends_and_splits | ticker |
| Company profile | yf_fundamentals | get_company_info | ticker |
| Income statement | yf_fundamentals | get_income_statement | ticker, quarterly=True |
| Balance sheet | yf_fundamentals | get_balance_sheet | ticker, quarterly=True |
| Cash flow | yf_fundamentals | get_cash_flow | ticker, quarterly=True |
| Valuation comps | yf_fundamentals | compare_valuations | tickers=["AAPL","MSFT","GOOGL"] |
| Financial comps | yf_fundamentals | compare_financials | tickers, statement_type="income" |
| Earnings data | yf_fundamentals | get_earnings_data | ticker |
| Analyst targets | yf_analysis | get_analyst_price_targets | ticker |
| Recommendations | yf_analysis | get_analyst_recommendations | ticker |
| Upgrades/downgrades | yf_analysis | get_upgrades_downgrades | ticker |
| Earnings estimates | yf_analysis | get_earnings_estimates | ticker |
| Revenue estimates | yf_analysis | get_revenue_estimates | ticker |
| Growth estimates | yf_analysis | get_growth_estimates | ticker |
| Institutional holders | yf_analysis | get_institutional_holders | ticker |
| Insider transactions | yf_analysis | get_insider_transactions | ticker |
| ESG data | yf_analysis | get_sustainability_data | ticker |
| News | yf_analysis | get_news | ticker, count=10 |
| Ticker search | yf_market | search_tickers | query, max_results=8 |
| Market status | yf_market | get_market_status | market="US" |
| Stock screener | yf_market | screen_stocks | filters, sort_field, count |
| Predefined screens | yf_market | get_predefined_screen | screen_name (day_gainers, most_actives, etc.) |
| Earnings calendar | yf_market | get_earnings_calendar | start, end (YYYY-MM-DD) |
| Sector info | yf_market | get_sector_info | sector_key (technology, healthcare, etc.) |
| Industry info | yf_market | get_industry_info | industry_key |
Many fields are already in display units — do NOT multiply by 100:
| Field | Unit | Example | Note |
|---|---|---|---|
regularMarketChangePercent | % (not decimal) | 0.389 = +0.39% | Do NOT multiply by 100 |
dividendYield | % (not decimal) | 0.41 = 0.41% | Same convention |
marketCap | Absolute USD | 3.71e12 | Divide by 1e9 for $B display |
trailingPE | Ratio | 31.98 | Display directly |
get_predefined_screen Response StructureQuotes are nested — not at the top level:
result = get_predefined_screen("day_gainers")
quotes = result["data"]["quotes"] # nested at result["data"]["quotes"], NOT result["quotes"]
# Each quote: symbol, regularMarketPrice, regularMarketChangePercent, marketCap, ...Inside Docker containers, MCP tool modules are unavailable. Use yfinance directly:
import yfinance as yf
# Stock screener (yfinance 1.2.0+)
result = yf.screen("day_gainers", count=5)
quotes = result.get("quotes", [])
# Stock data
ticker = yf.Ticker("AAPL")
info = ticker.info
hist = ticker.history(period="1y")Read .agents/skills/ui-design/SKILL.md for design quality (typography, color, avoiding generic AI aesthetics).
A dashboard must follow the theme it is viewed in — never ship a fixed palette:
--color-bg-page, --color-text-primary, …) that flip with the user's light/dark setting.prefers-color-scheme.The Theme Foundation block in references/ui-components.md §1 implements both: each bridge variable reads the app token first and falls back to an OS-adaptive value. Include that block verbatim in every dashboard, then style only with the bridge variables. Canvas/SVG chart code can't read var() — read the resolved value with the pick() helper (see references/chart-patterns.md). Never hardcode a palette hex in styles.
| Bridge variable | App token | Role |
|---|---|---|
--bg-page | --color-bg-page | Page background |
--bg-card | --color-bg-card | Card / panel background |
--bg-elevated | --color-bg-elevated | Raised surface (menus, popovers) |
--bg-subtle | --color-bg-subtle | Zebra rows, quiet fills |
--bg-hover | --color-bg-hover | Hover highlight, table headers |
--text-primary | --color-text-primary | Primary text |
--text-secondary | --color-text-secondary | Labels, captions, axis ticks |
--text-tertiary | --color-text-tertiary | De-emphasized text |
--border | --color-border-muted | Borders, grid lines |
--accent | --color-accent-primary | Links, primary series, active tab |
--positive | --color-profit | Gains |
--negative | --color-loss | Losses |
--warning | --color-warning | Cautions |
Light and dark literal values live only in the foundation block — don't restate them elsewhere.
auto-fit and minmax() for responsive columnsfont-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;| Element | Size |
|---|---|
| Page title (h1) | 1.5rem |
| Section title (h2) | 1.125rem |
| Body text | 0.875rem |
| Labels / captions | 0.75rem |
| KPI value | 1.75rem (bold) |
$ prefix ($182.52)% suffix, color-coded green/red (+2.34% / -1.56%)$2.87T, $142.5B, $3.2M)12,345,678) or abbreviated (12.3M)MMM DD, YYYY format (Mar 15, 2026)See references/ui-components.md for complete CSS and component code.
For live-data dashboards without React. FastAPI serves API endpoints and static HTML directly — no npm, no build step. Use the copy-ready template files with .fastapi-html suffix in references/:
<task>/
├── Dockerfile # cp references/Dockerfile.fastapi-html Dockerfile
├── start.sh # cp references/start.sh start.sh
├── server/
│ ├── main.py # cp references/server-main.fastapi-html.py server/main.py
│ └── requirements.txt # cp references/requirements.txt server/requirements.txt
└── static/
└── index.html # Single HTML file with fetch() pollingcp commands above, then add your API routes to server/main.pyserver/requirements.txt (append pandas, yfinance, etc.)static/index.html with fetch() calls to your API routes for live dataGetPreviewUrl(port=8050, command="bash <task>/start.sh", title="Dashboard")Dockerfile (references/Dockerfile.fastapi-html) — Python 3.12-slim only (no Node/npm). Uses uv pip install for fast deps.
server/main.py (references/server-main.fastapi-html.py) — FastAPI skeleton with CORS, HEAD /, /healthz, and StaticFiles mount for static/ directory. StaticFiles is the last mount (catches all unmatched routes).
start.sh — same references/start.sh template (works unchanged for all Docker tiers).
frontend/ directory — HTML lives in static/python:3.12-slim onlyStaticFiles mount — serves static/ directory with html=True (auto-serves index.html)fetch() for live data — HTML uses setInterval(() => fetch('/api/data').then(...), 30000) for auto-refreshindex.html, no client-side router neededWhen using FastAPI + Vite/React, scaffold this structure using the copy-ready template files in references/:
<task>/
├── Dockerfile # Copy from references/Dockerfile
├── start.sh # Copy from references/start.sh
├── server/
│ ├── main.py # Copy from references/server-main.py, add your API routes
│ ├── requirements.txt # Copy from references/requirements.txt, add your deps
│ ├── routes/ # API route modules (stocks.py, sectors.py)
│ └── models.py # Pydantic response models
├── frontend/
│ ├── package.json # Vite + React + chart libraries
│ ├── vite.config.js # Copy from references/vite.config.js
│ ├── index.html
│ └── src/
│ ├── App.jsx # Main app with routing/tabs
│ ├── components/ # Chart, KPI, Table components
│ ├── hooks/ # useStockData, useSectorData, etc.
│ └── utils/ # formatters, color helpers
└── verify.py # Copy from references/verification.md (optional)references/ into <task>/ — they work with zero modifications for port 8050server/main.py (the template includes CORS, HEAD /, /healthz, and static file serving)server/requirements.txt (template includes fastapi + uvicorn)frontend/src/ (vite.config.js template proxies /api to backend on port 8051)GetPreviewUrl(port=8050, command="bash <task>/start.sh", title="Dashboard")Dockerfile (references/Dockerfile) — Python 3.12 + Node + uv + tzdata. Builds frontend at image time, serves static files from FastAPI. Uses uv pip install for fast dependency installation.
start.sh (references/start.sh) — Cold-boot safe Docker wrapper. Starts dockerd if needed, builds image (uses layer cache on re-runs), removes old container, starts new one, health-checks with log dump on failure. Env var overrides: PORT (default 8050), NAME (default "dashboard").
server/main.py (references/server-main.py) — FastAPI skeleton with CORS, HEAD / (liveness for platform proxy), /healthz, SPA catch-all route for client-side routing (/tab/news, /stocks/AAPL → index.html), and a 503 fallback if the frontend build is missing.
server/requirements.txt (references/requirements.txt) — Minimal: fastapi + uvicorn. Append project-specific packages (pandas, yfinance, etc.).
frontend/vite.config.js (references/vite.config.js) — Vite + React with /api proxy to backend on port 8051.
Critical: Vite proxy is dev-only. The
proxysetting invite.config.jsonly applies duringnpm run dev. The production build outputs plain static files with no proxy. In the Docker image, FastAPI serves both the built SPA fromfrontend/dist/and all/api/*routes from the same port. The referenceserver-main.pytemplate already does this correctly — do NOT use a two-process architecture with separate static file server and API server.
tools/ modules (e.g., from tools.yf_price import ...) exist only in the host workspace Python environment — they are NOT copied into the Docker image. FastAPI server code inside Docker must call yfinance directly. Add yfinance to server/requirements.txt--network host: Required for the container to reach external APIs (yfinance, MCP servers). Already set in start.sh templatetzdata: Required for yfinance timezone handling. Already in Dockerfile templatedocker logs dashboard to debug startup failuresfuser -k 8050/tcp 2>/dev/null || true
cd frontend && npm install --prefer-offline && npm run build && cd ..
cd server && uvicorn main:app --host 0.0.0.0 --port 8050| Library | CDN URL | Best for |
|---|---|---|
| Chart.js | https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js | Line, bar, pie, doughnut, area |
| Plotly.js | https://cdn.plot.ly/plotly-2.35.2.min.js | Candlestick, heatmap, treemap |
| Lightweight Charts | https://unpkg.com/lightweight-charts@4/dist/lightweight-charts.standalone.production.js | TradingView-style candlestick |
Default to Chart.js. Use Plotly for candlesticks/heatmaps. Lightweight Charts only for TradingView-style.
| Library | Package | Best for |
|---|---|---|
| Recharts | recharts | Composable React charts — line, bar, area, pie |
| Plotly React | react-plotly.js plotly.js | Candlestick, heatmap, treemap |
| Lightweight Charts | lightweight-charts | TradingView-style financial charts |
Default to Recharts. Use Plotly for advanced financial charts.
See references/chart-patterns.md for ready-to-use code snippets.
Data: get_stock_history, get_company_info, get_analyst_price_targets, get_news
Layout:
Data: get_multiple_stocks_history, compare_valuations, compare_financials
Layout:
Data: get_sector_info, screen_stocks with sector filters, get_predefined_screen
Layout:
Data: get_earnings_calendar, get_earnings_data, get_earnings_estimates
Layout:
Data: get_multiple_stocks_history, compare_valuations, get_company_info for each holding
Layout:
GetPreviewUrlauto-fit for layouts. No horizontal scroll at any width<script>const DATA = ${json.dumps(data)}</script> — never inline raw Python dictsjson.dumps() with ensure_ascii=False for safe JSON embedding<style>, all JS in <script>, libraries via CDN <script src="...">index.html — eliminates path bugsuseStockData(ticker), useSectorData(key) for data fetching/api/* and the SPA from one porthost: '0.0.0.0': Both FastAPI and Vite must bind to 0.0.0.0, not 127.0.0.1 or localhost| Problem | Solution |
|---|---|
GetPreviewUrl returns error | Port already in use — try a different port (8051, 8052, ...) |
| Page is blank | Check for JS errors — ensure all getElementById targets exist |
| Data is empty | Validate MCP tool response before embedding — check for None or empty lists |
| Buttons/inputs do nothing | CSP blocking inline handlers — replace onclick= etc. with addEventListener. Run CSP self-check |
| FastAPI won't start | Ensure host='0.0.0.0' in uvicorn.run() |
| Vite won't start | Ensure --host 0.0.0.0 flag and check if port is free |
| CORS errors | Add CORSMiddleware to FastAPI or use Vite proxy |
| Charts don't render | CDN scripts must load before chart initialization — use DOMContentLoaded event |
| Iframe shows "refused to connect" | Server not ready yet — add a small delay or retry logic |
| HEAD / returns 404 or 405 | Add @app.head("/") as its own function — don't stack with /healthz (use server-main.py template) |
| SPA deep route returns 404 | Add catch-all @app.get("/{full_path:path}") that serves index.html for non-file paths (use server-main.py template) |
start.sh fails on restart | Ensure idempotent: dockerd startup check, docker rm -f before docker run (use start.sh template) |
| Docker: yfinance timezone error | Add tzdata package to Dockerfile (included in template) |
| Docker: can't reach external APIs | Use --network host flag (included in start.sh template) |
GetPreviewUrl not found / NameError | Tool only available to main agent runtime — sub-agents use Bash tool with run_in_background=true to start the server, then report port/command/title back |
Playwright ERR_CONNECTION_REFUSED | Use 127.0.0.1:PORT not localhost — sandbox resolves localhost to IPv6 (::1) first |
Background server died / <defunct> | Use Bash tool with run_in_background=true — do NOT use subprocess.Popen from execute_code (process becomes zombie when tool-call shell exits) |
ModuleNotFoundError: tools.* in Docker | MCP tools are host-only — use yfinance directly inside Docker containers |
Before calling GetPreviewUrl:
Data & Code
<task>/ directoryjson.dumps()CSP Safety
onclick, oninput, onchange, etc.) — all events via addEventListenereval(), new Function(), or string-based setTimeout()javascript: URLsVerification
node --check on extracted script blocks)Serving
0.0.0.0 (not 127.0.0.1 or localhost)GetPreviewUrl is idempotent (works on re-run after restart)start.sh and Dockerfile copied from templatesHEAD / endpoint (use server-main.py template)UI Quality
pick() for canvas colors) used — no palette hexes in stylesGetPreviewUrl is descriptive (e.g., "AAPL Stock Dashboard", not "Preview")© ginlix-ai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 10 other files (references) in plugins/langalpha_deliverables/skills/interactive-dashboard of ginlix-ai/LangAlpha.
Open the folder on GitHubat commit 111a0f6
Interactive Dashboard next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Interactive Dashboard this skillginlix-ai/LangAlpha | 1.8k | — | ~8.4k | Automated safety check: Pass | Apache-2.0 | |
| Exploratory Data Analysisspacering-net/codeg | 3.8k | 15 repos | ~3.6k | Automated safety check: Pass | MIT | |
| MatplotlibzLanqing/codex-claude-academic-skills | 4.6k | 18 repos | ~2.9k | Automated safety check: Pass | MIT | |
| Scikit LearnzLanqing/codex-claude-academic-skills | 4.6k | 17 repos | ~3.9k | Automated safety check: Pass | BSD-3-Clause | |
| Chart Visualizationbytedance/deer-flow | 83k | 2 repos | ~840 | Automated safety check: Pass | MIT | |
| TimesFM Forecastinggoogle-research/timesfm | 34k | — | ~4.7k | Automated safety check: Pass | Apache-2.0 |
spacering-net/codeg
Perform comprehensive exploratory data analysis on scientific data files across 200+ file formats.
zLanqing/codex-claude-academic-skills
Low-level plotting library for full customization. An agent skill from zLanqing/codex-claude-academic-skills.
zLanqing/codex-claude-academic-skills
Machine learning in Python with scikit-learn. An agent skill from zLanqing/codex-claude-academic-skills.
bytedance/deer-flow
Picks a suitable chart type from 26 options for your data, maps the data to that chart's parameters and generates a chart image through a JavaScript script.
google-research/timesfm
Forecasts any univariate time series zero-shot with Google's TimesFM model, returning point forecasts and calibrated prediction intervals without training.
vercel/next.js
Benchmark React or Next.js changes on Vercel Sandbox VMs with paired A/B statistics: react PR/commit vs base, or Next.js PR/commit vs base, measured end-to-end through the bench/render-pipeline app…
ginlix-ai/LangAlpha
Quality-checks an investment deck in .pptx form before it goes out: number consistency, chart and narrative alignment, source coverage, language and a circulation verdict.
ginlix-ai/LangAlpha
Produces a first-time equity research initiation report in five tasks: company research, financial model, valuation, charts and a DOCX report.
ginlix-ai/LangAlpha
Builds or repairs an integrated income statement, balance sheet and cash flow model in Excel with live formulas, supporting schedules, scenarios and a Checks sheet.
ginlix-ai/LangAlpha
Audits an existing Excel financial model without editing it, checking structure, formulas, integrity identities and source tie-out, and ends in a prioritized issue log.
ginlix-ai/LangAlpha
Builds a live Excel DCF valuation workbook with free cash flow projections, WACC, terminal value, three scenarios, sensitivity grids and a reverse DCF.
ginlix-ai/LangAlpha
Builds Word files with python-docx, edits existing ones in place with tracked changes and comments, then renders and validates the result.
Categories
Interactive web dashboards: stock trackers, sector heatmaps, portfolio monitors, served via preview URL. Interactive Dashboard is an agent skill from ginlix-ai/LangAlpha.
Interactive Dashboard fits situations like: data & Analytics work in your project.
Run `npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a claude-code`. Or copy the skill folder (plugins/langalpha_deliverables/skills/interactive-dashboard in ginlix-ai/LangAlpha) into .claude/skills/interactive-dashboard in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a codex`. Or copy the skill folder (plugins/langalpha_deliverables/skills/interactive-dashboard in ginlix-ai/LangAlpha) into .agents/skills/interactive-dashboard in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ginlix-ai/LangAlpha --skill interactive-dashboard -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/interactive-dashboard, .gemini/skills/interactive-dashboard, .github/skills/interactive-dashboard and .opencode/skills/interactive-dashboard in your project.
Going by SKILL.md and its folder, Interactive Dashboard needs Python, a shell and JavaScript for the scripts in its folder and the command-line tools its instructions call (npm, python, bash, docker, node and uv). Our summary lists: Python 3; Node.js; A Bash shell; Docker.
SKILL.md names 3 domains. In commands or code: cdn.jsdelivr.net, cdn.plot.ly and unpkg.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Interactive Dashboard is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.4k tokens (SKILL.md is roughly 33k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 25k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Interactive Dashboard: Exploratory Data Analysis (spacering-net/codeg, 3.8k stars), Matplotlib (zLanqing/codex-claude-academic-skills, 4.6k stars), Scikit Learn (zLanqing/codex-claude-academic-skills, 4.6k stars) and Chart Visualization (bytedance/deer-flow, 83k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ginlix-ai (a GitHub organization) maintains it in ginlix-ai/LangAlpha, which has 1,806 GitHub stars. The repository holds 38 skills in this directory. The repository was last updated on October 8, 2026.
Source: ginlix-ai/LangAlpha on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.