Labsco
nrwl logo

nx-import

โ˜… 25

by nrwl ยท part of nrwl/nx-ai-agents-config

๐Ÿ”Œ This skill ships inside the nx plugin โ€” install the plugin and you also get 1 sub-agents, an MCP server.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

Import Strategy

Subdirectory-at-a-time (nx import <source> apps --source=apps):

  • Recommended for monorepo sources โ€” files land at top level, no redundant config
  • Caveats: multiple import commands (separate merge commits each); dest must not have conflicting directories; root configs (deps, plugins, targetDefaults) not imported
  • Directory conflicts: Import into alternate-named dir (e.g. imported-apps/), then rename

Whole repo (nx import <source> imported --source=.):

  • Only for non-monorepo sources (single-project repos)
  • For monorepos, creates messy nested config (imported/nx.json, imported/tsconfig.base.json, etc.)
  • If you must: keep imported tsconfig.base.json (projects extend it), prefix workspace globs and executor paths

Directory Conventions

  • Always prefer the destination's existing conventions. Source uses libs/but dest uses packages/? Import into packages/ (nx import <source> packages/foo --source=libs/foo).
  • If dest has no convention (empty workspace), ask the user.

Application vs Library Detection

Before importing, identify whether the source is an application or a library:

  • Applications: Deployable end products. Common indicators:
    • Frontend: next.config.*, vite.config.* with a build entry point, framework-specific app scaffolding (CRA, Angular CLI app, etc.)
    • Backend (Node.js): Express/Fastify/NestJS server entrypoint, no "exports" field in package.json
    • JVM: Maven pom.xml with <packaging>jar</packaging> or <packaging>war</packaging> and a main class; Gradle application plugin or mainClass setting
    • .NET: .csproj/.fsproj with <OutputType>Exe</OutputType> or <OutputType>WinExe</OutputType>
    • General: Dockerfile, a runnable entrypoint, no public API surface intended for import by other projects
  • Libraries: Reusable packages consumed by other projects. Common indicators: "main"/"exports" in package.json, Maven/Gradle packaging as a library jar, .NET <OutputType>Library</OutputType>, named exports intended for import by other packages.

Destination directory rules:

  • Applications โ†’ apps/<name>. Check workspace globs (e.g. pnpm-workspace.yaml, workspaces in root package.json) for an existing apps/* entry.
    • If apps/* is not present, add it before importing: update the workspace glob config and commit (or stage) the change.
    • Example: nx import <source> apps/my-app --source=packages/my-app
  • Libraries โ†’ follow the dest's existing convention (packages/, libs/, etc.).

Non-Nx Source Issues

When the source is a plain pnpm/npm workspace without nx.json.

npm Script Rewriting (Critical)

Nx rewrites package.json scripts during init, creating broken commands (e.g. vitest run โ†’ nx test run). Fix: Remove all rewritten scripts โ€” Nx plugins infer targets from config files.

noEmit โ†’ composite + emitDeclarationOnly (Critical)

Plain TS projects use "noEmit": true, incompatible with Nx project references.

Symptoms: "typecheck target is disabled because one or more project references set 'noEmit: true'" or TS6310.

Fix in all imported tsconfigs:

  1. Remove "noEmit": true. If inherited via extends chain, set "noEmit": false explicitly.
  2. Add "composite": true, "emitDeclarationOnly": true, "declarationMap": true
  3. Add "outDir": "dist" and "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
  4. Add "extends": "../../tsconfig.base.json" if missing. Remove settings now inherited from base.

Stale node_modules and Lockfiles

nx import may bring node_modules/ (pnpm symlinks pointing to the source filesystem) and pnpm-lock.yaml from the source. Both are stale.

Fix: rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore, then pnpm install.

ESLint Config Handling

  • Legacy .eslintrc.json (ESLint 8): Delete all .eslintrc.*, remove v8 deps, create flat eslint.config.mjs.
  • Flat config (eslint.config.js): Self-contained configs can often be left as-is.
  • No ESLint: Create both root and project-level configs from scratch.

TypeScript paths Aliases

Nx uses package.json "exports" + pnpm workspace linking instead of tsconfig "paths". If packages have proper "exports", paths are redundant. Otherwise, update paths for the new directory structure.

Technology-specific Guidance

Identify technologies in the source repo, then read and apply the matching reference file(s).

Available references:

  • references/ESLINT.md โ€” ESLint projects: duplicate lint/eslint:lint targets, legacy .eslintrc.* linting generated files, flat config .cjs self-linting, typescript-eslint v7/v9 peer dep conflict, mixed ESLint v8+v9 in one workspace.
  • references/GRADLE.md
  • references/JEST.md โ€” Jest testing: @nx/jest/plugin setup, jest.preset.js, testing deps by framework, tsconfig.spec.json, Jest vs Vitest coexistence, Babel transforms, CI atomization.
  • references/NEXT.md โ€” Next.js projects: @nx/next/plugin targets, withNx, Next.js TS config (noEmit, jsx: "preserve"), auto-installing deps via wrong PM, non-Nx create-next-app imports, mixed Next.js+Vite coexistence.
  • references/TURBOREPO.md
  • references/VITE.md โ€” Vite projects (React, Vue, or both): @nx/vite/plugin typecheck target, resolve.alias/__dirname fixes, framework deps, Vue-specific setup, mixed React+Vue coexistence.