The big picture
GitHub Org Tools is a full-stack Next.js 16 application deployed on Vercel. It talks to GitHub through GraphQL (mostly) and REST (when it has to). Supabase handles persistent storage — sessions, installation metadata, leaderboard data, and caches.
There’s no separate backend server. The API routes in app/api/ are the backend. They handle auth, proxy GraphQL calls, manage installations, and run the leaderboard pipeline.
Architecture layers
┌─────────────────────────────────────────────────────────────┐
│ Frontend │
│ React 19 + Tailwind CSS 4 + shadcn/ui + TanStack Query │
│ Zustand stores (auth, workspace, leaderboard, analytics) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Next.js API Routes │
│ Auth (/api/auth/*) Install (/api/install/*) │
│ Organizations (/api/organizations/*) │
│ GraphQL proxy (/api/github/graphql) │
│ Leaderboard (/api/[org]/leaderboard/*) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Service Layer │
│ Auth services (crypto, oauth, session, user, installation) │
│ GitHub client factory (singleton App + memoized Octokit) │
│ GraphQL proxy (typed allowlist, fallback queries) │
│ Scoring engine (rules, aggregation, normalization) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Data Layer │
│ Supabase repositories (installation, user, org, team) │
│ Leaderboard DB (scoring rules, snapshots, cache) │
│ Shared axios client (interceptors, error handling) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ External APIs │
│ GitHub GraphQL API (primary) │
│ GitHub REST API (fallback for webhooks, invites) │
│ Supabase Postgres (sessions, cache, leaderboard) │
└─────────────────────────────────────────────────────────────┘Key design decisions
These are the choices that shaped how the system works. Understanding them will help you navigate the code and make informed changes.
1. Normalized database schema
User and organization data lives in users and organizations tables — not embedded as JSONB inside auth_sessions. This means you can query organizations independently of any session, membership lookups are efficient (indexed foreign keys), and referential integrity is enforced at the database level.
2. Token encryption at rest
GitHub OAuth tokens are encrypted with AES-256-GCM before they hit the database. The key comes from TOKEN_ENCRYPTION_KEY (or a fallback). Tokens are decrypted in memory only when a session is read. The plaintext token never touches the database, never appears in logs, and never reaches the client.
3. Supabase as a cache layer
Installation metadata, team memberships, and repository data live in Supabase with a stale-while-revalidate strategy. The default TTL is one hour. Webhook events (installations, repository changes) trigger immediate cache updates, so the data is usually fresh without hammering the GitHub API.
4. GraphQL-first architecture
Almost all GitHub data fetching goes through GraphQL via /api/github/graphql. The proxy enforces a typed allowlist of operations — the client can only run queries that the server explicitly permits. REST is reserved for things GitHub’s GraphQL API doesn’t support (like org invitations and webhook handling).
5. Server-side auth only
No JWTs in localStorage. No tokens exposed to the browser. Sessions are identified by opaque random IDs in httpOnly cookies. Every API route validates the session server-side. The client never sees the OAuth token — not even on the sign-in callback.
Data flow: sign in
User clicks "Sign in"
↓
GET /api/auth/start
→ Creates state JWT + CSRF cookie
→ Redirects to GitHub
↓
GitHub authorization
↓
GET /api/auth (callback)
→ Verifies state + CSRF
→ Exchanges code for token
→ Encrypts token (AES-256-GCM)
→ Fetches viewer profile + orgs
→ Upserts user, orgs, memberships
→ Creates session in auth_sessions
→ Sets gh_session cookie
→ Redirects to returnTo
↓
Frontend reads session
→ GET /api/auth/session
→ Decrypts token server-side
→ Returns SessionView (no token)
→ Zustand store updatedDetailed walkthrough: Authentication
Data flow: leaderboard computation
User requests leaderboard
↓
GET /api/[org]/leaderboard/repository
→ Resolves installation ID
→ Creates installation-scoped Octokit
→ Resolves repos for scope (org/repo/team)
→ Fetches commits, PRs, reviews via GraphQL
→ Normalizes to Signal[]
→ Applies scoring rules (engine.ts)
→ Aggregates by entity type
→ Writes computed_scores + leaderboard_materializations
→ Caches result in Redis (if configured)
→ Returns response
↓
Frontend displays
→ TanStack Query dedup + stale-while-revalidate
→ Background refresh via request-cache.ts LRUDetailed walkthrough: Scoring Overview
File organization
app/
api/ # API routes (the backend)
[organization]/ # Authenticated org pages
components/
auth/ # Auth components
layout/ # Header, footer, shell
leaderboards/ # Leaderboard UI
organization/ # Org management UI
ui/ # shadcn/ui components
hooks/
queries/ # TanStack Query hooks
mutations/ # TanStack Query mutations
lib/
auth/ # Auth system
github/ # GitHub client, GraphQL proxy, data fetching
leaderboard/ # Leaderboard pipeline orchestration
scoring/ # Scoring engine, rules, normalization
supabase/ # DB repositories
api/ # Shared axios client
env/ # Zod-validated env access
stores/ # Zustand stores
types/ # TypeScript types
content/ # Nextra docs (MDX)
supabase/migrations/ # SQL schema filesTechnology stack
| Layer | What we use |
|---|---|
| Framework | Next.js 16 (App Router) |
| UI | React 19, Tailwind CSS 4, shadcn/ui |
| State management | TanStack Query, Zustand |
| Auth | GitHub App OAuth, AES-256-GCM encryption |
| Database | Supabase (PostgreSQL) |
| API | GraphQL (primary), REST (fallback) |
| Deployment | Vercel |
| Docs | Nextra v4 |
Related
- Authentication — how auth flows work in detail
- Database Schema — complete table reference
- API Overview — all API endpoints
- Scoring Overview — the leaderboard pipeline