From 36e7dcf2f432f840783520e7ed8df3fa3a0856fb Mon Sep 17 00:00:00 2001 From: Niels Mokkenstorm Date: Sun, 17 May 2026 10:25:51 +0200 Subject: [PATCH] docs(cvg-69): add root README documenting layout, apps, packages, ci/deploy --- README.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f4a7a18 --- /dev/null +++ b/README.md @@ -0,0 +1,114 @@ +# cv-generator + +AI-assisted CV builder. Parses incoming CVs (PDF, GDPR export, manual entry), customises them per vacancy, and renders to HTML/PDF via a Playwright worker. + +- Issue tracker: [Linear `CVG`](https://linear.app/riotbyte/team/CVG) (workspace `riotbyte`, initiative [Ship CV Generator](https://linear.app/riotbyte/initiative/ship-cv-generator-3219205155f0)) +- Remote: `git@tangled.sh:mokkenstorm.dev/cv-manager` (GitHub mirror at `riotbyte-com/cv-generator`) + +## Repo layout + +This is a **bare repo with worktrees**, not a normal clone. + +``` +cv-generator/ +├── .bare/ bare repo (git objects, refs, config) +├── .git file pointing at .bare +├── .worktrees/ feature branch worktrees (one per CVG-N) +│ └── cvg-/ branch: feature/cvg- +└── main/ primary worktree, branch: main +``` + +All code lives inside worktrees. Don't try to check out files in the container directory itself. + +```bash +git worktree add .worktrees/cvg- -b feature/cvg- main +git worktree list +git worktree remove .worktrees/cvg- +``` + +## Monorepo + +pnpm workspaces orchestrated by lerna. + +### Apps + +| Path | Role | +| ------------- | ------------------------------------------------------------------------------------------------------------------ | +| `apps/api` | Thin GraphQL shell: resolvers, types, inputs, DataLoaders, REST sidecars. NestJS 11 + Apollo Server 5 + Express 5. | +| `apps/worker` | NestJS standalone process. Consumes the project-q queue. No HTTP, no GraphQL. Renders PDFs via Playwright. | +| `apps/client` | React + React Query + GraphQL codegen. Vite. | +| `apps/docs` | Documentation site (Vite). | + +### Packages + +| Path | Role | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `packages/core` | Thick NestJS module library: domain entities, services, Prisma, mail, database. Schema lives in `packages/core/prisma/`. | +| `packages/auth` | Guards (`JwtAuthGuard`, `VerifiedScopeGuard`), passport strategies, `AuthModule`. Imported by `apps/api`. (Auth domain _entities_ live in `@cv/core/auth`.) | +| `packages/handlers` | Project-q queue handlers (worker-side message → domain dispatch). | +| `packages/ai-parser` | LLM-driven CV parsing. Provider-agnostic. | +| `packages/ai-provider` | Self-registering AI provider registry (OpenAI, Anthropic, Ollama, ...). | +| `packages/cv-renderer` | Handlebars → HTML. **HTML only, no Playwright** - the worker owns rendering to PDF. | +| `packages/handlebars` | Shared Handlebars helpers/partials. | +| `packages/file-storage` | File backend abstraction (local, S3-compatible). | +| `packages/file-upload` | Upload pipeline primitives. | +| `packages/mail` | Transactional mail. | +| `packages/routing` | Shared React Router config / link helpers. | +| `packages/ui` | Shared client components (ESM). | +| `packages/utils` | `compact()`, `raise()`, misc. | +| `packages/biome-config` | Shared Biome config. | +| `packages/tsconfig` | Shared tsconfig bases. | + +### Pipeline + +``` +input (PDF / GDPR ZIP / manual) + → ai-parser + → customisation pass + → cv-renderer (Handlebars → HTML) + → worker (Playwright → PDF) +``` + +## Local dev + +```bash +pnpm install +pnpm prisma:generate +pnpm db:setup # prisma:deploy + seed +pnpm codegen # prisma:generate + GraphQL codegen (needs API running for schema introspection) +pnpm dev # all apps in parallel +``` + +Local optional LLM: + +```bash +pnpm llama:start # boot Ollama +pnpm llama:stop +``` + +`.env*` files are permission-blocked by tool settings; consult `git show HEAD:.env.example` for the template. + +## CI / deploy + +| File | Purpose | +| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| `.github/workflows/ci.yml` | Lint, typecheck, build, audit on every push. | +| `.github/workflows/release.yml` | Tag push → build & push server/worker images to GHCR via `ci/build-images.sh`. | +| `.github/workflows/deploy.yml` | Manual dispatch on a tag → `kubectl set image` on the production cluster. | +| `.github/workflows/deploy-client.yml` | Tag push → deploy SPA to Cloudflare Pages via `ci/deploy-client.sh`. | +| `.github/workflows/create-release.yml` | Tag bookkeeping. | +| `ci/pipeline.ts` | Local mirror of CI steps (install / prisma / lint / typecheck / build / audit). Run as `pnpm tsx ci/pipeline.ts [step]`. | +| `.docker/` | Production Dockerfiles + pruned workspace manifests (`copy-manifests.sh`). | + +Cluster manifests (Prometheus, ingress, cron jobs, secrets) live in a **separate infra repo**, not here. + +## Conventions + +- **Commits:** Conventional Commits, one-line header, scope is the Linear key (e.g. `feat(cvg-84): move CV parsing onto worker queue`). +- **Branches:** `feature/cvg-` matching the Linear issue. +- **TypeScript:** strict, `exactOptionalPropertyTypes` enabled. Use `compact()` from `@cv/utils` for Prisma inputs that may contain `undefined`. +- **Style (TS/JS):** functional patterns, guard clauses with braces, ternaries for simple conditionals, no `if/else` ladders, no `for` loops, no inline comments (code should be self-documenting). Biome enforces. +- **GraphQL codegen** needs a running API (`localhost:3000/graphql`) for schema introspection. +- **Async jobs** run on the project-q queue. The API enqueues, the worker handles. Job status persists to the `AsyncJob` Prisma model. +- **Zod 4:** import from `"zod/v4"`. `z.object()` is strict by default; use `z.looseObject()` for passthrough. +- **Prisma 7:** import error classes directly, not via the `Prisma.` namespace (TS 5.9 fails to narrow through the re-export). -- 2.51.2