A GitHub activity tracker for small project teams. Tracks pull requests, commits, and reviews across your team's repositories, and surfaces cycle time, throughput, and review-turnaround metrics — plus an optional weekly email digest.
- Track any GitHub repo by URL; auto-syncs every 15 minutes (or trigger a manual sync)
- Pull request, commit, and review history synced via the GitHub API
- Metrics: cycle time, PR throughput, commit activity, time-to-first-review, and reviewer activity — per repo or across all tracked repos
- Weekly digest email, grouped by repository
- Optional shared access code for small-team deployments
- Backend: Express, TypeScript, Prisma + PostgreSQL, Redis (caching), Octokit, node-cron, Resend (email)
- Frontend: Next.js (App Router), Tailwind, Recharts
Prerequisites: Node.js, a running PostgreSQL instance, and a running Redis instance.
npm install
cp .env.example .env # fill in the values below
npx prisma migrate deploy
npm run dev # http://localhost:3000Required env vars (see .env.example):
| Variable | Purpose |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
GITHUB_TOKEN |
Personal access token, raises GitHub API rate limits |
REDIS_URL |
Redis connection string for metrics caching |
FRONTEND_URL |
Frontend origin, for CORS |
Optional:
| Variable | Purpose |
|---|---|
RESEND_API_KEY, DIGEST_FROM_EMAIL, DIGEST_RECIPIENT_EMAIL |
Weekly digest email. All three required, otherwise sending is skipped. |
APP_ACCESS_TOKEN |
Shared access code required on every API request (sent as x-access-token). Leave blank to disable auth — fine for local/solo use, but set this before sharing a deployment with a team. |
SENTRY_DSN |
Error monitoring via Sentry. Leave blank to disable — errors still log to the console either way. |
cd frontend
npm install
echo 'NEXT_PUBLIC_API_URL="http://localhost:3000"' > .env.local
npm run dev # http://localhost:3001- Run
npx prisma migrate deploy(notmigrate dev) against your production database. - Set
APP_ACCESS_TOKENto a random string if the deployment will be reachable by more than just you. - Build each side with
npm run build, thennpm start.
A Dockerfile is provided for both the backend (repo root) and frontend (frontend/Dockerfile), plus a docker-compose.yml that also runs Postgres and Redis for a self-contained deployment.
cp .env.example .env # fill in GITHUB_TOKEN, APP_ACCESS_TOKEN, etc.
docker compose up -d --buildBefore the backend can serve requests, run migrations once against the compose Postgres instance (published on localhost:5432):
DATABASE_URL=postgresql://repotracker:repotracker@localhost:5432/repotracker npx prisma migrate deployThe frontend image bakes NEXT_PUBLIC_API_URL in at build time (it's a client-side env var) — set it via the NEXT_PUBLIC_API_URL shell variable before docker compose up --build if the backend isn't reachable at http://localhost:3000.
This runs the whole stack — Postgres, Redis, backend, frontend — on a machine you already own, with no cloud spend and no ports exposed to the public internet.
-
Install Docker, if it isn't already there:
curl -fsSL https://get.docker.com | sh sudo systemctl enable --now docker
(On a NAS like Synology/QNAP, use its own Docker/Container Manager app instead.)
-
Get the code onto the box (
git clone, or copy the repo over) and configure it:cp .env.example .env # fill in GITHUB_TOKEN, APP_ACCESS_TOKEN, etc. -
Install Tailscale on the server and on every device you want to access it from (phone, laptop) — tailscale.com/download:
curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale upNote the server's Tailscale hostname/IP (
tailscale ip, or the admin console) — call it<ts-host>below. -
Point the frontend at the backend over Tailscale, then build and start everything:
NEXT_PUBLIC_API_URL=http://<ts-host>:3000 FRONTEND_URL=http://<ts-host>:3001 docker compose up -d --build
-
Run migrations once, from the host itself:
DATABASE_URL=postgresql://repotracker:repotracker@localhost:5432/repotracker npx prisma migrate deploy
-
Every service in
docker-compose.ymlhasrestart: unless-stopped, so as long as Docker starts on boot (step 1 already enabled that), everything comes back automatically after a reboot or power loss.
From any device signed into the same Tailscale account, open http://<ts-host>:3001 — no port forwarding, no domain, no TLS setup, and traffic is already encrypted over Tailscale's WireGuard tunnel. APP_ACCESS_TOKEN is optional in this setup since Tailscale itself gates who can reach the machine at all, but it's still worth setting if you ever add other people to your tailnet.
.github/workflows/ci.yml runs on every push to main and every PR: type-checks, builds, and tests the backend, and lints and builds the frontend.
npm test # runs the backend Vitest suite once
npm run test:watchFrontend has no test suite yet; cd frontend && npm run lint is the closest available check.