Docs and code (identifiers, comments, commit messages) are English only. Chat with the user is in the user's language.
Root (all workspaces, nx run-many fan-outs):
pnpm lint # nx run-many -t lint
pnpm typecheck # nx run-many -t typecheck (tsgo)
pnpm test:unit # vitest watch; pnpm test:unit:ci for a single run
pnpm stylelint
pnpm circular-deps # madge, UI code only
pnpm knip # unused files/exports/deps
pnpm deps:check # syncpack — dependency versions consistent across packages
pnpm docs:check # docs/packages coverage + link validity
pnpm har:check # e2e HAR mocks carry no secrets (re-runs the sanitizer + scans for tokens)Single package — use a pnpm filter with the package name, not the folder:
pnpm --filter app-web dev
pnpm --filter app-backend start:dev
pnpm --filter @languages-learner/uikit typecheckFull local stack: pnpm dev at the root (backend in Docker + apps/web natively). Every package
has its own README.md listing its scripts — check it before inventing commands.
- Code: 4-space indent, 100 columns, trailing commas, LF (
linebreak-styleis an ESLint error on Windows too). Tailwind class sorting viaprettier-plugin-tailwindcss. - Markdown/JSON/YAML: 2-space indent (override in
prettier.config.mjs), 100 columns, LF.
- Type imports must be inline:
import { type Foo }(@typescript-eslint/consistent-type-imports,fixStyle: "inline-type-imports"). newline-before-returnis an error.- FSD: imports flow downward only; cycles forbidden (
madge). - Do not edit generated files (
database.types.ts,openapi.json,api.ts). - No
VITE_-prefixed copies of Supabase credentials — see architecture/web-ssr.md.
- PR titles must be conventional/semantic (
feat:,fix:,chore:…), enforced by.github/workflows/check-pr-title.yml. - Before a PR:
pnpm lint,pnpm typecheck,pnpm test:unit:ci,pnpm docs:check.
Change code → update the matching page in docs/. Rules and the trigger table are in
maintaining-docs.md.