SEO-friendly analytics dashboard for Linear sprints/cycles — velocity, burn-down, cycle time / lead time, WIP, scope creep, risk signals, and actionable recommendations.
Fully data-driven — all names, projects and labels are fetched dynamically from the Linear API. No hardcoding.
If you manage delivery in Linear and want a lightweight, no-build, browser-run dashboard for sprint analytics and engineering metrics, this repo gives you a single-page dashboard that pulls data from the Linear GraphQL API and renders KPIs + charts.
Typical use cases:
- Engineering managers / PMs: sprint health, scope creep, WIP overload, overdue work
- Teams: velocity trend, burn-down reality check, stale work discovery
- Ops/Enablement: consistent KPI definitions across squads
| Block | Metrics |
|---|---|
| Executive Summary | Progress bar, burn-down prediction, days early/late |
| KPI Cards | Velocity (vs historical), Lead Time, WIP, Scope Creep |
| Burn-down Chart | Ideal vs. Actual remaining work (Chart.js) |
| Team Grid | Load %, WIP count, Avg Cycle Time, Overdue, Labels |
| Risk Assessment | Priority inflation, Tech debt, Unassigned, WIP overload |
| Recommendations | ≥3 auto-generated actionable insights per sprint |
- 🔄 Grouping: By Assignee / By Project / By Label
- ⚖️ Estimation mode: Issue Count or Story Points
- ⏰ Stale threshold: configurable (default 72h)
- 🎯 Priority filter: All / High+ / Urgent only
- 🔄 Cycle selector: switch between all active cycles
- Vanilla HTML + CSS + ES Modules
- Chart.js (CDN) for charts
- Linear GraphQL API for data
- Playwright for tests (dev dependency)
⚠️ The dashboard uses ES Modules — must be served over HTTP, not opened asfile://directly.
cd linear-dashboard
python -m http.server 8080
# Open http://localhost:8080npx serve linear-dashboard -p 8080
# Open http://localhost:8080Install Live Server extension → right-click index.html → Open with Live Server
- Go to Linear Settings → API
- Generate a Personal Access Token
- Paste it into the dashboard setup screen
- Token is saved in
localStorage— enter once per browser
linear-dashboard/
├── index.html # Main SPA entry point
├── styles/
│ └── main.css # Dark glassmorphism design system
└── js/
├── linear-api.js # GraphQL API client with caching
├── metrics.js # KPI calculation engine
├── settings.js # User preferences (localStorage)
└── dashboard.js # UI controller & rendering
linear-api.js ──→ Parallel GraphQL queries (Promise.all)
│
metrics.js ──→ Pure calculation functions (stateless)
│
settings.js ──→ User config (EventTarget, localStorage)
│
dashboard.js ──→ DOM rendering & event orchestration
- No build step — vanilla ES Modules, zero dependencies except Chart.js (CDN)
- In-memory cache — 5-minute TTL per query, cleared on Refresh
- Parallel fetching —
Promise.all([getCycleIssues, getPreviousCycles])for <5s load - XSS protection — all user-data rendered through
esc()sanitizer
| Metric | Definition |
|---|---|
| Velocity | Completed weight / elapsed days. Compared to avg of last 3 sprints |
| Lead Time | Time from first started transition → completed (avg, median, p90) |
| WIP | Issues currently in started state, grouped by assignee |
| Scope Creep | Issues created after cycle.startsAt |
| Burn-down | Ideal linear line vs. actual remaining work per day |
All settings persist in localStorage:
| Key | Default | Description |
|---|---|---|
linear_dashboard_token |
— | Linear Personal Access Token |
linear_dashboard_estimation |
count |
count or points |
linear_dashboard_stale_hours |
72 |
Hours before issue is "stale" |
linear_dashboard_grouping |
assignees |
Grid grouping mode |
linear_dashboard_priority_filter |
all |
Priority filter |
- Token stored in
localStorage(client-side only, never sent anywhere except Linear API) - All rendered strings pass through HTML entity sanitizer
- No eval, no inline scripts
- Before pushing to the repo: do not commit
settings.json(it contains tokens). Usesettings.json.exampleas a template: copy it tosettings.jsonand fill in your keys.settings.jsonis listed in.gitignore.
| Requirement | Status |
|---|---|
| Dynamic data discovery (cycle, assignees, labels) | ✅ |
| Velocity with historical comparison (3 cycles) | ✅ |
| Lead Time (avg, median, p90) | ✅ |
| WIP per assignee | ✅ |
| Scope Creep detection | ✅ |
| Count / Story Points modes | ✅ |
| Grouping (Assignees / Projects / Labels) | ✅ |
| Configurable Stale Threshold | ✅ |
| Priority filter | ✅ |
| Executive Summary with Burn-down | ✅ |
| Team Grid (Name, Load, WIP, Cycle Time, Blockers) | ✅ |
| Risk Assessment (Priority inflation, Tech Debt, Unassigned) | ✅ |
| ≥3 Automatic recommendations | ✅ |
| Load time < 5 seconds | ✅ (parallel fetch + cache) |