# Repo map A quick map of where things live, so you can go straight to the right file. Path aliases (from `tsconfig*.json`): | Alias | Resolves to | Use from | | --- | --- | --- | | `@server/*` | `server/*` | anywhere (server and UI, for shared types) | | `@app/*`, `@/*` | `src/*` | UI | | `@test/*`, `@cli/*` | `test/*`, `cli/*` | tests, CLI | | `#private/*` | `server/private/*` | **only** inside `server/private/` | | `#dynamic/*` | `server/private/*` (enterprise/saas) or `server/*` (oss) | outside `server/private/` when you need the private implementation on paid builds | | `#open/*`, `#closed/*` | `server/*`, `server/private/*` | internal to the esbuild `#dynamic` switcher; don't use | ## Top level ``` server/ Express API server (TypeScript, bundled with esbuild.mjs) src/ Next.js dashboard (App Router) messages/ i18n JSON. Only en-US.json is edited by hand; Crowdin generates the others config/ config.yml (+ privateConfig.yml on enterprise), example configs cli/ pangctl CLI install/ installer (Go) docs/ Developer docs for agents and contributors (this folder) test/ Shared test helpers scripts/ Build/test scripts (run-tests.mjs) esbuild.mjs Server bundler; holds the #private guard and the #dynamic switcher drizzle.*.ts Drizzle configs (drizzle.config.ts is generated by set:pg / set:sqlite) ``` Generated and gitignored, switched by npm scripts: `server/build.ts` (`npm run set:oss|enterprise|saas`), `tsconfig.json` (copied from `tsconfig.{oss,enterprise,saas}.json`), `server/db/index.ts`, `drizzle.config.ts`, `server/setup/migrations.ts` (`npm run set:sqlite|pg`). ## server/ ``` server/ index.ts Entry. Boots config, migrations, and all servers below apiServer.ts External API (dashboard + user API). Routes: #dynamic/routers/external internalServer.ts Internal API (Next server-side fetches, badger). Routes: #dynamic/routers/internal integrationApiServer.ts Integration API (API keys, OpenAPI docs). Routes: #dynamic/routers/integration aiGatewayServer.ts AI gateway nextServer.ts Serves the Next app openApi.ts OpenAPITags enum + registry build.ts GENERATED: `build` = "oss" | "enterprise" | "saas" auth/ actions.ts (ActionsEnum), sessions/, password, totp, canUserAccess*.ts middlewares/ verify*Access.ts, verifyUserHasAction, verifyLimits, logActionAudit (stub) integration/ verifyApiKey*.ts counterparts for the integration API routers/ One folder per entity (see below) + router files: external.ts Dashboard/user routes (session auth) internal.ts Internal routes integration.ts API-key routes (needs public-/private-resource aliases) hybrid.ts Hybrid/remote node routes private/ ENTERPRISE/SAAS ONLY (see docs/enterprise-private-code.md) routers/{external,internal,integration,hybrid}.ts Import the public routers and add private routes routers// Private-only handlers lib/ Private implementations of #dynamic modules, config, redis, stripe, billing lib/readConfigFile.ts privateConfigSchema (private config values) lib/config.ts `privateConfig` singleton middlewares/ Real logActionAudit etc. lib/ config.ts `config` singleton: config.getRawConfig() readConfigFile.ts Public config zod schema crypto.ts encrypt/decrypt (AES, keyed by server.secret) blueprints/ Blueprint schema (types.ts) + apply (publicResources.ts, privateResources.ts) + export traefik/ Traefik dynamic config generation for public resources billing/tierMatrix.ts TierFeature -> tiers; used by server and UI paywalls response.ts `response()` envelope helper validators.ts, schemas.ts Shared zod validators deleteResource.ts, deleteSiteResource.ts, deleteOrg.ts Cascading delete helpers rebuildClientAssociations.ts Recomputes client <-> site resource access db/ index.ts GENERATED: re-exports ./pg or ./sqlite + `driver` pg/schema/{schema,privateSchema}.ts Postgres tables sqlite/schema/{schema,privateSchema}.ts SQLite tables (must mirror pg) setup/ Startup tasks + migrations (scriptsPg/, scriptsSqlite/). Don't edit unless asked emails/ React email templates routers/newt/ Messages to/from Newt (site connector) over websockets routers/olm/ Messages to/from Olm (client connector) routers/gerbil/ Exit node (WireGuard) coordination routers/badger/ Traefik auth plugin endpoints (verifySession) routers/traefik/ Traefik HTTP config provider routers/ws/ Websocket server (private/routers/ws for enterprise) ``` ### Entity routers (`server/routers//`) Each folder has `index.ts` (re-exports), one file per operation (`createX.ts`, `getX.ts`, `listXs.ts`, `updateX.ts`, `deleteX.ts`), and often `types.ts` / `validation.ts`. See `docs/crud-endpoints.md`. Main ones: `org`, `site`, `resource` (public resources), `siteResource` (private resources), `target` (public resource targets), `policy` (resource policies), `client`, `user`, `role`, `domain`, `idp`, `apiKeys`, `accessToken`, `blueprints`, `labels`, `redirect`, `aiProvider`, `aiBudget`, `virtualApiKey`, `auditLogs`, `certificates`. ## src/ (dashboard) ``` src/ app/ layout.tsx, navigation.tsx Root layout; sidebar nav items (orgNavSections etc.) [orgId]/settings/ All org settings pages (one folder per section) layout.tsx Sidebar shell general/ Org settings: layout.tsx (tabs) + page.tsx, security/, logs/, auth-page/ resources/public/ Public resources: page.tsx (list), create/, [niceId]// resources/private/ Private (site) resources: page.tsx, create/, [niceId]// sites/, clients/, access/, domains/, api-keys/, blueprints/, ai-providers/, ... (private)/ Route group for enterprise-only pages (billing, idp, license, policies, remote-exit-nodes) admin/ Server admin pages auth/ Login, signup, 2FA, resource auth pages components/ ui/ shadcn primitives (button, form, input, select, tabs, ...) Credenza.tsx Responsive modal (dialog on desktop, drawer on mobile). Use for every modal DismissableBanner.tsx Help/info banner (wrapped by *Banner.tsx components) HorizontalTabs.tsx Route-based tabs used in [id]/layout.tsx files Settings.tsx SettingsContainer / SettingsSection / ... layout primitives SettingsSectionTitle.tsx Page title + description PaidFeaturesAlert.tsx Paywall notice for tiered features ConfirmDeleteDialog.tsx Type-the-name-to-delete Credenza contexts/ + providers/ + hooks/ Context per entity: OrgProvider/useOrgContext, ResourceProvider/useResourceContext, SiteResourceProvider/useSiteResourceContext, useEnvContext, usePaidStatus, ... lib/ api/ index.ts: createApiClient (client), `internal` (server components), formatAxiosError; cookies.ts: authCookieHeader pullEnv.ts Builds the Env object (flags etc.) from process.env for the UI ``` ### Fetching data - **Server components / layouts**: `internal.get>(path, await authCookieHeader())`, with `internal` from `@app/lib/api` and `authCookieHeader` from `@app/lib/api/cookies`. Use `getCachedOrg` / `getCachedOrgUser` from `@app/lib/api/*` for the org. - **Client components**: `const api = createApiClient(useEnvContext());`, then `api.get/put/post/delete`. Errors go to `toast({ variant: "destructive", description: formatAxiosError(e, t("...")) })`. - Response types are imported straight from the server router, e.g. `import { GetResourceResponse } from "@server/routers/resource"`.