---
title: Progress Dashboard
description: Keep a live progress dashboard for a long task, generated by a script from your project's own files so it never goes stale.
meta: Claude Code Prompt
---

Gives a long task a page you can glance at instead of scrolling back through the session, and keeps it honest. Claude writes a small script that builds one HTML file, `dashboard/index.html`, from the project's own files, and runs it after every step (or inside the build, where the project has one), so the page is never edited by hand and never drifts. Each section reads one source: the steps, questions, and stuck items from a small state file, the latest results from git, the whole roadmap with every subtask and the latest release from your docs, and any live counts straight from the project's data. It shows the questions waiting for you, each with the default Claude will take if you do not answer, and when progress was last recorded. If progress stops being recorded, the page says so in a visible warning rather than looking live. Every dashboard follows one layout, the one running at https://azqato.github.io/prompts/dashboard/, written out in full in the prompt; the colors and fonts are your project's own branding, and a project with its own page layout can use that instead. The page opens with a double-click, reloads itself every ten seconds, and makes no network requests. It is published with the project, so on a static site anyone can watch progress at `/dashboard/`, and Claude keeps anything private off it.

The script is small, written in the language your project already uses, and adds no dependencies; nothing else is installed, and no agents or plugins are set up. Any existing status page is folded into the dashboard and redirected, so there is one place to look. When Claude needs a decision, it adds the question and carries on with whatever does not depend on the answer. The first time, it takes the palette and fonts from your project's branding and records them in `CLAUDE.md` after you confirm. It checks the script before relying on it: two runs give the same page, and the page fits a phone screen. When the task is done, it asks whether to make this a standing rule, and shows you the exact lines before writing them.

## Prompt

