Top-Level Layout
/
├── app/ # Next.js App Router
├── components/ # React components
├── content/ # Nextra MDX documentation (served at /docs)
├── hooks/ # TanStack Query hooks + utility hooks
├── lib/ # All business logic, no React
├── public/ # Static assets
├── stores/ # Zustand state stores
├── supabase/ # Database migrations
├── types/ # TypeScript types
└── example.env # Template for .env.localPath alias: @/ maps to the project root (tsconfig.json → paths: { '@/*': ['./*'] }).
app/
Next.js App Router. Each subdirectory is a route segment.
app/
├── [organization]/ Org-scoped pages (guarded by ProtectedRoute)
│ ├── layout.tsx Server Component — passes org slug to OrganizationLayoutClient
│ ├── page.tsx Server Component — redirects → /{org}/organization
│ ├── organization/
│ │ ├── page.tsx OrganizationOverview (FeaturePlaceholder stub)
│ │ ├── team-management/ TeamManagement (bulk add users to a team)
│ │ ├── role-management/ BulkRoleManagement (bulk member/admin change)
│ │ └── mass-invite/ MassInvite (user search + JSON + CSV/XLSX import)
│ ├── leaderboards/
│ │ ├── layout.tsx Adds RecomputeButton FAB (dev-only, null in prod)
│ │ ├── loading.tsx Loading state
│ │ ├── page.tsx ContributorLeaderboard
│ │ ├── r/
│ │ │ ├── page.tsx RepositoryLeaderboard (repo from ?repository= param)
│ │ │ └── [repository]/ RepositoryLeaderboard (repo from path param)
│ │ ├── team/ TeamLeaderboard (list + drilldown via ?team=)
│ │ └── scoring/ ScoringRules (full preset CRUD + JSON import/export)
│ └── analytics/
│ ├── page.tsx OrganizationAnalytics (stats + trend + top contributors)
│ ├── contributor/ ContributorProfileView (cmdk combobox + timeline)
│ ├── repository/ RepositoryAnalytics (repo selector + trend + top contributors)
│ ├── heatmap/ ContributionHeatmap (pure CSS grid, 365-day)
│ └── timeline/ ActivityTimeline (bespoke zigzag layout)
├── account/
│ └── page.tsx Account page — session info, installations, logout
├── api/
│ ├── auth/ OAuth: start (GET), callback (GET), session (GET), logout (POST)
│ ├── install/ App install: start, callback, complete, status, webhook
│ ├── organizations/ Lists, detail, mass-invite, bulk-role, teams/bulk-add
│ ├── github/graphql/ Allowlisted GraphQL proxy (POST)
│ ├── [organization]/ 18 org-scoped routes (leaderboard, analytics, repository, contributor, etc.)
│ └── debug/ Debug routes (gated by ENABLE_DEBUG_ROUTES)
├── docs/ Nextra docs rendering
│ ├── layout.tsx Docs layout (Nextra Layout + navbar + footer)
│ └── [[...mdxPath]]/ Catch-all page renderer for MDX files in content/
├── error.tsx Global error boundary
├── layout.tsx Root layout — QueryProvider + header + footer + Toaster
├── loading.tsx Root loading state
├── not-found.tsx 404 page
└── page.tsx Marketing homepagecomponents/
components/
├── auth/ ProtectedRoute, AuthErrorBanner; AuthConsole (orphaned — not used)
├── layout/ Header, HeaderWrapper, FooterWrapper, Sidebar, OrganizationLayoutClient, HomepageCTAs
├── organization/ MassInvite, TeamManagement, BulkRoleManagement, InstallationAccessBanner, UserSearchPanel, FeaturePlaceholder
├── leaderboards/ ContributorLeaderboard, RepositoryLeaderboard, TeamLeaderboard, ScoringRules, RecomputeButton (dev-only), LeaderboardControls, TimelineChart, RepositoryContributorsTimeline, BrushNavigator, charts
├── analytics/ OrganizationAnalytics, OrganizationActivityTrend, ContributorProfileView, ContributorSelector, ContributionHeatmap, ActivityTimeline, RepositoryAnalytics, RepositoryActivityTrend
├── shared/charts/ ChartTooltip, ChartDropdown, MiniSparkline (pure SVG sparkline)
├── providers/ QueryProvider, TanStackDevtools
├── docs/ (empty — reserved for docs-specific components)
└── ui/ shadcn/ui re-exports (chart.tsx unused by feature components)hooks/
hooks/
├── queries/ # TanStack Query useQuery hooks
├── mutations/ # TanStack Query useMutation hooks
├── query-keys.ts # Centralized query key factory
├── use-auth-session.ts # Session hook (wraps GET /api/auth/session)
└── use-mobile.ts # Mobile breakpoint detectionlib/
All server and shared business logic. No React.
lib/
├── auth/
│ └── server/ # OAuth flow, session CRUD, crypto, cookie helpers, installation auth
├── github/
│ ├── client-factory.ts # Octokit factories (App singleton, installation token)
│ ├── create-leaderboard-octokit.ts # Install-first, user-fallback strategy
│ ├── fetch-graphql.ts # fetchOrgScoringDataGraphQL, fetchOrgTeamsDataGraphQL
│ ├── graphqlProxy.ts # executeGithubGraphql (public proxy executor)
│ ├── graphql-response-cache.ts # LRU + Redis cache for GraphQL responses
│ ├── ingest-limits.ts # Pagination caps and concurrency limits
│ ├── operations/registry.ts # USER_GITHUB_GRAPHQL_OPERATIONS + OPERATION_QUERY_FALLBACKS
│ └── queries/ # Server-side ingest query strings (bypass allowlist)
├── leaderboard/
│ ├── pipeline.ts # recomputeLeaderboard, serveLeaderboard, refreshLeaderboardInBackground
│ ├── ingest.ts # runIngest()
│ ├── ingest-freshness.ts # evaluateIngestFreshness, 24h cooldown logic
│ ├── score.ts # scoreActivePresetForEntity, scoreRemainingEntityTypes
│ ├── serve.ts # serveLeaderboard, computeCustomDateRange
│ ├── redis-cache.ts # Snapshot cache (24h TTL)
│ ├── request-cache.ts # Memory LRU (30s) + response cache (24h)
│ ├── cache-key.ts # Cache key generation helpers
│ ├── resolve-installation.ts # resolveInstallationForOrganization
│ └── time-range.ts # getDateRangeForScoreTimePeriod
├── scoring/
│ ├── engine.ts # computeScores, computeSignalScore, buildLeaderboard
│ ├── aggregate.ts # aggregateByRepository, aggregateByTeamSignals
│ ├── normalize.ts # normalizeGitHubData (GitHub API response → Signal[])
│ ├── diminishing.ts # diminishingValue formula
│ ├── rules.ts # defaultScoringRuleset()
│ └── index.ts # Barrel
├── supabase/ # DB repositories, one file per domain
│ ├── leaderboard-db.ts # Leaderboard read/write (largest file)
│ ├── signals.ts # Signal upsert logic
│ ├── installation-repository.ts # Installation CRUD
│ ├── organization-repository.ts # Org CRUD
│ ├── repo-cache.ts # Repository cache
│ ├── team-cache-repository.ts # Team cache
│ ├── user-repository.ts # User CRUD
│ ├── ingest-state.ts # Ingest lock/state management
│ └── server.ts # Supabase server client factory
├── analytics/ # rollups.ts — type definitions only, no queries
├── api/ # server.ts — requireApiSession, apiError, parseJsonBody
├── cache/ # redis.ts — Upstash REST client, redisPatternDel
├── constants/ # time.ts — SCORE_TIME_PERIODS, INGEST, CACHE constants
├── env/ # index.ts — @t3-oss/env-nextjs config + lazy proxies
├── errors.ts # Error → human-readable message mapping
├── organization/ # Org helper utilities
├── schemas/ # Zod schemas for API request validation
└── utils.ts # cn() — clsx + tailwind-mergestores/
Zustand stores for client state.
stores/
├── auth-store.ts # session: AuthSession | null
├── workspace-store.ts # selectedTeam, dateRange
├── leaderboard-store.ts # leaderboardType, selectedRepository, selectedTeam, scoringRules
├── analytics-store.ts # activeView, selectedRepository, selectedContributor
└── url-params-store.ts # Per-route URL param cachetypes/
TypeScript interfaces and types only — no runtime code.
types/
├── auth/ # session.ts (SessionView omits githubToken), state.ts
├── api/ # installations, leaderboards, auth, sync, mass-invite
├── db/ # All DB table shapes as TS interfaces
├── scoring/ # rules, leaderboard, aggregate, graphql, signals, presets
├── github/ # installation.ts, teams.ts
└── installations/ # snapshot.tssupabase/migrations/
11 SQL migrations applied in order (001–011). Do not modify applied migrations — add new ones instead.
| File | Purpose |
|---|---|
001_enums_and_utilities.sql | Enums, utility functions |
002_users_and_organizations.sql | Users and orgs tables |
003_repositories_and_teams.sql | Repositories, teams |
004_relationships.sql | Join tables |
005_github_installations.sql | GitHub App installations |
006_auth_sessions.sql | Auth sessions + token columns |
007_scoring_presets.sql | Scoring preset configuration |
008_signals.sql | Signals table with monthly partitioning |
009_sync_state.sql | Ingest state and lock tracking |
010_leaderboard_materializations.sql | Leaderboard snapshot storage |
011_computed_scores.sql | Computed score rows |
Last updated on