# Codebase Structure **Analysis Date:** 2026-05-11 ## Directory Layout ```text reactive-resume/ ├── apps/ │ └── web/ # Sole deployable application (TanStack Start / Vite / Nitro) │ ├── plugins/ # Nitro startup plugins (run on `pnpm dev` / `pnpm start`) │ ├── public/ # Static assets (PWA, opengraph, templates, screenshots) │ ├── locales/ # Lingui `.po` translation catalogs (~40 locales) │ ├── src/ │ │ ├── components/ # Reusable web components grouped by feature │ │ ├── dialogs/ # Global dialog system + dialog implementations │ │ ├── hooks/ # App-level React hooks │ │ ├── libs/ # Browser/server glue (auth, orpc, query, resume, theme, locale, pwa) │ │ ├── routes/ # File-based TanStack Router routes (UI + `server.handlers`) │ │ ├── router.tsx # Router factory (builds query client, context, SSR query integration) │ │ ├── routeTree.gen.ts # GENERATED — do not hand-edit │ │ ├── server.ts # Nitro fetch entry (wraps `react-start/server-entry`) │ │ └── index.css # Tailwind v4 entry │ ├── components.json # shadcn config │ ├── lingui.config.ts # i18n extract config │ ├── vite.config.ts # Vite + TanStack Start + Nitro + PWA + Lingui │ └── vitest.config.ts ├── packages/ │ ├── ai/ # AI prompts, Zustand store, patch-resume tool │ ├── api/ # oRPC routers, services, helpers, DTOs, rate-limit middleware │ ├── auth/ # Better Auth config and helpers │ ├── config/ # Shared tsconfig + vitest base configs │ ├── db/ # Drizzle client + schema (Postgres) │ ├── email/ # Nodemailer transport + react-email templates │ ├── env/ # `@t3-oss/env-core` server env (auto-loads root `.env`) │ ├── fonts/ # Google Fonts metadata │ ├── import/ # JSON Resume / Reactive Resume v3/v4 importers │ ├── pdf/ # React PDF document, fonts, 14 templates, shared primitives │ ├── runtime-externals/ # Declares bcrypt, sharp, @aws-sdk/client-s3 as runtime-only │ ├── schema/ # Zod schemas (resume data, templates, page, analysis, icons) │ ├── scripts/ # Standalone tsx scripts (db reset, font generation) │ ├── ui/ # Shared Base UI + shadcn-style components │ └── utils/ # Small focused helpers (color, date, html, sanitize, etc.) ├── migrations/ # Drizzle-generated SQL + snapshots (one folder per migration) ├── docs/ # Project documentation ├── skills/ # Internal agent skill definitions ├── data/ # Local-FS storage root (when S3 is unset) — gitignored runtime data ├── .vite-hooks/ # Lefthook-managed git hooks (commit-msg, pre-commit) ├── .github/ # GitHub Actions / issue templates ├── .claude/ # Project-local Claude/Codex agent assets ├── .codex/ ├── .planning/ # GSD planning + codebase maps (this directory) ├── .vscode/ ├── compose.dev.yml # Postgres + SeaweedFS for local dev ├── compose.yml # Production-shaped compose ├── Dockerfile # Node 24 multi-stage build ├── AGENTS.md # Canonical agent guide (symlinked from CLAUDE.md) ├── README.md ├── SECURITY.md ├── LICENSE ├── package.json # Root scripts (turbo run …) + workspace devDeps ├── pnpm-workspace.yaml # `apps/*` + `packages/*` ├── pnpm-lock.yaml ├── turbo.json # Pipeline + globalEnv allowlist ├── biome.json # Biome (lint + format) config ├── knip.json # Dead-code/dep analysis config ├── lefthook.yml # Git hooks ├── commitlint.config.cjs ├── crowdin.yml # Translation sync config ├── tsconfig.json # Root TS solution config ├── vitest.shared.ts / vitest.setup.ts # Shared vitest config and global setup ├── .ncurc.cjs # npm-check-updates ignore list ├── .env.example # Documented env vars └── .gitignore / .dockerignore ``` ## Directory Purposes **`apps/web/`:** - Purpose: The only deployed app — TanStack Start / React 19 / Vite / Nitro. - Contains: Routes, components, dialogs, hooks, libs, server entry, build config. - Key files: `apps/web/vite.config.ts`, `apps/web/src/router.tsx`, `apps/web/src/server.ts`, `apps/web/src/routes/__root.tsx`, `apps/web/plugins/1.migrate.ts`, `apps/web/plugins/2.storage.ts`. **`apps/web/src/routes/`:** - Purpose: TanStack Router file-based route tree. Each file is either a UI route, a server-only endpoint (`server.handlers`), or both. - Notable subtrees: - `__root.tsx` — global HTML shell, providers, head/meta, PWA scripts. - `_home/` — public marketing layout (`route.tsx`, `index.tsx`, `-sections/{hero,features,faq,testimonials,...}.tsx`). - `auth/` — login/register/2FA/password flows and OAuth callback (`oauth.ts`). - `dashboard/` — authenticated dashboard (`route.tsx`, `index.tsx`, `resumes/`, `settings/{profile,preferences,api-keys,authentication,integrations,job-search,danger-zone}.tsx`, `-components/{header,sidebar,functions}.{ts,tsx}`). - `builder/$resumeId/` — resume builder (`route.tsx` shell, `index.tsx` browser-only preview, `-components/`, `-sidebar/{left,right}/`, `-store/{section,sidebar}.ts`). - `$username/$slug.tsx` — public/shared resume route (`ssr: "data-only"`). - `api/` — server-only endpoints (`rpc.$.ts`, `auth.$.ts`, `health.ts`, `openapi.$.ts`, `uploads/$userId.$.ts`, `-helpers/resume-pdf.ts`). - `mcp/` — Model Context Protocol server (`index.ts`, `-helpers/{tools,resources,prompts,mcp-server-card,mcp-tool-names,tool-annotations}.ts`). - `[.]well-known/` — OAuth/OIDC/MCP discovery documents. - `uploads/$userId.$.tsx` — etag/security-validated file serving. - `templates/$.tsx` — template preview/download. - `schema[.]json.ts` — `/schema.json` endpoint. **`apps/web/src/components/`:** - Purpose: Reusable, app-scoped components organized by domain. - Subdirectories: - `animation/` — Motion-driven UI (`comet-card`, `count-up`, `spotlight`, `text-mask`). - `command-palette/` — Cmd-K UI (`index.tsx`, `store.ts`, `pages/`). - `input/` — Custom inputs (`chip-input`, `color-picker`, `github-stars-button`, `icon-picker`, `rich-input`, `url-input`). - `layout/` — Error/loading/not-found screens, breakpoint indicator. - `level/`, `locale/`, `theme/`, `typography/` — combobox/toggle utilities for those concerns. - `resume/` — Builder preview surface (`preview.tsx`, `preview.browser.tsx`, `preview.shared.tsx`, `pdf-canvas.tsx`, `builder-resume-draft.ts`). - `ui/` — App-level UI extensions (`combobox.tsx`, `copyright.tsx`). - `user/` — User dropdown menu. **`apps/web/src/libs/`:** - Purpose: Glue between UI and external systems. - Contents: - `auth/{client.ts,session.ts}` — Better Auth browser client + SSR session getter. - `orpc/client.ts` — Isomorphic oRPC client (in-process server + RPCLink browser). - `query/client.ts` — TanStack Query client factory. - `resume/` — Section, PDF, and ordering helpers (`make-section-item.ts`, `move-item.ts`, `section-actions.ts`, `section-title.ts`, `section-title-locale.ts`, `pdf-document.tsx`, `pdf-document.server.tsx`, `section.tsx`). - `theme.ts`, `locale.ts`, `pwa.ts`, `error-message.ts`, `tanstack-form.tsx` — direct app utilities. **`apps/web/src/dialogs/`:** - Purpose: Global imperative dialog system. - Contents: `manager.tsx` (renders open dialogs), `store.ts` (Zustand store), then domain dialogs under `auth/`, `resume/{sections,template,index.tsx,import.tsx}`, `api-key/`. **`apps/web/src/hooks/`:** - Purpose: Web-app hooks. (Shared cross-package hooks live in `packages/ui/src/hooks/`.) - Contents: `use-confirm.tsx`, `use-controlled-state.tsx`, `use-form-blocker.tsx`, `use-mobile.tsx`, `use-prompt.tsx`, `use-sync-form-values.ts`. **`apps/web/plugins/`:** - Purpose: Nitro startup plugins. - Contents: `1.migrate.ts` (runs Drizzle migrations on boot), `2.storage.ts` (validates the local data dir when S3 isn't configured). **`apps/web/public/`:** - Purpose: Static assets served at the site root. - Notable subdirs: `templates/{jpg,pdf}/` (per-template previews), `screenshots/` (PWA + marketing), `opengraph/`, `icon/`, `logo/`, `fonts/`, `photos/`, `sounds/`, `videos/`. Top-level files include `favicon.{ico,svg}`, `apple-touch-icon-180x180.png`, `manifest.webmanifest`, `pwa-{64,192,512}x.png`, `maskable-icon-512x512.png`, `robots.txt`, `sitemap.xml`, `funding.json`. **`apps/web/locales/`:** - Purpose: Lingui `.po` translation catalogs (~40 languages, `en-US` is source). - Synced via `crowdin.yml` and `pnpm lingui:extract`. **`packages/ai/`:** - Purpose: AI prompt assets, patch-resume tool, sanitize/extraction helpers. - Key paths: `packages/ai/src/prompts/{chat,analyze-resume,docx-parser,pdf-parser}-*.md`, `packages/ai/src/store.ts`, `packages/ai/src/tools/{patch-resume,patch-proposal}.ts`, `packages/ai/src/resume/{extraction-template,sanitize}.ts`. **`packages/api/`:** - Purpose: Server-side business logic exposed over oRPC. The only place oRPC procedures live. - Key paths: `packages/api/src/context.ts` (auth context + `publicProcedure`/`protectedProcedure`), `packages/api/src/routers/{ai,auth,flags,resume,statistics,storage,index}.ts`, `packages/api/src/services/{resume,resume-events,storage,ai,auth,flags,statistics}.ts`, `packages/api/src/dto/resume.ts`, `packages/api/src/helpers/{resume-access,resume-access-policy}.ts`, `packages/api/src/middleware/rate-limit/index.ts`. **`packages/auth/`:** - Purpose: Better Auth instance and types reused by web routes and API context. - Key paths: `packages/auth/src/config.ts` (Drizzle adapter, OAuth/passkey/2FA/api-key/JWT/MCP OAuth provider), `packages/auth/src/functions.ts`, `packages/auth/src/types.ts`. **`packages/config/`:** - Purpose: Shared tsconfig and vitest base configs consumed via workspace devDep. - Key paths: `packages/config/tsconfig.base.json`, `packages/config/vitest.config.ts`. **`packages/db/`:** - Purpose: Drizzle client and schema. Migration tooling but **migrations live in repo-root `migrations/`** (`packages/db/drizzle.config.ts` → `out: "../../migrations"`). - Key paths: `packages/db/src/client.ts` (singleton `pg.Pool` + `drizzle()` on `globalThis`), `packages/db/src/schema/{auth,resume,index}.ts`, `packages/db/src/relations.ts`. **`packages/email/`:** - Purpose: SMTP transport + react-email templates. - Key paths: `packages/email/src/transport.ts`, `packages/email/src/templates/{auth,reset-password,verify-email,verify-email-change}.tsx`. **`packages/env/`:** - Purpose: Type-safe server environment variables. Auto-loads the repo-root `.env` for app/server callers (drizzle-kit must export `DATABASE_URL` manually). - Key paths: `packages/env/src/server.ts`. **`packages/fonts/`:** - Purpose: Generated Google Fonts metadata used by the typography combobox and React PDF font registration. - Key paths: `packages/fonts/src/index.ts`, `packages/fonts/src/webfontlist.json` (regenerated by `packages/scripts/fonts/generate.ts`). **`packages/import/`:** - Purpose: Importers that convert external resume formats into the shared `ResumeData` schema. - Key paths: `packages/import/src/{json-resume,reactive-resume-json,reactive-resume-v4-json}.tsx`. **`packages/pdf/`:** - Purpose: React PDF rendering — the same code paths used by the browser preview and the server-side PDF download. - Key paths: `packages/pdf/src/document.tsx`, `packages/pdf/src/context.tsx`, `packages/pdf/src/section-title.ts`, `packages/pdf/src/hooks/use-register-fonts.ts`, `packages/pdf/src/templates/index.ts`, `packages/pdf/src/templates//Page.tsx` (14 templates: `azurill`, `bronzor`, `chikorita`, `ditgar`, `ditto`, `gengar`, `glalie`, `kakuna`, `lapras`, `leafish`, `meowth`, `onyx`, `pikachu`, `rhyhorn`, `scizor`), shared primitives under `packages/pdf/src/templates/shared/` (`filtering.ts`, `rich-text.tsx`, `sections.tsx`, `primitives.tsx`, `picture.ts`, `page-size.ts`, `columns.ts`, `metrics.ts`, `meta-line.tsx`, `contact.ts`, `contact-item.tsx`, `level-display.tsx`, `section-links.ts`, `rich-text-html.ts`, `rich-text-spacing.ts`, `styles.ts`, `types.ts`, `context.tsx`). **`packages/runtime-externals/`:** - Purpose: Vendors `bcrypt`, `sharp`, `@aws-sdk/client-s3` so they stay runtime-only (Vite externalizes them in `apps/web/vite.config.ts:55`). - No `src/` — `package.json` is the entire surface. **`packages/schema/`:** - Purpose: Source-of-truth Zod schemas for resume data, templates, page settings, AI analysis, and icon catalog. - Key paths: `packages/schema/src/resume/{data,default,sample,analysis}.ts`, `packages/schema/src/templates.ts`, `packages/schema/src/page.ts`, `packages/schema/src/icons.ts`. **`packages/scripts/`:** - Purpose: Standalone tsx scripts; no exports. - Key paths: `packages/scripts/database/reset.ts` (`pnpm --filter @reactive-resume/scripts db:reset`), `packages/scripts/fonts/generate.ts` (`pnpm --filter @reactive-resume/scripts fonts:generate`). **`packages/ui/`:** - Purpose: Shared component library (Base UI primitives + shadcn-style wrappers, Tailwind v4 styles). - Key paths: `packages/ui/src/components/{dialog,dropdown-menu,command,resizable,form,tooltip,sonner,…}.tsx`, `packages/ui/src/hooks/{use-confirm,use-controlled-state,use-mobile,use-prompt}.tsx`, `packages/ui/src/styles/globals.css`. **`packages/utils/`:** - Purpose: Pure utility functions used everywhere. Each helper has its own export path; do not import internal files. - Key paths: `packages/utils/src/{color,date,field,file,html,level,locale,network-icons,rate-limit,sanitize,string,style,url}.ts`, Node-only `packages/utils/src/{monorepo.node,url-security.node}.ts`, and `packages/utils/src/resume/{docx/index.ts,patch.ts}`. **`migrations/`:** - Purpose: Drizzle-generated migration directories (one per migration), kept at the repo root. - Layout: each `YYYYMMDDhhmmss__/` contains `migration.sql` (the SQL Drizzle will apply) and `snapshot.json` (Drizzle's internal state). - Applied by `apps/web/plugins/1.migrate.ts` on every server boot, and manually by `pnpm db:migrate`. Generated by `pnpm db:generate` (which writes here because of `out: "../../migrations"` in `packages/db/drizzle.config.ts`). Do not hand-edit `migration.sql`/`snapshot.json`. **`data/` (and `apps/web/data/`):** - Purpose: Default local-filesystem storage root when S3 vars are unset. `/data` is validated/created at boot by `apps/web/plugins/2.storage.ts`. Override with `LOCAL_STORAGE_PATH` (must be absolute). - `data/statistics/` and `apps/web/data/statistics/` exist as runtime byproducts; treat as gitignored runtime state. **`.vite-hooks/`:** - Purpose: Lefthook-managed git hooks (`pre-commit` runs `biome check`, `commit-msg` runs commitlint). Configured by `lefthook.yml` and `commitlint.config.cjs`. **`.planning/`:** - Purpose: GSD planning artifacts. - Subdirectories: `.planning/codebase/` (this directory — analysis docs). ## Key File Locations **Entry Points:** - `apps/web/src/server.ts` — Nitro fetch entry. - `apps/web/src/router.tsx` — Router factory. - `apps/web/src/routes/__root.tsx` — Root route + global providers. - `apps/web/plugins/1.migrate.ts` — Migration on boot. - `apps/web/plugins/2.storage.ts` — Local storage validation on boot. **Configuration:** - `apps/web/vite.config.ts` — Vite + TanStack Start + Nitro + PWA + Lingui. - `turbo.json` — Pipeline + `globalEnv` allowlist. - `pnpm-workspace.yaml` — Workspaces (`apps/*` + `packages/*`). - `biome.json` — Lint + format rules. - `knip.json` — Dead-code analysis config. - `lefthook.yml` — Git hooks. - `packages/db/drizzle.config.ts` — Drizzle migration config (writes to `../../migrations`). - `packages/env/src/server.ts` — Server env schema + `.env` loader. - `apps/web/lingui.config.ts` — i18n extract config. - `compose.dev.yml` / `compose.yml` — Postgres + SeaweedFS (dev) and prod-shaped compose. **Core API:** - `packages/api/src/routers/index.ts` — Router root. - `packages/api/src/context.ts` — Auth resolver + procedure factories. - `packages/api/src/services/resume.ts` — Resume CRUD/patch/lock/password/duplication. - `packages/api/src/services/storage.ts` — S3 + local FS storage abstraction. - `packages/api/src/helpers/resume-access-policy.ts` — Visibility/redaction policy. **Core data:** - `packages/db/src/schema/resume.ts` — Resume, statistics, analysis tables. - `packages/db/src/schema/auth.ts` — Better Auth tables. - `packages/db/src/client.ts` — Singleton `pg.Pool` + `drizzle()` client. - `packages/schema/src/resume/data.ts` — Canonical Zod schema for `ResumeData`. - `packages/schema/src/templates.ts` — Enum of template names. **Core PDF:** - `packages/pdf/src/document.tsx` — `ResumeDocument` root component. - `packages/pdf/src/templates/index.ts` — Template registry. - `packages/pdf/src/hooks/use-register-fonts.ts` — Font registration + CJK fallbacks. - `packages/pdf/src/templates/shared/filtering.ts` — Shared section filtering. **Auth:** - `packages/auth/src/config.ts` — Better Auth instance. - `apps/web/src/routes/api/auth.$.ts` — `/api/auth/*` handler with OAuth sanitization. - `apps/web/src/libs/auth/{client.ts,session.ts}` — Browser client + SSR session helper. **Testing:** - `vitest.shared.ts`, `vitest.setup.ts` — Repo-wide setup (Testing Library, jest-dom, happy-dom env). - `packages/config/vitest.config.ts` — Reusable Vitest base. - `apps/web/vitest.config.ts` — Web app Vitest config. ## Naming Conventions **Files:** - Source files: `kebab-case.ts` / `kebab-case.tsx` (e.g. `resume-access-policy.ts`, `command-palette.tsx`). - Component PascalCase is reserved for component names *inside* files; filenames stay kebab-case (e.g. `Button` exported from `packages/ui/src/components/button.tsx`). - PDF template components are the one PascalCase exception: `packages/pdf/src/templates/azurill/AzurillPage.tsx` (kept that way because the directory name doubles as the template enum value). - Tests sit next to their subject: `foo.ts` ↔ `foo.test.ts`, `foo.tsx` ↔ `foo.test.tsx`. - Browser-only modules use a `.browser.tsx` suffix (e.g. `apps/web/src/components/resume/preview.browser.tsx`). - Server-only modules use a `.server.tsx` suffix when they live next to browser counterparts (e.g. `apps/web/src/libs/resume/pdf-document.server.tsx`). - Generated files use `.gen.ts` (e.g. `apps/web/src/routeTree.gen.ts`). - Node-only utilities use a `.node.ts` suffix (e.g. `packages/utils/src/monorepo.node.ts`, `packages/utils/src/url-security.node.ts`). **Routes (TanStack Router file conventions):** - `$param.tsx` — dynamic path segment (e.g. `apps/web/src/routes/$username/$slug.tsx`). - `$.tsx` — splat (matches the rest of the path; used for `api/rpc/$`, `api/auth/$`, `[.]well-known/$`). - `_layout/` (underscore prefix) — pathless layout group (e.g. `apps/web/src/routes/_home/`). - `-folder/` (dash prefix) — colocated, non-route helpers (`-components/`, `-sidebar/`, `-store/`, `-sections/`, `-helpers/`). The router ignores these. - `[.]well-known` — escaped folder name for paths starting with a dot. - `name[.]json.ts` — escaped dot in a route filename (used for `/schema.json`). - `route.tsx` — layout/wrapper route at a directory level; `index.tsx` — index route inside it. **Directories:** - `apps/` and `packages/` — kebab-case workspace members. - `packages//src//.ts` — every public path in `package.json` exports points into `src/`. **Package names:** All workspace packages are scoped under `@reactive-resume/*` (`api`, `auth`, `db`, `ui`, etc.). The web app is just `web`. ## Where to Add New Code **New oRPC procedure:** - Define in `packages/api/src/routers/.ts`, register it on the exported router map, and add corresponding business logic to `packages/api/src/services/.ts`. - If authenticated, prefer `protectedProcedure` from `packages/api/src/context.ts`. - If it mutates resumes, attach `resumeMutationRateLimit` from `packages/api/src/middleware/rate-limit/index.ts`. - Define input/output Zod schemas in `packages/api/src/dto/.ts` when reused. **New database table or column:** - Add the table/column to `packages/db/src/schema/.ts`, update `packages/db/src/relations.ts` if needed, re-export from `packages/db/src/schema/index.ts`. - Run `DATABASE_URL=... pnpm db:generate` to write a migration directory under `migrations/`. - Apply with `DATABASE_URL=... pnpm db:migrate` (or just start the app — `apps/web/plugins/1.migrate.ts` runs them on boot). **New resume field or section:** - Update Zod first in `packages/schema/src/resume/data.ts` (and `default.ts` / `sample.ts` if applicable). - Adjust API DTOs (`packages/api/src/dto/resume.ts`), importers (`packages/import/src/*.tsx`), PDF templates and shared primitives (`packages/pdf/src/templates/...`), and the builder forms under `apps/web/src/routes/builder/$resumeId/-sidebar/`. **New resume template:** - Add to the template enum in `packages/schema/src/templates.ts`. - Implement the page component at `packages/pdf/src/templates//Page.tsx` and register it in `packages/pdf/src/templates/index.ts`. - Drop static previews into `apps/web/public/templates/jpg/.jpg` and `apps/web/public/templates/pdf/.pdf`. **New web route:** - Add the file under `apps/web/src/routes/...`. Use `$param.tsx` for dynamic segments, `_layout/` for pathless groups, and `-folder/` for colocated helpers. - The route tree regenerates into `apps/web/src/routeTree.gen.ts` — do not hand-edit. - For browser-only sub-routes, set `ssr: false` (see `apps/web/src/routes/builder/$resumeId/index.tsx`) or `ssr: "data-only"` (see `apps/web/src/routes/$username/$slug.tsx`). **New server-only HTTP endpoint:** - Add a route file (typically under `apps/web/src/routes/api/`) and export `Route = createFileRoute(...)({ server: { handlers: { GET/POST/ANY: handler } } })`. - Import server-only deps (`@reactive-resume/db/client`, `@reactive-resume/api/services/*`) only inside the handler module so they stay out of the client bundle. **New shared component:** - App-only: `apps/web/src/components//.tsx` (with colocated test if behaviour is non-trivial). - Reused across packages: `packages/ui/src/components/.tsx` (export via deep path `@reactive-resume/ui/components/`). **New shared utility:** - Add to `packages/utils/src/.ts` and an explicit `"./": "./src/.ts"` entry in `packages/utils/package.json` `exports`. Never import private files across packages. **New dialog:** - Implement under `apps/web/src/dialogs//.tsx`. - Register with the dialog store and ensure `apps/web/src/dialogs/manager.tsx` renders it. **New AI prompt or tool:** - Prompts go in `packages/ai/src/prompts/.md` (re-exported via `packages/ai/src/prompts.ts`). - Tools go in `packages/ai/src/tools/.ts` and are exposed through the AI router in `packages/api/src/routers/ai.ts`. **New MCP tool/resource/prompt:** - Register in `apps/web/src/routes/mcp/-helpers/{tools,resources,prompts}.ts`; reuse existing oRPC services for actual logic. ## Special Directories **`apps/web/src/routes/`:** - Purpose: Source for the file-based route tree. - Generated artifact: `apps/web/src/routeTree.gen.ts`. - Committed: Yes (the tree file is committed; regenerated by TanStack Router tooling on dev/build). **`migrations/`:** - Purpose: Drizzle-generated SQL + snapshots. - Generated: Yes (by `pnpm db:generate`). - Committed: Yes — do not hand-edit, but always commit new migration folders. **`apps/web/.output/`:** - Purpose: Nitro/Vite production build output (server + client + PWA assets). - Generated: Yes (by `pnpm build`). - Committed: No (gitignored). **`apps/web/locales/`:** - Purpose: Lingui `.po` catalogs. - Generated: `en-US.po` is the source; other locales are synced via Crowdin (`crowdin.yml`). - Committed: Yes. **`data/` and `apps/web/data/`:** - Purpose: Default local storage root when S3 is unset (`/data`). - Generated: Yes (at runtime by `apps/web/plugins/2.storage.ts` or service calls). - Committed: No (gitignored runtime state). **`.turbo/`, `.pnpm-store/`, `node_modules/`:** - Purpose: Tool caches and dependency stores. - Committed: No. **`.vite-hooks/`:** - Purpose: Lefthook-installed git hooks (`commit-msg`, `pre-commit`). - Committed: Yes (so contributors get hooks automatically), but the underlying behavior is defined by `lefthook.yml`. **`packages/runtime-externals/`:** - Purpose: Marks `bcrypt`, `sharp`, `@aws-sdk/client-s3` as runtime dependencies that Vite externalizes. - No source files — package.json is the entire contract. ## Files / Locations to Avoid Hand-Editing - `apps/web/src/routeTree.gen.ts` — regenerated by TanStack Router tooling. - `migrations/_/migration.sql` and `snapshot.json` — generated by `drizzle-kit`. Add a new migration via `pnpm db:generate` instead of editing past ones. - `pnpm-lock.yaml` — managed by pnpm. Update via `pnpm install`. - `apps/web/.output/`, `apps/web/coverage/`, `packages/*/coverage/`, `packages/*/reports/` — build/test artifacts. - `apps/web/locales/*.po` (except `en-US.po`) — synced from Crowdin per `crowdin.yml`. - `apps/web/public/screenshots/`, `apps/web/public/opengraph/`, `apps/web/public/templates/{jpg,pdf}/` — regenerated assets; replace files wholesale rather than diff-editing. --- *Structure analysis: 2026-05-11*