Start here
How it works
The path a dashboard takes from your AI tool through compile, validate and seed, to a scheduled refresh that rewrites only its data.
There are two loops. The authoring loop runs when you ask for a dashboard and involves your AI. The refresh loop runs on a schedule and involves nobody. Almost everything surprising about Dashies follows from the fact that these are separate.
The authoring loop
Your AI tool talks to the Dashies publish service over MCP. It sends a spec: one small YAML document naming a connection, a schedule, one or more datasets (each a SQL query plus its declared dimensions and measures), and the tiles that display them.
The server then does four things, in order, and stops at the first failure:
- Compile. The spec becomes one self-contained HTML file: the markup, the slots each tile reads from, an empty runtime marker, and a refresh manifest recording the SQL, the declarations and the schedule.
- Validate. Structural and correctness rules run against the spec. A tile bound to a measure the query never returns, a measure that cannot be re-aggregated in the mode you picked, a filter that cannot be answered by the data you are shipping: each is refused with a pointer at the exact field.
- Seed. Every dataset's SQL is executed once, read-only, through the same confined executor the scheduler will use later. The results are baked into the file. A dataset that fails, returns zero rows, or returns columns that do not match its declarations cannot publish.
- Store. The file goes to object storage, the row goes to the database, and the previous body is snapshotted into version history.
Seeding is why a freshly published dashboard already has real numbers on it instead of a loading state, and it is also the strongest check in the pipeline: it proves the SQL actually runs inside the executor that will run it unattended.
The refresh loop
A scheduler sweeps for due dashboards. For each one it re-runs the manifest's SQL against the same connection, and rewrites only the data inside the stored file. No AI is involved, no model is called, and the markup is not regenerated.
| Stage | Who does it | What it touches |
|---|---|---|
| Author | your AI tool | writes the spec |
| Compile, validate, seed | the publish service | produces the file and the manifest |
| Store | the publish service | object storage plus a version snapshot |
| Refresh | the scheduler, on your cadence | the data block inside the file, nothing else |
| Serve | the router, on every request | injects the current runtime, then streams the file |
Why only the data is rewritten
The published file carries its numbers in exactly one place: a single
<script type="application/json" id="dashies-data"> block. Refresh finds that
block by its id, replaces the JSON between the tags, and writes the file back.
The consequence is the one people underestimate: your design is not regenerated. Whatever the dashboard looked like when it was published is byte-for-byte what it looks like after a thousand refreshes. The full contract is in The data island.
Why the runtime is not in the file
The compiled file does not contain the client-side code that draws the charts. It contains an empty marker. The current runtime is inserted at serve time, on every request, and is never stored.
That means a dashboard published a year ago runs today's runtime, with today's fixes, without being republished. See The runtime.
Where it can go wrong
Each of these has a page, because each is a real failure people hit:
- The query is correct SQL but the number it produces cannot be re-aggregated the way the dashboard will re-aggregate it. See Measure correctness.
- The data you ship is the wrong shape for the filters you want. See Datasets and the four modes.
- The connection is real and yours, but not usable by this dashboard. See Connections and scope.
- The refresh is armed but the plan does not include it. See Plans and what is gated.
Next
Is Dashies right for you?, or build one in the Quickstart.