Architecture Overview
gh-org-tool is a single deployable unit — a Next.js application with no separate backend service. All business logic, API surface, and frontend rendering live in one codebase. The entire system runs on Vercel.
System layers
Technology stack
| Layer | Technology | Version |
|---|---|---|
| Framework | Next.js | 16.2.6 |
| React | React | 19.2.0 |
| Language | TypeScript | — |
| Package manager | pnpm | 10.33.1 |
| Dev bundler | Turbopack | — |
| CSS | Tailwind CSS | 4 |
| Component library | shadcn/ui (new-york style) | — |
| Server state | TanStack Query | — |
| Client state | Zustand (5 stores) | — |
| Database | Supabase (Postgres) | — |
| Cache | Upstash Redis (optional) | — |
| Auth | GitHub App OAuth + App installations | — |
| Deployment | Vercel | — |
| Tests | Vitest + v8 coverage | — |
| Docs | Nextra v4 | — |
Directory structure
app/ Next.js App Router pages and API routes
api/ All backend logic (route handlers)
auth/ OAuth callback, session management
github/ GraphQL proxy, org endpoints
install/ Installation webhook and management
leaderboard/ Leaderboard read endpoints
mass-invite/ Bulk invitation endpoint
scoring/ Scoring preset management
debug/ Debug routes (gated by ENABLE_DEBUG_ROUTES)
lib/
auth/ Session handling, token encryption, guards
github/ Octokit wrappers, GraphQL client
leaderboard/ Ingest pipeline, query logic, caching
scoring/ Score computation engine
supabase/ Repository pattern over Supabase tables
cache/ Redis client (redis.ts)
env/ Env var validation (index.ts)
types/ Shared TypeScript types (db/, api/, scoring/, auth/)
stores/ Zustand stores
hooks/ TanStack Query hooks
content/ Nextra documentation source (this site)
supabase/migrations/ 11 SQL migration filesDesign decisions
Single deployable unit
There is no separate API server, worker process, or microservice. Every endpoint is a Next.js route handler. Background jobs (ingest, score computation) run as long-lived route handler calls from the frontend. This simplifies deployment to zero-config Vercel push, at the cost of being tied to Vercel’s function execution model.
Two GitHub auth modes
The application operates with two different GitHub credentials depending on the operation:
- User OAuth token — obtained during sign-in; used for the GraphQL proxy and listing orgs. Scoped to what the signed-in user can see.
- Installation token (
getInstallationOctokit) — obtained by the GitHub App on behalf of its installation on an org. Used for leaderboard ingest and mass-invite. Scoped to what the GitHub App installation was granted access to.
This is intentional: ingestion should not be limited to what any individual user can see.
Repository pattern for data access
All database access goes through typed repositories in lib/supabase/. Route handlers never construct raw Supabase queries directly. This keeps query logic testable and co-located with the schema types in types/db/.
TanStack Query configuration
The frontend uses TanStack Query with staleTime: 30000 (30 seconds) and refetchOnWindowFocus: false. This means data is considered fresh for 30 seconds and will not re-fetch when the user switches back to the tab. Explicit refetch is triggered by user actions (e.g. manual sync button).
Five Zustand stores
| Store | File | Responsibility |
|---|---|---|
auth-store | stores/auth-store.ts | Current auth session state |
workspace-store | stores/workspace-store.ts | Active org / installation context |
leaderboard-store | stores/leaderboard-store.ts | Leaderboard UI state |
url-params-store | stores/url-params-store.ts | URL-reflected filter parameters |
analytics-store | stores/analytics-store.ts | Analytics panel state |
No infrastructure-as-code
There is no Docker, Kubernetes, docker-compose, Terraform, or vercel.json. Deployment is a direct git push to the Vercel-connected repository. Environment variables are managed through the Vercel dashboard.