Files
Julien Gautier d797becc2b chore: track Nx 22 AI tooling artefacts injected by generators
Nx 22 generators inject AI agent tooling into the repo via marked
sections and side files. Rather than re-deleting them after every
generator run, track the workspace-level ones and document why.

- CLAUDE.md gains a 'General Guidelines for working with Nx' section
  between Nx-managed markers; future Nx versions will update this
  section automatically without touching our project rules above.
  Pre-existing prettier-formatted blank lines added before code blocks
  are kept.
- .claude/settings.json (228 bytes) enables the nx-claude-plugins
  marketplace from nrwl/nx-ai-agents-config; tracked for contributor
  consistency. The personal .claude/settings.local.json stays
  gitignored.
- .github/ is the Nx AI skills/prompts/agents catalog. Kept despite
  being GitHub-named; it does not conflict with our Gitea workflows
  which will live under .gitea/workflows/ (per ADR-0015).
- .gitignore picks up Nx-managed transient dirs (.nx/polygraph,
  .claude/worktrees) and a trailing newline fix.

AGENTS.md is removed: it duplicated only the Nx auto-injected guidance
that CLAUDE.md already carries (CLAUDE.md is the strictly broader file
- project rules + Nx section). One source of truth for AI-agent
guidance.
2026-04-30 17:46:04 +02:00

4.3 KiB

Turborepo

The Config-as-Package Pattern

Turborepo monorepos ship with internal workspace packages that share configuration:

  • @repo/typescript-config (or similar) — tsconfig files (base.json, nextjs.json, react-library.json, etc.)
  • @repo/eslint-config (or similar) — ESLint config files and all ESLint plugin dependencies

These are not code libraries. They distribute config via Node module resolution (e.g., "extends": "@repo/typescript-config/nextjs.json"). This is the default Turborepo pattern — expect it in virtually every Turborepo import. Package names vary — check package.json files to identify the actual names.

Check for Root Config Files First

Before doing any config merging, check whether the destination workspace uses shared root configuration. This decides how to handle the config packages.

  • If the workspace has a root tsconfig.base.json and/or root eslint.config.mjs that projects extend, merge the config packages into these root configs (see steps below).
  • If the workspace does NOT have root config files — each project manages its own configuration independently (similar to Turborepo). In this case, do not create root config files or merge into them. Just remove turbo-specific parts (turbo.json, eslint-plugin-turbo) and leave the config packages in place, or ask the user how they want to handle them.

If unclear, check for the presence of tsconfig.base.json at the root or ask the user.

Merging TypeScript Config (Only When Root tsconfig.base.json Exists)

The config package contains a hierarchy of tsconfig files. Each project extends one via package name.

  1. Read the config package — trace the full inheritance chain (e.g., nextjs.json extends base.json).
  2. Update root tsconfig.base.json — absorb compilerOptions from the base config. Add Nx paths for cross-project imports (Turborepo doesn't use path aliases, Nx relies on them).
  3. Update each project's tsconfig.json:
    • Change "extends" from "@repo/typescript-config/<variant>.json" to the relative path to root tsconfig.base.json.
    • Inline variant-specific overrides from the intermediate config (e.g., Next.js: "module": "ESNext", "moduleResolution": "Bundler", "jsx": "preserve", "noEmit": true; React library: "jsx": "react-jsx").
    • Preserve project-specific settings (outDir, include, exclude, etc.).
  4. Delete the config package and remove it from all devDependencies.

Merging ESLint Config (Only When Root eslint.config Exists)

The config package centralizes ESLint plugin dependencies and exports composable flat configs.

  1. Read the config package — identify exported configs, plugin dependencies, and inheritance.
  2. Update root eslint.config.mjs — absorb base rules (JS recommended, TypeScript-ESLint, Prettier, etc.). Drop eslint-plugin-turbo.
  3. Update each project's eslint.config.mjs — switch from importing @repo/eslint-config/<variant> to extending the root config, adding framework-specific plugins inline.
  4. Move ESLint plugin dependencies from the config package to root devDependencies.
  5. If @nx/eslint plugin is configured with inferred targets, remove "lint" scripts from project package.json files.
  6. Delete the config package and remove it from all devDependencies.

General Cleanup

  • Remove turbo-specific dependencies: turbo, eslint-plugin-turbo.
  • Delete all turbo.json files (root and per-package).
  • Run workspace validation (nx run-many -t build lint test typecheck) to confirm nothing broke.

Key Pitfalls

  • Trace the full inheritance chain before inlining — check what each variant inherits from the base.
  • Module resolution changes — from Node package resolution (@repo/...) to relative paths (../../tsconfig.base.json).
  • ESLint configs are JavaScript, not JSON — handle JS imports, array spreading, and plugin objects when merging.

Helpful docs: