The problem
Raw JSON data is useful but not readable to most people who need to make decisions from it. Building a dashboard from scratch takes time. Business intelligence tools have costs and setup overhead. The gap between "here is the data" and "here is something useful to look at" is wider than it should be.
Instant Dashboard closes that gap with a single interaction: paste your JSON, describe what you want, get a visual result.
What it does
You paste structured JSON data into the app. You describe your preferences in plain English -- chart types, colors, what to emphasize, whether you want a dark theme. The app sends this to a language model, and the response streams back to your browser character by character, appearing as live code in a code view panel.
When the generation finishes, the app validates the HTML and renders it in a sandboxed preview iframe. The result is a self-contained HTML dashboard with inline CSS that you can download and use anywhere, with no external dependencies.
No account needed. No data stored. The whole interaction is stateless.
The streaming architecture
Streaming was the key technical decision. Rather than waiting for the entire dashboard to generate and then showing it, the app forwards each token from the LLM to the browser the moment it arrives using Server-Sent Events (SSE).
Browser
POST /api/generate-stream
|
Flask opens SSE response (text/event-stream)
|
LLM generates tokens
|
Each token: emit "data: {chunk: '...'}\n\n"
|
Generation complete: validate full HTML
|
Valid: emit "event: done" with final HTML
Invalid + retries remaining: emit "event: retry", loop
Invalid + no retries: emit "event: error"
One important detail: the X-Accel-Buffering: no response header disables Nginx proxy buffering. Without this, a proxy layer would accumulate the entire response before forwarding it to the browser, which would break the streaming effect entirely.
Auto-retry on bad output
Language models occasionally produce output that doesn't quite match the instructions -- malformed HTML, markdown fences that weren't stripped, incomplete documents. The server automatically retries up to three times before surfacing an error. Each retry emits a status event so the frontend can show "Retrying..." rather than just appearing stuck.
Validation pipeline
The generated HTML goes through a few checks before reaching the iframe:
- Strip markdown code fences (models sometimes wrap output in ```html blocks even when told not to)
- Verify a
<!DOCTYPE html>declaration is present - Check for
<html>and<body>structure - Remove
javascript:URI schemes from links as a safety measure
The iframe uses sandbox="allow-same-origin allow-scripts" so inline scripts in the generated dashboard are isolated from the parent page.
The system prompt
The LLM is instructed with a specific set of constraints that make the output reliable:
- Return only a valid, complete
<!DOCTYPE html>document -- no markdown, no explanation - Use only inline CSS; no CDN dependencies
- Use only data from the provided JSON -- no made-up values
- Display "Data Unavailable" for missing fields rather than guessing
- Follow the user's visual instructions precisely
Getting these constraints right was iterative. Early versions produced partial documents, or added explanatory text before the HTML, or included CDN links that wouldn't load in the sandboxed iframe. Each constraint was added to fix a specific observed failure mode.
Frontend state management
The generator page manages a single state object. Every action updates this state, then a render function reconciles the UI from it. This made the streaming states (idle, streaming, retrying, done, error) easier to manage cleanly than scattering DOM updates across event handlers.
Provider flexibility
The LLM integration is fully configurable through environment variables. Any OpenAI-compatible API endpoint works -- model name, API URL, and API key are all external to the code. This made it easy to test with different models and switch to whichever was producing the best results at the time.
Tech stack
| Layer | Technology |
|---|---|
| Backend | Python, Flask |
| Streaming | Server-Sent Events (SSE) |
| LLM | OpenAI-compatible API (configurable) |
| HTML validation | Custom pipeline |
| Frontend | Vanilla JS (ES Modules), Vanilla CSS |
| Hosting | Vercel (serverless Python) |