```
Keep a progress dashboard for this task, generated by a script from the project's own files. Never edit the dashboard page by hand, and do not create or install any agents, subagents, or plugins.

Start
- Read the README, CLAUDE.md, and docs/ if they exist. Check whether a dashboard style is already recorded, whether the project has a build step, and whether any page already reports live status (an ingestion, queue, or build status page).
- If no style is recorded, take it from the project's existing branding, never invent one: its design doc (such as docs/DESIGN.md), its CSS custom properties or theme file, and any brand files. Take the background, panel, border, text, and muted colors, the accent, the status colors if it has them, and the font families, and fill any gap from the nearest brand color rather than a new one. Only where the project has no branding at all, ask me once, with your suggested default for each, and wait: light or dark, and one accent color. Show me the palette with where each color came from, and the lines that record it under a "Progress dashboard" heading in CLAUDE.md (creating the file if needed), and write them once I confirm.
- Tell me the task as you understand it, broken into steps, and the default you will take for each decision you can already foresee. If the task itself is unclear, ask a short follow-up rather than guessing.

Sources: one per section
Each section of the page reads exactly one source. The page holds no fact of its own.
- Steps, Questions, and Stuck: a state file, dashboard/state.json, holding the task name, a one-line summary, the commit the task started from, the stale limit in minutes (default 30), and lists of steps (name, status, and the time the status was set, from the system clock), questions (question, default, open or answered by default), and stuck items (what, waiting for). You update this file, never the page. Where the project already tracks the task's steps in its docs, with a Status marker on each, read the steps from there instead, and keep only questions and stuck items in state.json. Never keep the same steps in both.
- Latest results: from git, the files changed since the task's starting commit, each with its last commit message, plus uncommitted changes. Where there is no git, use the newest changelog entry, or failing that the files the task touched by modification time. Never type results in by hand, and leave the dashboard page itself out of the list.
- Roadmap, where the project keeps one (such as a Roadmap section in docs/PRD.md): parsed from that doc on every run, and shown in full. List every milestone and every subtask under it, in the roadmap's own order, each with its status: planned or proposed updates, scoped work, deferred items, and any verification checklist. Completed items stay listed but dimmed, so what is open stands out. Above the list, a card counting what is done out of the whole. Keep the roadmap parseable: a markdown table with a Status column, or a Status line under each item. Leave the section out where there is no roadmap.
- Latest release, where the project keeps a changelog: the newest entry's version, date, and headings.
- Live project status, where the task drives something measurable (items processed, a queue, a pipeline): read straight from the project's data files and shown as its own section, with counts.
- Under each section's heading, a small line naming its source and when that source last changed.
- If a source cannot be read or parsed, the section says so, and names the file and the reason. It never shows an empty state that looks like good news.

Generator
- Write one small script in the language the project already uses, with no new dependencies, that reads the sources above and writes dashboard/index.html. Put it with the project's other scripts, or at dashboard/generate.<ext> if there is no such place.
- If the project has a build step that runs after each unit of work, call the generator from it. Otherwise run it with one command after every step, and whenever state.json changes. Running it is the update: never patch the HTML.
- Write the page atomically (to a temporary file, then rename), so a reload never catches it half written. Rewrite it only when its content, ignoring the generation time, has changed, so version control sees no change when nothing changed.
- The page's first line is a comment saying it is generated, naming the script and the command, and that it must not be edited by hand.

Page
- One file that opens by double-clicking. No server, no network requests, and no external scripts, fonts, or images: everything is inline. Name the brand's fonts first in each font stack, followed by system fonts, and never download or link one.
- It reloads itself every 10 seconds with <meta http-equiv="refresh" content="10">, which works from a local file.
- Times are honest. The top bar shows when progress was last recorded: the last change to state.json, or to the step statuses in the docs where steps live there. The generation time goes in the footer. One small inline script, with no network access, compares the last-recorded time with the viewer's clock and, while the task is open, shows a visible "May be stale: no progress recorded for N minutes" banner once the stale limit has passed, and turns the top bar's dot to the stale color. The page reads correctly with the script blocked; only the banner is lost. This is the only script on the page.
- Use this layout every time, in this order. Only the colors and fonts change, and they come from the recorded style. A working example is at https://azqato.github.io/prompts/dashboard/, which you may open to see it, but these lines are the specification, so build from them even if that page cannot be reached, and never copy its gold-on-black colors or its content.
  - Sidebar, on the left: a small brand mark and the word Progress, a box naming the current task, then links to each section below with a count beside each (steps, open questions, stuck items, results, and roadmap items still open). The link to the overview is highlighted in the accent color. At the bottom, a line saying the page is generated and naming the script. Below 900px wide the sidebar becomes a strip of section links across the top that scrolls sideways, not a drawer.
  - Top bar, sticky: the task name, a small pulsing dot with the time progress was last recorded and "refreshes every 10 seconds", and the percent of steps done in an accent-colored chip.
  - The stale banner, directly under the top bar, hidden unless the script shows it.
  - Overview: four summary figures in a row (two across below 1200px, one below 420px): steps done as a fraction with the percent, in progress, stuck, and open questions. Each has a short line under it in green when all is well and red when something needs me. Under them, a Progress card with a meter in the accent color and the summary from state.json, which becomes the final summary when the task is done.
  - Steps: a table of number, step, status, and the time each status was set, with the step in progress highlighted.
  - Questions for you: a table of question, the default you will take if I do not answer, and whether it is open or answered by default.
  - Stuck: a table of what is blocked and what it is waiting for.
  - Live status, where the project has one (see Sources).
  - Latest results: a table of file and what changed, with paths relative to the project root.
  - Latest release, and the full Roadmap, where the project has them.
  - Footer: one line saying this is a generated working page, how to regenerate it, the generation time, that it is not indexed, and that a published copy shows the state as of the last publish.
  - A section with nothing in it shows a short empty state ("Nothing is blocked.") rather than disappearing, so the layout never shifts.
  - Every status is a pill that carries a word as well as a color (Done, In progress, Waiting, Not started, Proposed, Deferred), never color alone. Tables sit in their own scrolling box, so a wide table never widens the page. Figures use tabular numbers, and panels share one border, radius, and background.
- Where the project already has its own page layout (site chrome such as a header, navigation, and footer), you may render the dashboard inside it instead of the sidebar layout. Every section above is still required, including Questions and Stuck with their empty states, and so are the times and the stale banner.

One status page
- Where the project already has a page reporting live status, fold it into the dashboard as a section, generated from the same sources, and turn the old page into a redirect to that section (such as dashboard/index.html#status), so existing links still work. Tell me which pages you folded in.
- Docs that need a fast-changing number link to the dashboard instead, or give the number with an as-of date. Never copy a live number into a doc without one.

Privacy and publishing
- The dashboard, its state file, and its generator are part of the project, tracked like any other file, never added to an ignore file, and published wherever the project is published. Where the project's docs describe its folder structure, list dashboard/ there as a project folder that is never merged into the docs.
- On a static site the page is served at /dashboard/; otherwise anyone who can see the repository can read it and its state file. Put nothing in either that you would not publish: no secrets, keys, personal details, private paths, or private matters. Keep a question that involves any of those in the conversation, and put only a neutral line in state.json.
- Include <meta name="robots" content="noindex">, since it is a working page rather than content.
- If dashboard/ already exists for something else, use progress-dashboard/ instead and tell me.

Working
- Create state.json and the generator before starting the task, run the generator, and tell me the page's path, and its public address if the project is published somewhere you can name.
- After every step, and whenever something gets stuck or a question comes up, update state.json and run the generator (or the build that runs it).
- When you need a decision, add it to Questions in state.json with your default, and keep working on anything that does not depend on it. When you reach work that does, take the default, mark the question answered by default, and regenerate.
- When the task is finished, mark every step done, write the final summary into state.json, and regenerate.
- Where the task ends with the project being published, regenerate before it is published, so the finished page goes live with everything else. Never make publishing, or confirming that something is live, a step on the page: it can never be marked done in the copy that goes live. Report those in the conversation instead.

Verify
After writing or changing the generator:
- Run it twice in a row. The second run must produce the same page, ignoring the generation time, and must not rewrite the file.
- Run the project's link or orphan check, if it has one.
- Load the page at 390px wide in a headless browser and confirm it has no horizontal overflow (its scrollWidth equals its clientWidth). A headless window may refuse to go that narrow; if so, load the page in a 390px-wide frame and measure that.
- Change one source (a step's status in state.json), regenerate, and confirm the page shows it.
Report what passed, and anything you could not check.

Afterwards
Ask whether I want this as a standing rule. If I do, show me the exact lines for the project's CLAUDE.md, and write them once I confirm: for any task with more than 5 steps, or likely to take longer than 30 minutes, keep dashboard/state.json and regenerate dashboard/index.html with the project's dashboard generator after every step, as described here, using the recorded style; never edit the page by hand; nothing private goes in either file. Where the project keeps a PRD with a working-practice section, record the rule there too. A rule that is already in CLAUDE.md stays as it is; a later documentation pass leaves it alone.
```
