The Problem
When you're working across multiple active repositories, it's easy to lose the thread. A hotfix lands on main at midnight, a large batch of commits from a collaborator changes something you rely on, or a repo quietly goes stale. Email notifications drown in noise. Checking each repo individually doesn't scale. There was no tool that gave me one opinionated view of what actually mattered across my entire GitHub account.
What ShipWatch Live Does
ShipWatch Live is a real-time monitoring dashboard that installs as a GitHub App, receives signed webhook events from every connected repository, and surfaces the activity that deserves attention. The distinguishing feature is the AI review pipeline: any commit in the feed can be sent to Claude for a full code review, and any problem Claude identifies can be fixed with a single button click that commits the corrected code directly back to the repository.
Key Features
Architecture
The full pipeline from installation to auto-fix:
GitHub App Install → OAuth Callback → Supabase upsert → webhook registration → HMAC-verified event → database write → server-rendered dashboard → AI review → one-click commit
GitHub App Authentication
ShipWatch Live authenticates as a GitHub App using RS256-signed JWTs, not a user OAuth token. On installation, the callback route receives the installation ID, generates an installation access token scoped to that install, and upserts a record in the `github_installations` table in Supabase. All subsequent API calls on behalf of a repository use that installation token rather than user credentials.
Webhook Pipeline
GitHub delivers signed `push`, `installation`, `installation_repositories`, and `ping` events to `/api/github/webhook`. The handler computes the expected HMAC-SHA256 digest using the shared webhook secret and rejects any payload where the signature does not match. Verified push payloads are written to the `webhook_events` table with the installation ID, event type, repository name, branch, commit count, and the full payload stored as `jsonb` for flexible querying.
AI Review — `/api/review-commit`
When the Review button fires, the route handler:
1. Fetches the commit diff from GitHub using the installation token
2. Parses changed files, sorts them by lines changed (descending), and fetches the full content of up to 15 files
3. Sends the diff and file contents to an n8n webhook endpoint
4. n8n passes the payload to Claude with a structured review prompt
5. The response is normalized across multiple possible envelope shapes and returned as a typed analysis object
The modal renders the result as a collapsible review with severity indicators and per-issue suggestions.
One-Click Auto-Fix — `/api/apply-fix`
When a Fix button fires on a specific suggestion:
1. Fetches the current file content and its blob SHA from GitHub
2. Sends the file content, the suggested fix description, and context to a separate n8n AI fix workflow
3. n8n asks Claude to produce corrected file content
4. The corrected content is base64-encoded and committed back via a PUT to the GitHub Contents API using the blob SHA as the update guard
5. The dashboard reflects the fix without a page reload
Middleware — `proxy.ts`
A Next.js middleware layer runs on every request. It refreshes the Supabase session cookie from the request headers, protects all `/dashboard` routes by redirecting unauthenticated users to the login page, and explicitly allows `/api/github/webhook` through without an auth check — since GitHub's webhook delivery cannot carry a session cookie.
Database Schema
Two Supabase tables underpin the app:
Row Level Security is enabled on both tables so users only see data tied to their own GitHub App installation.
Dashboard
The dashboard page is a Next.js server component. On each request it queries Supabase for recent webhook events and the user's installations, computes alerts inline (no background job), and renders the activity feed and stats bar server-side. No client-side polling. The activity feed component is a client component responsible for the Review/Fix button interactions and AI modal state.
What I Learned
The GitHub App authentication model is meaningfully different from plain OAuth and requires more care. JWT generation with RS256, installation token scoping, and the distinction between user-granted access and installation-granted access all took deliberate study. The AI pipeline end-to-end — fetching context, routing through n8n, normalizing Claude's response shape, and committing corrected code back via the Contents API — turned out to be the most architecturally interesting part of the project. It forced me to think carefully about error states at each step: what happens if the diff is too large, if n8n times out, if the blob SHA is stale by the time the fix commit fires.