Build turns a GitHub account into an engineering dashboard: 30-day contribution signal, PR and issue flow health, repository momentum and risk, and release cadence.
| Route | Charts and panels |
|---|---|
/ |
30-day contribution trend · language share · pinned and recently shipped repositories |
/activity |
30-day contribution heatmap with weekly totals and streaks · PR cycle time (median open-to-merge hours) · PR flow health (merge and reopen rates) · issue flow health (opened vs closed, net backlog) · commit timing heatmap (weekday × hour, timezone-aware) · PR throughput · daily breakdown |
/repos |
pinned vs non-pinned momentum · weekly commit cadence · repository risk panel (hot / active / stale / dormant) · browsable repository inventory |
/featured |
featured relevance score breakdown (pinned boost + stars + recency + 30-day commits) · monthly release cadence · featured project cards |
Every chart is a Recharts component fed by server-side data shaping in lib/github.ts. Data comes from the GitHub REST and GraphQL APIs, fetched in server components and cached with a five-minute revalidation window plus an on-demand revalidation endpoint. It is not real-time: there are no WebSockets or streaming updates.
| Technology | Purpose |
|---|---|
| Next.js 16 (App Router) | React 19 server components, "use cache" route caching |
| TypeScript | Type safety throughout |
| Recharts | Charts, with a theme-aware palette from CSS variables |
| Tailwind CSS v4 | Utility-first styling |
| GSAP | Headline and scroll-reveal motion (respects reduced motion) |
| GitHub REST + GraphQL API | Repositories, pinned items, commits, PRs, issues, releases |
| Lucide React | Icon library |
| Vitest | Unit and smoke tests |
Dark and light mode use a small custom theme provider (cookie plus localStorage, system-aware) rather than a library.
- Node.js v20.9+ (CI runs on 24)
- npm or compatible package manager
- A GitHub token (fine-grained with repository read access is preferred; classic with
public_repoalso works)
git clone https://github.com/brandonperfetti/github-commit-dashboard.git
cd github-commit-dashboard
npm installCreate a .env.local file in the project root:
GITHUB_TOKEN=your_github_personal_access_token
NEXT_PUBLIC_SITE_URL=http://localhost:3000
REVALIDATE_SECRET=replace_with_a_long_random_secretNote: The
GITHUB_TOKENis used server-side only and is never exposed to the client. Note:NEXT_PUBLIC_SITE_URLis required for production builds and metadata URLs. Note:REVALIDATE_SECRETsecures on-demand cache invalidation (POST /api/revalidate). Note: The dashboard's GitHub username is theUSERNAMEconstant inlib/github.ts; change it there to point the dashboard at another account.
npm run devOpen http://localhost:3000 to view the dashboard.
This dashboard can run against anonymous GitHub API limits, but you will hit 403 rate limits more often during local development.
Add a token in .env.local:
GITHUB_TOKEN=github_pat_...
ALLOWED_DEV_ORIGINS=192.168.1.156Notes:
- Keep it server-side only (do not prefix with
NEXT_PUBLIC_). ALLOWED_DEV_ORIGINSaccepts a comma-separated list for local device testing (for example,192.168.1.156,192.168.1.200).- Fine-grained token with read access to repositories is preferred.
- With a token present, the app uses authenticated
/user/reposcalls and can include private repositories you can access, and it reads your pinned repositories over GraphQL. - Without a token, it falls back to public
/users/{username}/reposand skips pinned repositories.
npm testThe suite runs on Vitest with no network access: every GitHub request goes through a fetch router in tests/helpers, and any unrouted request fails the test. It covers the data shaping behind the charts (streaks, calendar weeks, weekly and monthly windows, cycle-time medians, merge rates, timezone bucketing, risk buckets), the GitHub client's pagination and fallbacks, the URL and timezone helpers, and a smoke render of the home route from stubbed API responses, including the case where every upstream call fails. npm run test:watch keeps it running while you work.
npm run build
npm run startnpm run validate:env -- --mode=productionThis checks required production variables (currently NEXT_PUBLIC_SITE_URL) and fails fast when missing or malformed.
Trigger targeted cache invalidation (by tag and/or path):
curl -X POST http://localhost:3000/api/revalidate \
-H "Content-Type: application/json" \
-H "x-revalidate-secret: $REVALIDATE_SECRET" \
-d '{
"tags": ["route:activity", "github:commit-timing"],
"paths": ["/activity"]
}'Supported payload fields:
tags: cache tags set viacacheTag(...)paths: route paths forrevalidatePath(...)
Security notes:
- The endpoint requires
REVALIDATE_SECRET. - Secret can be passed via
x-revalidate-secretorAuthorization: Bearer .... - Tags must match
^[a-z0-9:_-]{2,64}$; paths must begin with/.
Use the Revalidate Cache workflow (.github/workflows/revalidate-cache.yml) to trigger invalidation from the Actions UI:
- Open Actions → Revalidate Cache → Run workflow
- Select
PrevieworProduction - Optionally override
base_url - Provide comma-separated
tags_csvandpaths_csv
The workflow calls POST /api/revalidate with REVALIDATE_SECRET.
The Warm Route Cache workflow (.github/workflows/warm-route-cache.yml) runs every 15 minutes and pings key routes (/, /activity, /repos, /featured) to reduce cold-cache first-load latency.
You can also run it manually from Actions and override:
target_environment(PrevieworProduction)base_urlroutes_csv
npm run lintCI(.github/workflows/ci.yml) runs lint, the Prettier check, and the test suite on every pull request and on pushes tomainanddevelop.Env Guard(.github/workflows/env-guard.yml) validates the production environment variables.
github-commit-dashboard/
├── app/
│ ├── activity/ # Contribution, PR/issue flow, and commit timing page
│ ├── api/
│ │ ├── activity/ # Commit timing heatmap endpoint (timezone query)
│ │ └── revalidate/ # Secret-guarded on-demand cache invalidation
│ ├── components/
│ │ ├── charts/ # Recharts components + theme-aware color hook
│ │ ├── motion/ # GSAP headline and scroll-reveal wrappers
│ │ └── ui/ # Badge, button, card primitives
│ ├── featured/ # Featured repositories page
│ ├── repos/ # Repository browser page
│ ├── layout.tsx # Root layout with theme provider
│ └── page.tsx # Dashboard home
├── lib/
│ ├── github.ts # GitHub API client and all chart data shaping
│ ├── site-config.ts # Public site URL resolution
│ ├── timezone.ts # IANA timezone validation
│ └── url.ts # Safe http(s) URL normalisation
├── tests/ # Vitest suite (fetch-stubbed, no network)
└── public/ # Static assets
This project is optimized for deployment on Vercel. Add GITHUB_TOKEN, NEXT_PUBLIC_SITE_URL, and REVALIDATE_SECRET as environment variables in the Vercel project settings.
MIT © Brandon Perfetti
