A self-updating, zero-dependency dashboard for triaging a GitHub repo's open issues. It classifies every open issue on four dimensions —
PR status × area × type × support tier
— and renders an interactive, filterable dashboard. A GitHub Action rebuilds the data on a schedule and publishes the static site to GitHub Pages, so the dashboard stays live with no server to run.
Built for the PHP internals team (ships with a php/php-src config) but works
for any repository by editing one config file.
- Pure PHP 8.5+, no Composer, no extensions beyond core (uses PHP's stream
transport for HTTPS — no
ext-curl). Clone it and run; nothing to install. - Deterministic classification — no AI, no network at classify time. Areas
and types come from labels; support tier is computed from the reported PHP
version against a schedule and today's date (so tiers age on their own).
Anything that can't be classified from the data lands in an explicit
unclassified/unknownbucket that is shown, never hidden or guessed. - Static output. The pipeline writes
site/data.json; the pagefetch()es it. No backend, no client-side API calls, no rate-limit surprises for viewers.
- Fork this repo.
- In Settings → Pages, set Source to GitHub Actions.
- (Optional) add a
DASHBOARD_TOKENsecret (a PAT) for higher rate limits or a private target repo — otherwise the workflow's built-in token is used. - Run the Refresh & Deploy workflow (Actions tab → Run workflow), or wait for the 6-hourly schedule. Your dashboard is published to your Pages URL.
# 1. build the dataset (a token is optional but avoids the 60 req/hr limit)
GITHUB_TOKEN=$(gh auth token) php bin/build.php --config=config/php-src.php
# 2. serve the static site (fetch() needs HTTP, not file://)
php -S localhost:8000 -t site
# open http://localhost:8000
# 3. run the tests
php tests/run.phpRequires PHP 8.5+ with allow_url_fopen on and the openssl extension
(both are on by default in a normal build).
Copy config/php-src.php, edit it, and pass --config=config/your-repo.php
(and set the same path in .github/workflows/refresh.yml). The four dimensions
are fixed; the config just maps your repo's labels and versions onto them:
- area — label prefixes (e.g.
Extension:,Component:). - type — label → type map (e.g.
Bug→bug). - support tier — a per-version schedule of active/security-until dates, plus a regex to read the version out of the issue body. Omit this and every issue is simply untiered.
- pr linkage — which repo's PRs count, and optional deterministic backlink
recovery from PR text (
Fixes GH-1234).
See config/schema.md for the full contract.
config/*.php one file per target repo (the only repo-specific surface)
src/ GitHubClient · Fetcher · Classifier · Builder · Validator
bin/build.php fetch → classify → validate → write site/data.json
site/ index.html + app.js (vanilla) that fetch data.json
tests/run.php zero-dependency test runner
.github/ ci.yml (lint + tests) · refresh.yml (schedule → Pages)
Validator refuses to write output that is empty or malformed, so a failed or
throttled fetch never overwrites a good dashboard.
MIT.