Implement project structure and documentation for Fog Expedition, including .mcp.json configuration, agent guidelines in AGENTS.md, and detailed project context in PROJECT_CONTEXT.md. Update .gitignore and pnpm-workspace.yaml for new dependencies and workspace management. Introduce CI monitoring skills and scripts for enhanced CI pipeline management.
This commit is contained in:
109
.agents/skills/nx-import/references/ESLINT.md
Normal file
109
.agents/skills/nx-import/references/ESLINT.md
Normal file
@@ -0,0 +1,109 @@
|
||||
## ESLint
|
||||
|
||||
ESLint-specific guidance for `nx import`. For generic import issues (root deps, pnpm globs, project references), see `SKILL.md`.
|
||||
|
||||
---
|
||||
|
||||
### How `@nx/eslint/plugin` Works
|
||||
|
||||
`@nx/eslint/plugin` scans for ESLint config files and creates a lint target for each project. It detects **both** flat config files (`eslint.config.{js,mjs,cjs,ts,mts,cts}`) and legacy config files (`.eslintrc.{json,js,cjs,mjs,yml,yaml}`).
|
||||
|
||||
**Plugin options (set during `nx add @nx/eslint`):**
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": "@nx/eslint/plugin",
|
||||
"options": {
|
||||
"targetName": "eslint:lint"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Auto-installation**: `nx import` auto-detects ESLint config files and offers to install `@nx/eslint`. Accept the offer — it registers the plugin and updates `namedInputs.production` to exclude ESLint config files.
|
||||
|
||||
---
|
||||
|
||||
### Duplicate `lint` and `eslint:lint` Targets
|
||||
|
||||
After import, projects will have **two** lint-related targets if the source `package.json` has a `"lint"` npm script:
|
||||
|
||||
- `eslint:lint` — inferred by `@nx/eslint/plugin`; has proper caching and input/output tracking
|
||||
- `lint` — created by Nx from the npm script via `nx:run-script`; no caching intelligence, just wraps `npm run lint`
|
||||
|
||||
**Fix**: Remove the `"lint"` script from each project's `package.json`. Keep `"lint:fix"` if present — there is no plugin-inferred equivalent for auto-fixing.
|
||||
|
||||
---
|
||||
|
||||
### Legacy `.eslintrc.*` Configs Linting Generated Files
|
||||
|
||||
When `@nx/eslint/plugin` runs `eslint .` on a project with a legacy `.eslintrc.*` config that uses `parserOptions.project`, it tries to lint **all** files in the project directory including:
|
||||
|
||||
- Generated `dist/**/*.d.ts` files (not in tsconfig `include`)
|
||||
- The `.eslintrc.js` config file itself (not in tsconfig `include`)
|
||||
|
||||
This causes `Parsing error: ESLint was configured to run on X using parserOptions.project, however that TSConfig does not include this file`.
|
||||
|
||||
**Fix**: Add `ignorePatterns` to the `.eslintrc.*` config:
|
||||
|
||||
```json
|
||||
// .eslintrc.json
|
||||
{
|
||||
"ignorePatterns": ["dist/**"]
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
// .eslintrc.js — also ignore the config file itself since module.exports isn't in tsconfig
|
||||
module.exports = {
|
||||
ignorePatterns: ['dist/**', '.eslintrc.js'],
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Flat Config `.cjs` Files Self-Linting
|
||||
|
||||
When a project uses `eslint.config.cjs` (CJS flat config), `eslint .` lints the config file itself. The `require()` call on line 1 triggers `@typescript-eslint/no-require-imports`.
|
||||
|
||||
**Fix**: Add the config filename to the top-level `ignores` array:
|
||||
|
||||
```js
|
||||
module.exports = tseslint.config(
|
||||
{
|
||||
ignores: ['dist/**', 'node_modules/**', 'eslint.config.cjs'],
|
||||
},
|
||||
// ...
|
||||
);
|
||||
```
|
||||
|
||||
The same applies to `eslint.config.js` in a CJS project (no `"type": "module"`) if it uses `require()`.
|
||||
|
||||
---
|
||||
|
||||
### `typescript-eslint` Version Conflict With ESLint 9
|
||||
|
||||
`typescript-eslint@7.x` declares `peerDependencies: { "eslint": "^8.56.0" }`, but it is commonly used alongside `"eslint": "^9.0.0"`. npm treats this as a hard peer dep conflict and refuses to install.
|
||||
|
||||
**Root cause**: `@nx/eslint` init adds `eslint@~8.57.0` at the workspace root (for its own peer deps). Workspace packages that request `eslint@^9.0.0` + `typescript-eslint@^7.0.0` trigger the conflict when npm resolves their deps.
|
||||
|
||||
**Fix**: Upgrade `typescript-eslint` from `^7.0.0` to `^8.0.0` directly in the affected workspace package's `package.json`. The `tseslint.config()` API and `tseslint.configs.recommended` are identical between v7 and v8 — no config changes needed.
|
||||
|
||||
```json
|
||||
// packages/my-package/package.json
|
||||
{
|
||||
"devDependencies": {
|
||||
"typescript-eslint": "^8.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: npm's root-level `"overrides"` field does not force versions for workspace packages' direct dependencies — update each package.json individually.
|
||||
|
||||
---
|
||||
|
||||
### Mixed ESLint v8 and v9 in One Workspace
|
||||
|
||||
Legacy v8 and flat-config v9 packages can coexist in the same workspace. Each package resolves its own `eslint` version. The root `eslint@~8.57.0` (added by `@nx/eslint` init) is used by legacy v8 packages; v9 packages get their own hoisted `eslint@9`.
|
||||
|
||||
`@nx/eslint/plugin` infers `eslint:lint` targets for **both** config formats. Legacy packages run ESLint v8 with `.eslintrc.*`; flat-config packages run ESLint v9 with `eslint.config.*`. No special nx.json configuration is needed to support both simultaneously.
|
||||
12
.agents/skills/nx-import/references/GRADLE.md
Normal file
12
.agents/skills/nx-import/references/GRADLE.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## Gradle
|
||||
|
||||
- If you import an entire Gradle repository into a subfolder, files like `gradlew`, `gradlew.bat`, and `gradle/wrapper` will end up inside that imported subfolder.
|
||||
- The `@nx/gradle` plugin expects those files at the workspace root to infer Gradle projects/tasks automatically.
|
||||
- If the target workspace has no Gradle setup yet, consider moving those files to the root (especially when using `@nx/gradle`).
|
||||
- If the target workspace already has Gradle configured, avoid duplicate wrappers: remove imported duplicates from the subfolder or merge carefully.
|
||||
- Because the import lands in a subfolder, Gradle project references can break; review settings and project path references, then fix any errors.
|
||||
- If `@nx/gradle` is installed, run `nx show projects` to verify that Gradle projects are being inferred.
|
||||
|
||||
Helpful docs:
|
||||
|
||||
- https://nx.dev/docs/technologies/java/gradle/introduction
|
||||
223
.agents/skills/nx-import/references/JEST.md
Normal file
223
.agents/skills/nx-import/references/JEST.md
Normal file
@@ -0,0 +1,223 @@
|
||||
## Jest
|
||||
|
||||
Jest-specific guidance for `nx import`. For the basic "Jest Preset Missing" fix (create `jest.preset.js`, install deps), see `SKILL.md`. This file covers deeper Jest integration issues.
|
||||
|
||||
---
|
||||
|
||||
### How `@nx/jest` Works
|
||||
|
||||
`@nx/jest/plugin` scans for `jest.config.{ts,js,cjs,mjs,cts,mts}` and creates a `test` target for each project.
|
||||
|
||||
**Plugin options:**
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": "@nx/jest/plugin",
|
||||
"options": {
|
||||
"targetName": "test"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`npx nx add @nx/jest` does two things:
|
||||
|
||||
1. **Registers `@nx/jest/plugin` in `nx.json`** — without this, no `test` targets are inferred
|
||||
2. Updates `namedInputs.production` to exclude test files
|
||||
|
||||
**Gotcha**: `nx add @nx/jest` does NOT create `jest.preset.js` — that file is only generated when you run a generator (e.g. `@nx/jest:configuration`). For imports, you must create it manually (see "Jest Preset" section below).
|
||||
|
||||
**Other gotcha**: If you create `jest.preset.js` manually but skip `npx nx add @nx/jest`, the plugin won't be registered and `nx run PROJECT:test` will fail with "Cannot find target 'test'". You need both.
|
||||
|
||||
---
|
||||
|
||||
### Jest Preset
|
||||
|
||||
The preset provides shared Jest configuration (test patterns, ts-jest transform, resolver, jsdom environment).
|
||||
|
||||
**Root `jest.preset.js`:**
|
||||
|
||||
```js
|
||||
const nxPreset = require('@nx/jest/preset').default;
|
||||
module.exports = { ...nxPreset };
|
||||
```
|
||||
|
||||
**Project `jest.config.ts`:**
|
||||
|
||||
```ts
|
||||
export default {
|
||||
displayName: 'my-lib',
|
||||
preset: '../../jest.preset.js',
|
||||
// project-specific overrides
|
||||
};
|
||||
```
|
||||
|
||||
The `preset` path is relative from the project root to the workspace root. Subdirectory imports preserve the original relative path (e.g. `../../jest.preset.js`), which resolves correctly if the import destination matches the source directory depth.
|
||||
|
||||
---
|
||||
|
||||
### Testing Dependencies
|
||||
|
||||
#### Core (always needed)
|
||||
|
||||
```
|
||||
pnpm add -wD jest ts-jest @types/jest @nx/jest
|
||||
```
|
||||
|
||||
#### Environment-specific
|
||||
|
||||
- **DOM testing** (React, Vue, browser libs): `jest-environment-jsdom`
|
||||
- **Node testing** (APIs, CLIs): no extra deps (Jest defaults to `node` env, but Nx preset defaults to `jsdom`)
|
||||
|
||||
#### React testing
|
||||
|
||||
```
|
||||
pnpm add -wD @testing-library/react @testing-library/jest-dom
|
||||
```
|
||||
|
||||
#### React with Babel (non-ts-jest transform)
|
||||
|
||||
Some React projects use Babel instead of ts-jest for JSX transformation:
|
||||
|
||||
```
|
||||
pnpm add -wD babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
|
||||
```
|
||||
|
||||
**When**: Project `jest.config` has `transform` using `babel-jest` instead of `ts-jest`. Common in older Nx workspaces and CRA migrations.
|
||||
|
||||
#### Vue testing
|
||||
|
||||
```
|
||||
pnpm add -wD @vue/test-utils
|
||||
```
|
||||
|
||||
Vue projects typically use Vitest (not Jest) — see VITE.md.
|
||||
|
||||
---
|
||||
|
||||
### `tsconfig.spec.json`
|
||||
|
||||
Jest projects need a `tsconfig.spec.json` that includes test files:
|
||||
|
||||
```json
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
**Common issues after import:**
|
||||
|
||||
- Missing `"types": ["jest", "node"]` — causes `describe`/`it`/`expect` to be unrecognized
|
||||
- Missing `"module": "commonjs"` — Jest doesn't support ESM by default (ts-jest transpiles to CJS)
|
||||
- `include` array missing test patterns — TypeScript won't check test files
|
||||
|
||||
---
|
||||
|
||||
### Jest vs Vitest Coexistence
|
||||
|
||||
Workspaces can have both:
|
||||
|
||||
- **Jest**: Next.js apps, older React libs, Node libraries
|
||||
- **Vitest**: Vite-based React/Vue apps and libs
|
||||
|
||||
Both `@nx/jest/plugin` and `@nx/vite/plugin` (which infers Vitest targets) coexist without conflicts — they detect different config files (`jest.config.*` vs `vite.config.*`).
|
||||
|
||||
**Target naming**: Both default to `test`. If a project somehow has both config files, rename one:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": "@nx/jest/plugin",
|
||||
"options": { "targetName": "jest-test" }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `@testing-library/jest-dom` — Jest vs Vitest
|
||||
|
||||
Projects migrating from Jest to Vitest (or workspaces with both) need different imports:
|
||||
|
||||
**Jest** (in `test-setup.ts`):
|
||||
|
||||
```ts
|
||||
import '@testing-library/jest-dom';
|
||||
```
|
||||
|
||||
**Vitest** (in `test-setup.ts`):
|
||||
|
||||
```ts
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
```
|
||||
|
||||
If the source used Jest but the dest workspace uses Vitest for that project type, update the import path. Also add `@testing-library/jest-dom` to tsconfig `types` array.
|
||||
|
||||
---
|
||||
|
||||
### Non-Nx Source: Test Script Rewriting
|
||||
|
||||
Nx rewrites `package.json` scripts during init. Test scripts get broken:
|
||||
|
||||
- `"test": "jest"` → `"test": "nx test"` (circular if no executor configured)
|
||||
- `"test": "vitest run"` → `"test": "nx test run"` (broken — `run` becomes an argument)
|
||||
|
||||
**Fix**: Remove all rewritten test scripts. `@nx/jest/plugin` and `@nx/vite/plugin` infer test targets from config files.
|
||||
|
||||
---
|
||||
|
||||
### CI Atomization
|
||||
|
||||
`@nx/jest/plugin` supports splitting tests per-file for CI parallelism:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": "@nx/jest/plugin",
|
||||
"options": {
|
||||
"targetName": "test",
|
||||
"ciTargetName": "test-ci"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This creates `test-ci--src/lib/foo.spec.ts` targets for each test file, enabling Nx Cloud distribution. Not relevant during import, but useful for post-import CI setup.
|
||||
|
||||
---
|
||||
|
||||
### Common Post-Import Issues
|
||||
|
||||
1. **"Cannot find target 'test'"**: `@nx/jest/plugin` not registered in `nx.json`. Run `npx nx add @nx/jest` or manually add the plugin entry.
|
||||
|
||||
2. **"Cannot find module 'jest-preset'"**: `jest.preset.js` missing at workspace root. Create it (see SKILL.md).
|
||||
|
||||
3. **"Cannot find type definition file for 'jest'"**: Missing `@types/jest` or `tsconfig.spec.json` doesn't have `"types": ["jest", "node"]`.
|
||||
|
||||
4. **Tests fail with "Cannot use import statement outside a module"**: `ts-jest` not installed or not configured as transform. Check `jest.config.ts` transform section.
|
||||
|
||||
5. **Snapshot path mismatches**: After import, `__snapshots__` directories may have paths baked in. Run tests once with `--updateSnapshot` to regenerate.
|
||||
|
||||
---
|
||||
|
||||
## Fix Order
|
||||
|
||||
### Subdirectory Import (Nx Source)
|
||||
|
||||
1. `npx nx add @nx/jest` — registers plugin in `nx.json` (does NOT create `jest.preset.js`)
|
||||
2. Create `jest.preset.js` manually (see "Jest Preset" section above)
|
||||
3. Install deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`
|
||||
4. Install framework test deps: `@testing-library/react @testing-library/jest-dom` (React), `@vue/test-utils` (Vue)
|
||||
5. Verify `tsconfig.spec.json` has `"types": ["jest", "node"]`
|
||||
6. `nx run-many -t test`
|
||||
|
||||
### Whole-Repo Import (Non-Nx Source)
|
||||
|
||||
1. Remove rewritten test scripts from `package.json`
|
||||
2. `npx nx add @nx/jest` — registers plugin (does NOT create preset)
|
||||
3. Create `jest.preset.js` manually
|
||||
4. Install deps (same as above)
|
||||
5. Verify/fix `jest.config.*` — ensure `preset` path points to root `jest.preset.js`
|
||||
6. Verify/fix `tsconfig.spec.json` — add `types`, `module`, `include` if missing
|
||||
7. `nx run-many -t test`
|
||||
214
.agents/skills/nx-import/references/NEXT.md
Normal file
214
.agents/skills/nx-import/references/NEXT.md
Normal file
@@ -0,0 +1,214 @@
|
||||
## Next.js
|
||||
|
||||
Next.js-specific guidance for `nx import`. For generic import issues (pnpm globs, root deps, project references, name collisions, ESLint, frontend tsconfig base settings, `@nx/react` typings, Jest preset, target name prefixing, non-Nx source handling), see `SKILL.md`.
|
||||
|
||||
---
|
||||
|
||||
### `@nx/next/plugin` Inferred Targets
|
||||
|
||||
`@nx/next/plugin` detects `next.config.{ts,js,cjs,mjs}` and creates these targets:
|
||||
|
||||
- `build` → `next build` (with `dependsOn: ['^build']`)
|
||||
- `dev` → `next dev`
|
||||
- `start` → `next start` (depends on `build`)
|
||||
- `serve-static` → same as `start`
|
||||
- `build-deps` / `watch-deps` — for TS solution setup
|
||||
|
||||
**No separate typecheck target** — Next.js runs TypeScript checking as part of `next build`. The `@nx/js/typescript` plugin provides a standalone `typecheck` target for non-Next libraries in the workspace.
|
||||
|
||||
**Build target conflict**: Both `@nx/next/plugin` and `@nx/js/typescript` define a `build` target. `@nx/next/plugin` wins for Next.js projects (it detects `next.config.*`), while `@nx/js/typescript` handles libraries with `tsconfig.lib.json`. No rename needed — they coexist.
|
||||
|
||||
### `withNx` in `next.config.js`
|
||||
|
||||
Nx-generated Next.js projects use `composePlugins(withNx)` from `@nx/next`. This wrapper is optional for `next build` via the inferred plugin (which just runs `next build`), but it provides Nx-specific configuration. Keep it if present.
|
||||
|
||||
### Root Dependencies for Next.js
|
||||
|
||||
Beyond the generic root deps issue (see SKILL.md), Next.js projects typically need:
|
||||
|
||||
**Core**: `react`, `react-dom`, `@types/react`, `@types/react-dom`, `@types/node`, `@nx/react` (see SKILL.md for `@nx/react` typings)
|
||||
**Nx plugins**: `@nx/next` (auto-installed by import), `@nx/eslint`, `@nx/jest`
|
||||
**Testing**: see SKILL.md "Jest Preset Missing" section
|
||||
**ESLint**: `@next/eslint-plugin-next` (in addition to generic ESLint deps from SKILL.md)
|
||||
|
||||
### Next.js Auto-Installing Dependencies via Wrong Package Manager
|
||||
|
||||
Next.js detects missing `@types/react` during `next build` and tries to install it using `yarn add` regardless of the actual package manager. In a pnpm workspace, this fails with a "nearest package directory isn't part of the project" error.
|
||||
|
||||
**Root cause**: `@types/react` is missing from root devDependencies.
|
||||
**Fix**: Install deps at the root before building: `pnpm add -wD @types/react @types/react-dom`
|
||||
|
||||
### Next.js TypeScript Config Specifics
|
||||
|
||||
Next.js app tsconfigs have unique patterns compared to Vite:
|
||||
|
||||
- **`noEmit: true`** with `emitDeclarationOnly: false` — Next.js handles emit, TS just checks types. This conflicts with `composite: true` from the TS solution setup.
|
||||
- **`"types": ["jest", "node"]`** — includes test types in the main tsconfig (no separate `tsconfig.app.json`)
|
||||
- **`"plugins": [{ "name": "next" }]`** — for IDE integration
|
||||
- **`include`** references `.next/types/**/*.ts` for Next.js auto-generated types
|
||||
- **`"jsx": "preserve"`** — Next.js uses its own JSX transform, not React's
|
||||
|
||||
**Gotcha**: The Next.js tsconfig sets `"noEmit": true` which disables `composite` mode. This is fine because Next.js projects use `next build` for building, not `tsc`. The `@nx/js/typescript` plugin's `typecheck` target is not needed for Next.js apps.
|
||||
|
||||
### `next.config.js` Lint Warning
|
||||
|
||||
Imported Next.js configs may have `// eslint-disable-next-line @typescript-eslint/no-var-requires` but the project ESLint config enables different rule sets. This produces `Unused eslint-disable directive` warnings. Harmless — remove the comment or ignore.
|
||||
|
||||
### `@nx/next:init` Rewrites All npm Scripts (Whole-Repo Import)
|
||||
|
||||
When `@nx/next:init` runs during a whole-repo import, it rewrites the project's `package.json` scripts to prefixed `nx` calls:
|
||||
|
||||
```json
|
||||
{
|
||||
"dev": "nx next:dev",
|
||||
"build": "nx next:build",
|
||||
"start": "nx next:start"
|
||||
}
|
||||
```
|
||||
|
||||
This is the standard "npm Script Rewriting" issue from SKILL.md, but triggered by `@nx/next:init` rather than Nx init. **Fix**: Remove all rewritten scripts from `package.json` — `@nx/next/plugin` infers all targets from `next.config.*`.
|
||||
|
||||
---
|
||||
|
||||
## Non-Nx Source (create-next-app)
|
||||
|
||||
### Whole-Repo Import Recommended
|
||||
|
||||
For single-project `create-next-app` repos, use whole-repo import into a subdirectory:
|
||||
|
||||
```bash
|
||||
nx import /path/to/source apps/web --ref=main --source=. --no-interactive
|
||||
```
|
||||
|
||||
### `next-env.d.ts`
|
||||
|
||||
`next build` auto-generates `next-env.d.ts` at the project root. Add `next-env.d.ts` to the dest root `.gitignore` — it is framework-generated and should not be committed.
|
||||
|
||||
### ESLint: Self-Contained `eslint-config-next`
|
||||
|
||||
`create-next-app` generates a flat ESLint config using `eslint-config-next` (which bundles its own plugins). This is **self-contained** — no root `eslint.config.mjs` needed, no `@nx/eslint-plugin` dependency. The `@nx/eslint/plugin` detects it and creates a lint target.
|
||||
|
||||
### TypeScript: No Changes Needed
|
||||
|
||||
Non-Nx Next.js projects have self-contained tsconfigs with `noEmit: true`, their own `lib`, `module`, `moduleResolution`, and `jsx` settings. Since `next build` handles type checking internally, no tsconfig modifications are needed. The project does NOT need to extend `tsconfig.base.json`.
|
||||
|
||||
**Gotcha**: The `@nx/js/typescript` plugin won't create a `typecheck` target because there's no `tsconfig.lib.json`. This is fine — use `next:build` for type checking.
|
||||
|
||||
### `noEmit: true` and TS Solution Setup
|
||||
|
||||
Non-Nx Next.js projects use `noEmit: true`, which conflicts with Nx's TS solution setup (`composite: true`). If the dest workspace uses project references and you want the Next.js app to participate:
|
||||
|
||||
1. Remove `noEmit: true`, add `composite: true`, `emitDeclarationOnly: true`
|
||||
2. Add `extends: "../../tsconfig.base.json"`
|
||||
3. Add `outDir` and `tsBuildInfoFile`
|
||||
|
||||
**However**, this is optional for standalone Next.js apps that don't export types consumed by other workspace projects.
|
||||
|
||||
### Tailwind / PostCSS
|
||||
|
||||
`create-next-app` with Tailwind generates `postcss.config.mjs`. This works as-is after import — no path changes needed since PostCSS resolves relative to the project root.
|
||||
|
||||
---
|
||||
|
||||
## Mixed Next.js + Vite Coexistence
|
||||
|
||||
When both Next.js and Vite projects exist in the same workspace.
|
||||
|
||||
### Plugin Coexistence
|
||||
|
||||
Both `@nx/next/plugin` and `@nx/vite/plugin` can coexist in `nx.json`. They detect different config files (`next.config.*` vs `vite.config.*`) so there are no conflicts. The `@nx/js/typescript` plugin handles libraries.
|
||||
|
||||
### Vite Standalone Project tsconfig Fixes
|
||||
|
||||
Vite standalone projects (imported as whole-repo) have self-contained tsconfigs without `composite: true`. The `@nx/js/typescript` plugin's typecheck target runs `tsc --build --emitDeclarationOnly` which requires `composite`.
|
||||
|
||||
**Fix**:
|
||||
|
||||
1. Add `extends: "../../tsconfig.base.json"` to the root project tsconfig
|
||||
2. Add `composite: true`, `declaration: true`, `declarationMap: true`, `tsBuildInfoFile` to `tsconfig.app.json` and `tsconfig.spec.json`
|
||||
3. Set `moduleResolution: "bundler"` (replace `"node"`)
|
||||
4. Add source files to `tsconfig.spec.json` `include` — specs import app code, and `composite` mode requires all files to be listed
|
||||
|
||||
### Typecheck Target Names
|
||||
|
||||
- `@nx/vite/plugin` defaults `typecheckTargetName` to `"vite:typecheck"`
|
||||
- `@nx/js/typescript` uses `"typecheck"`
|
||||
- Next.js projects have NO standalone typecheck target — Next.js runs type checking during `next build`
|
||||
|
||||
No naming conflicts between frameworks.
|
||||
|
||||
---
|
||||
|
||||
## Fix Order — Nx Source (Subdirectory Import)
|
||||
|
||||
1. Import Next.js apps into `apps/<name>` (see SKILL.md: "Application vs Library Detection")
|
||||
2. Generic fixes from SKILL.md (pnpm globs, root deps, `.gitkeep` removal, frontend tsconfig base settings, `@nx/react` typings)
|
||||
3. Install Next.js-specific deps: `pnpm add -wD @next/eslint-plugin-next`
|
||||
4. ESLint setup (see SKILL.md: "Root ESLint Config Missing")
|
||||
5. Jest setup (see SKILL.md: "Jest Preset Missing")
|
||||
6. `nx reset && nx sync --yes && nx run-many -t typecheck,build,test,lint`
|
||||
|
||||
## Fix Order — Non-Nx Source (create-next-app)
|
||||
|
||||
1. Import into `apps/<name>` (see SKILL.md: "Application vs Library Detection")
|
||||
2. Generic fixes from SKILL.md (pnpm globs, stale files cleanup, script rewriting, target name prefixing)
|
||||
3. (Optional) If app needs to export types for other workspace projects: fix `noEmit` → `composite` (see SKILL.md)
|
||||
4. `nx reset && nx run-many -t next:build,eslint:lint` (or unprefixed names if renamed)
|
||||
|
||||
---
|
||||
|
||||
## Iteration Log
|
||||
|
||||
### Scenario 1: Basic Nx Next.js App Router + Shared Lib → TS preset (PASS)
|
||||
|
||||
- Source: CNW next preset (Next.js 16, App Router) + `@nx/react:library` shared-ui
|
||||
- Dest: CNW ts preset (Nx 23)
|
||||
- Import: subdirectory-at-a-time (apps, libs separately)
|
||||
- Errors found & fixed:
|
||||
1. pnpm-workspace.yaml: `apps`/`libs` → `apps/*`/`libs/*`
|
||||
2. Root tsconfig: `nodenext` → `bundler`, add `dom`/`dom.iterable` to `lib`, add `jsx: react-jsx`
|
||||
3. Missing `@nx/react` (for CSS module/image type defs in lib)
|
||||
4. Missing `@types/react`, `@types/react-dom`, `@types/node`
|
||||
5. Next.js trying `yarn add @types/react` — fixed by installing at root
|
||||
6. Missing `@nx/eslint`, root `eslint.config.mjs`, ESLint plugins
|
||||
7. Missing `@nx/jest`, `jest.preset.js`, `jest-environment-jsdom`, `ts-jest`
|
||||
- All targets green: typecheck, build, test, lint
|
||||
|
||||
### Scenario 3: Non-Nx create-next-app (App Router + Tailwind) → TS preset (PASS)
|
||||
|
||||
- Source: `create-next-app@latest` (Next.js 16.1.6, App Router, Tailwind v4, flat ESLint config)
|
||||
- Dest: CNW ts preset (Nx 23)
|
||||
- Import: whole-repo into `apps/web`
|
||||
- Errors found & fixed:
|
||||
1. pnpm-workspace.yaml: `apps/web` → `apps/*`
|
||||
2. Stale files: `node_modules/`, `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `.gitignore` — deleted
|
||||
3. Nx-rewritten npm scripts (`"build": "nx next:build"`, etc.) — removed
|
||||
- No tsconfig changes needed — self-contained config with `noEmit: true`
|
||||
- ESLint self-contained via `eslint-config-next` — no root config needed
|
||||
- No test setup (create-next-app doesn't include tests)
|
||||
- All targets green: next:build, eslint:lint
|
||||
|
||||
### Scenario 4: Non-Nx create-next-app (alongside Vite, React Router 7, TanStack, CRA) → TS preset (PASS)
|
||||
|
||||
- See VITE.md Scenario 6 for the full multi-import scenario
|
||||
- Next.js-specific findings:
|
||||
1. `@nx/next:init` rewrote all scripts to `nx next:*` format — removed all rewritten scripts
|
||||
2. Stale files: `node_modules/`, `package-lock.json`, `.gitignore` — deleted (npm workspace, no pnpm files)
|
||||
3. ESLint self-contained via `eslint-config-next` — no root config needed
|
||||
4. No tsconfig changes needed — `noEmit: true` stays; `next build` handles type checking
|
||||
- Targets: `next:build`, `next:dev`, `next:start`, `eslint:lint`
|
||||
|
||||
### Scenario 5: Mixed Next.js (Nx) + Vite React (standalone) → TS preset (PASS)
|
||||
|
||||
- Source A: CNW next preset (Next.js 16, App Router) — subdirectory import of `apps/`
|
||||
- Source B: CNW react-standalone preset (Vite 7, React 19) — whole-repo import into `apps/vite-app`
|
||||
- Dest: CNW ts preset (Nx 23)
|
||||
- Errors found & fixed:
|
||||
1. All Scenario 1 fixes for the Next.js app
|
||||
2. Stale files from Vite source: `node_modules/`, `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `.gitignore`, `nx.json`
|
||||
3. Removed rewritten scripts from Vite app's `package.json`
|
||||
4. ESLint 8 vs 9 conflict — `@nx/eslint` peer on ESLint 8 resolved wrong version. Fixed with `pnpm.overrides`
|
||||
5. Vite tsconfigs missing `composite: true`, `declaration: true` — needed for `tsc --build --emitDeclarationOnly`
|
||||
6. Vite `tsconfig.spec.json` `include` missing source files — specs import app code
|
||||
7. Vite tsconfig `moduleResolution: "node"` → `"bundler"`, added `extends: "../../tsconfig.base.json"`
|
||||
- All targets green: typecheck, build, test, lint for both projects
|
||||
62
.agents/skills/nx-import/references/TURBOREPO.md
Normal file
62
.agents/skills/nx-import/references/TURBOREPO.md
Normal file
@@ -0,0 +1,62 @@
|
||||
## Turborepo
|
||||
|
||||
- Nx replaces Turborepo task orchestration, but a clean migration requires handling Turborepo's config packages.
|
||||
- Migration guide: https://nx.dev/docs/guides/adopting-nx/from-turborepo#easy-automated-migration-example
|
||||
- Since Nx replaces Turborepo, all turbo config files and config packages become dead code and should be removed.
|
||||
|
||||
## 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:
|
||||
|
||||
- https://nx.dev/docs/guides/adopting-nx/from-turborepo
|
||||
393
.agents/skills/nx-import/references/VITE.md
Normal file
393
.agents/skills/nx-import/references/VITE.md
Normal file
@@ -0,0 +1,393 @@
|
||||
## Vite
|
||||
|
||||
Vite-specific guidance for `nx import`. For generic import issues (pnpm globs, root deps, project references, name collisions, ESLint, frontend tsconfig base settings, `@nx/react` typings, Jest preset, non-Nx source handling), see `SKILL.md`.
|
||||
|
||||
---
|
||||
|
||||
### `@nx/vite/plugin` Typecheck Target
|
||||
|
||||
`@nx/vite/plugin` defaults `typecheckTargetName` to `"vite:typecheck"`. If the workspace expects `"typecheck"`, set it explicitly in `nx.json`. If `@nx/js/typescript` is also registered, rename one target to avoid conflicts (e.g. `"tsc-typecheck"` for the JS plugin).
|
||||
|
||||
Keep both plugins only if the workspace has non-Vite pure TS libraries — `@nx/js/typescript` handles those while `@nx/vite/plugin` handles Vite projects.
|
||||
|
||||
### @nx/vite Plugin Install Failure
|
||||
|
||||
Plugin init loads `vite.config.ts` before deps are available. **Fix**: `pnpm add -wD vite @vitejs/plugin-react` (or `@vitejs/plugin-vue`) first, then `pnpm exec nx add @nx/vite`.
|
||||
|
||||
### Vite `resolve.alias` and `__dirname` (Non-Nx Sources)
|
||||
|
||||
**`__dirname` undefined** (CJS-only): Replace with `fileURLToPath(new URL('./src', import.meta.url))` from `'node:url'`.
|
||||
|
||||
**`@/` path alias**: Vite's `resolve.alias` works at runtime but TS needs matching `"paths"`. Set `"baseUrl": "."` in project tsconfig.
|
||||
|
||||
**PostCSS/Tailwind**: Verify `content` globs resolve correctly after import.
|
||||
|
||||
### Missing TypeScript `types` (Non-Nx Sources)
|
||||
|
||||
Non-Nx tsconfigs may not declare all needed types. Ensure Vite projects include `"types": ["node", "vite/client"]` in their tsconfig.
|
||||
|
||||
### `noEmit` Fix: Vite-Specific Notes
|
||||
|
||||
See SKILL.md for the generic noEmit→composite fix. Vite-specific additions:
|
||||
|
||||
- Non-Nx Vite projects often have **both** `tsconfig.app.json` and `tsconfig.node.json` with `noEmit` — fix both
|
||||
- Solution-style tsconfigs (`"files": [], "references": [...]`) may lack `extends`. Add `extends` pointing to the dest root `tsconfig.base.json` so base settings (`moduleResolution`, `lib`) apply.
|
||||
- This is safe — Vite/Vitest ignore TypeScript emit settings.
|
||||
|
||||
### Dependency Version Conflicts
|
||||
|
||||
**Shared Vite deps (both frameworks):** `vite`, `vitest`, `jsdom`, `@types/node`, `typescript` (dev)
|
||||
|
||||
**Vite 6→7**: Typecheck fails (`Plugin<any>` type mismatch); build/serve still works. Fix: align versions.
|
||||
**Vitest 3→4**: Usually works; type conflicts may surface in shared test utils.
|
||||
|
||||
---
|
||||
|
||||
## React Router 7 (Vite-Based)
|
||||
|
||||
React Router 7 (`@react-router/dev`) uses Vite under the hood with a `vite.config.ts` and a `react-router.config.ts`. The `@nx/vite/plugin` detects `vite.config.ts` and creates inferred targets.
|
||||
|
||||
### Targets
|
||||
|
||||
`@nx/vite/plugin` creates `build`, `dev`, `serve` targets. The `build` target invokes the script defined in `package.json` (usually `react-router build`), not `vite build` directly.
|
||||
|
||||
**No separate typecheck target from `@nx/vite/plugin`** — React Router 7 typegen is run as part of `typecheck` (e.g. `react-router typegen && tsc`). The `typecheck` target is inferred from the tsconfig. Keep the `typecheck` script in `package.json` if present; it is not rewritten.
|
||||
|
||||
### tsconfig Notes
|
||||
|
||||
React Router 7 uses a single `tsconfig.json` (no `tsconfig.app.json`/`tsconfig.node.json` split). It includes:
|
||||
|
||||
- `"rootDirs": [".", "./.react-router/types"]` — for generated type files; keep as-is
|
||||
- `"paths": { "~/*": ["./app/*"] }` — self-referential alias; keep as-is
|
||||
- `"noEmit": true` — replace with composite settings per SKILL.md
|
||||
|
||||
### Build Output
|
||||
|
||||
React Router 7 outputs to `build/` (not `dist/`). Add `build` to the dest root `.gitignore`.
|
||||
|
||||
### Generated Types Directory
|
||||
|
||||
React Router 7 generates `.react-router/` at the project root for route type generation. Add `.react-router` to the dest root `.gitignore`.
|
||||
|
||||
---
|
||||
|
||||
## TanStack Start (Vite-Based)
|
||||
|
||||
TanStack Start uses Vinxi under the hood, which wraps Vite. Projects have a standard `vite.config.ts` that `@nx/vite/plugin` detects normally.
|
||||
|
||||
### Targets
|
||||
|
||||
`@nx/vite/plugin` creates `build`, `dev`, `preview`, `serve-static`, `typecheck` targets. The `build` target runs `vite build` which invokes the TanStack Start Vinxi pipeline (produces both client and SSR bundles).
|
||||
|
||||
### tsconfig Notes
|
||||
|
||||
TanStack Start uses a single `tsconfig.json` with `"allowImportingTsExtensions": true` and `"noEmit": true`. Apply the standard noEmit → composite fix. `allowImportingTsExtensions` is compatible with `emitDeclarationOnly: true` — no change needed.
|
||||
|
||||
### `paths` Aliases
|
||||
|
||||
TanStack Start commonly uses `"#/*": ["./src/*"]` and `"@/*": ["./src/*"]`. These are self-referential — keep as-is for a single-project app.
|
||||
|
||||
### Uncommitted Source Repo
|
||||
|
||||
`create-tan-stack` initializes a git repo but does NOT make an initial commit. Before importing, commit first:
|
||||
|
||||
```bash
|
||||
git -C /path/to/source add . && git -C /path/to/source commit -m "Initial commit"
|
||||
```
|
||||
|
||||
### Generated and Build Directories
|
||||
|
||||
TanStack Start / Vinxi / Nitro generate several directories that must be added to the dest root `.gitignore`:
|
||||
|
||||
- `.vinxi` — Vinxi build cache
|
||||
- `.tanstack` — TanStack generated files
|
||||
- `.nitro` — Nitro build artifacts
|
||||
- `.output` — server-side build output (SSR/edge)
|
||||
|
||||
These are not covered by `dist` or `build`.
|
||||
|
||||
---
|
||||
|
||||
## React-Specific
|
||||
|
||||
### React Dependencies
|
||||
|
||||
**Production:** `react`, `react-dom`
|
||||
**Dev:** `@types/react`, `@types/react-dom`, `@vitejs/plugin-react`, `@testing-library/react`, `@testing-library/jest-dom`, `jsdom`
|
||||
**ESLint (Nx sources):** `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`
|
||||
**ESLint (`create-vite`):** `eslint-plugin-react-refresh`, `eslint-plugin-react-hooks` — self-contained flat configs can be left as-is
|
||||
**Nx plugins:** `@nx/react` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint`
|
||||
|
||||
### React TypeScript Configuration
|
||||
|
||||
Add `"jsx": "react-jsx"` — in `tsconfig.base.json` for single-framework workspaces, per-project for mixed (see Mixed section).
|
||||
|
||||
### React ESLint Config
|
||||
|
||||
```js
|
||||
import nx from '@nx/eslint-plugin';
|
||||
import baseConfig from '../../eslint.config.mjs';
|
||||
export default [...baseConfig, ...nx.configs['flat/react'], { files: ['**/*.ts', '**/*.tsx'], rules: {} }];
|
||||
```
|
||||
|
||||
### React Version Conflicts
|
||||
|
||||
React 18 (source) + React 19 (dest): pnpm may hoist mismatched `react-dom`, causing `TypeError: Cannot read properties of undefined (reading 'S')`. **Fix**: Align versions with `pnpm.overrides`.
|
||||
|
||||
### `@testing-library/jest-dom` with Vitest
|
||||
|
||||
If source used Jest: change import to `@testing-library/jest-dom/vitest` in test-setup.ts, add to tsconfig `types`.
|
||||
|
||||
---
|
||||
|
||||
## Vue-Specific
|
||||
|
||||
### Vue Dependencies
|
||||
|
||||
**Production:** `vue` (plus `vue-router`, `pinia` if used)
|
||||
**Dev:** `@vitejs/plugin-vue`, `vue-tsc`, `@vue/test-utils`, `jsdom`
|
||||
**ESLint:** `eslint-plugin-vue`, `vue-eslint-parser`, `@vue/eslint-config-typescript`, `@vue/eslint-config-prettier`
|
||||
**Nx plugins:** `@nx/vue` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint` (install AFTER deps — see below)
|
||||
|
||||
### Vue TypeScript Configuration
|
||||
|
||||
Add to `tsconfig.base.json` (single-framework) or per-project (mixed):
|
||||
|
||||
```json
|
||||
{ "jsx": "preserve", "jsxImportSource": "vue", "resolveJsonModule": true }
|
||||
```
|
||||
|
||||
### `vue-shims.d.ts`
|
||||
|
||||
Vue SFC files need a type declaration. Usually exists in each project's `src/` and imports cleanly. If missing:
|
||||
|
||||
```ts
|
||||
declare module '*.vue' {
|
||||
import { defineComponent } from 'vue';
|
||||
const component: ReturnType<typeof defineComponent>;
|
||||
export default component;
|
||||
}
|
||||
```
|
||||
|
||||
### `vue-tsc` Auto-Detection
|
||||
|
||||
Both `@nx/js/typescript` and `@nx/vite/plugin` auto-detect `vue-tsc` when installed — no manual config needed. Remove source scripts like `"typecheck": "vue-tsc --noEmit"`.
|
||||
|
||||
### ESLint Plugin Installation Order (Critical)
|
||||
|
||||
`@nx/eslint` init **crashes** if Vue ESLint deps aren't installed first (it loads all config files).
|
||||
|
||||
**Correct order:**
|
||||
|
||||
1. `pnpm add -wD eslint@^9 eslint-plugin-vue vue-eslint-parser @vue/eslint-config-typescript @typescript-eslint/parser @nx/eslint-plugin typescript-eslint`
|
||||
2. Create root `eslint.config.mjs`
|
||||
3. Then `npx nx add @nx/eslint`
|
||||
|
||||
### Vue ESLint Config Pattern
|
||||
|
||||
```js
|
||||
import vue from 'eslint-plugin-vue';
|
||||
import vueParser from 'vue-eslint-parser';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
import baseConfig from '../../eslint.config.mjs';
|
||||
export default [
|
||||
...baseConfig,
|
||||
...vue.configs['flat/recommended'],
|
||||
{
|
||||
files: ['**/*.vue'],
|
||||
languageOptions: { parser: vueParser, parserOptions: { parser: tsParser } },
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],
|
||||
rules: { 'vue/multi-word-component-names': 'off' },
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
**Important**: `vue-eslint-parser` override must come **AFTER** base config — `flat/typescript` sets the TS parser globally without a `files` filter, breaking `.vue` parsing.
|
||||
|
||||
`vue-eslint-parser` must be an explicit pnpm dependency (strict resolution prevents transitive import).
|
||||
|
||||
**Known issue**: Some generated Vue ESLint configs omit `vue-eslint-parser`. Use the pattern above instead.
|
||||
|
||||
---
|
||||
|
||||
## Mixed React + Vue
|
||||
|
||||
When both frameworks coexist, several settings become per-project.
|
||||
|
||||
### tsconfig `jsx` — Per-Project Only
|
||||
|
||||
- React: `"jsx": "react-jsx"` in project tsconfig
|
||||
- Vue: `"jsx": "preserve"`, `"jsxImportSource": "vue"` in project tsconfig
|
||||
- Root: **NO** `jsx` setting
|
||||
|
||||
### Typecheck — Auto-Detects Framework
|
||||
|
||||
`@nx/vite/plugin` uses `vue-tsc` for Vue projects and `tsc` for React automatically.
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": [
|
||||
{ "plugin": "@nx/eslint/plugin", "options": { "targetName": "lint" } },
|
||||
{
|
||||
"plugin": "@nx/vite/plugin",
|
||||
"options": {
|
||||
"buildTargetName": "build",
|
||||
"typecheckTargetName": "typecheck",
|
||||
"testTargetName": "test"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Remove `@nx/js/typescript` if all projects use Vite. Keep it (renamed to `"tsc-typecheck"`) only for non-Vite pure TS libs.
|
||||
|
||||
### ESLint — Three-Tier Config
|
||||
|
||||
1. **Root**: Base rules only, no framework-specific rules
|
||||
2. **React projects**: Extend root + `nx.configs['flat/react']`
|
||||
3. **Vue projects**: Extend root + `vue.configs['flat/recommended']` + `vue-eslint-parser`
|
||||
|
||||
**Required packages**: Shared (`eslint@^9`, `@nx/eslint-plugin`, `typescript-eslint`, `@typescript-eslint/parser`), React (`eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`), Vue (`eslint-plugin-vue`, `vue-eslint-parser`)
|
||||
|
||||
`@nx/react`/`@nx/vue` are for generators only — no target conflicts.
|
||||
|
||||
---
|
||||
|
||||
## Redundant npm Scripts After Import
|
||||
|
||||
`nx import` copies `package.json` verbatim, so npm scripts come along. For Vite-based projects `@nx/vite/plugin` already infers the same targets from `vite.config.ts` — the npm scripts just shadow the plugin with weaker `nx:run-script` wrappers (no first-class caching inputs/outputs). Remove them after import.
|
||||
|
||||
### Standalone Vite App (`create-vite`)
|
||||
|
||||
Remove the following scripts — every one is redundant:
|
||||
|
||||
| Script | Plugin replacement |
|
||||
| ----------------------------- | ---------------------------------------------------------------------------- |
|
||||
| `dev: vite` | `@nx/vite/plugin` → `dev` |
|
||||
| `build: tsc -b && vite build` | `@nx/vite/plugin` → `build`; `typecheck` via `@nx/js/typescript` handles tsc |
|
||||
| `preview: vite preview` | `@nx/vite/plugin` → `preview` |
|
||||
| `lint: eslint .` | `@nx/eslint/plugin` → `eslint:lint` |
|
||||
|
||||
### TanStack Start
|
||||
|
||||
Remove `build`, `dev`, `preview`, and `test` scripts, but move any hardcoded `--port` flag to `vite.config.ts` first:
|
||||
|
||||
```ts
|
||||
// vite.config.ts
|
||||
export default defineConfig({
|
||||
server: { port: 3000 }, // replaces `vite dev --port 3000`
|
||||
...
|
||||
})
|
||||
```
|
||||
|
||||
### React Router 7 — Keep ALL scripts
|
||||
|
||||
Do **not** remove React Router 7 scripts. They use the framework CLI (`react-router build`, `react-router dev`, `react-router-serve`) which is not interchangeable with plain `vite`:
|
||||
|
||||
- `typecheck` runs `react-router typegen && tsc` — typegen must precede `tsc` or it fails on missing route types
|
||||
- `start` serves the SSR bundle — no plugin equivalent
|
||||
|
||||
---
|
||||
|
||||
## Fix Orders
|
||||
|
||||
### Nx Source
|
||||
|
||||
1. Generic fixes from SKILL.md (pnpm globs, root deps, executor paths, frontend tsconfig base settings, `@nx/react` typings)
|
||||
2. Configure `@nx/vite/plugin` typecheck target
|
||||
3. **React**: `jsx: "react-jsx"` (root or per-project)
|
||||
4. **Vue**: `jsx: "preserve"` + `jsxImportSource: "vue"`; verify `vue-shims.d.ts`; install ESLint deps before `@nx/eslint`
|
||||
5. **Mixed**: `jsx` per-project; remove/rename `@nx/js/typescript`
|
||||
6. `nx sync --yes && nx reset && nx run-many -t typecheck,build,test,lint`
|
||||
|
||||
### Non-Nx Source (additional steps)
|
||||
|
||||
0. Import into `apps/<name>` (see SKILL.md: "Application vs Library Detection")
|
||||
1. Generic fixes from SKILL.md (stale files cleanup, pnpm globs, rewritten scripts, target name prefixing, noEmit→composite, ESLint handling)
|
||||
2. Fix `noEmit` in **all** tsconfigs (app, node, etc. — non-Nx projects often have multiple)
|
||||
3. Add `extends` to solution-style tsconfigs so root settings apply
|
||||
4. Fix `resolve.alias` / `__dirname` / `baseUrl`
|
||||
5. Ensure `types` include `vite/client` and `node`
|
||||
6. Install `@nx/vite` manually if it failed during import
|
||||
7. Remove redundant npm scripts so `@nx/vite/plugin` infers them natively (see "Redundant npm Scripts" section)
|
||||
8. **Vue**: Add `outDir` + `**/*.vue.d.ts` to ESLint ignores
|
||||
9. Full verification
|
||||
|
||||
### Multiple-Source Imports
|
||||
|
||||
See SKILL.md for generic multi-import (name collisions, dep refs). Vite-specific: fix tsconfig `references` paths for alternate directories (`../../libs/` → `../../libs-beta/`).
|
||||
|
||||
### Non-Nx Source: React Router 7
|
||||
|
||||
1. Ensure source has at least one commit (see SKILL.md: "Source Repo Has No Commits")
|
||||
2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: "Application vs Library Detection") → auto-installs `@nx/vite`, `@nx/react`
|
||||
3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`
|
||||
4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`
|
||||
5. Add `build` and `.react-router` to dest root `.gitignore`
|
||||
6. **Keep all npm scripts** — React Router 7 uses framework CLI (`react-router build/dev`), not plain vite (see "Redundant npm Scripts" above)
|
||||
7. `npm install && nx reset && nx sync --yes`
|
||||
|
||||
### Non-Nx Source: TanStack Start
|
||||
|
||||
1. Ensure source has at least one commit — `create-tan-stack` does NOT auto-commit (see SKILL.md)
|
||||
2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: "Application vs Library Detection") → auto-installs `@nx/vite`, `@nx/vitest`
|
||||
3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`
|
||||
4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`
|
||||
5. Keep `allowImportingTsExtensions` — compatible with `emitDeclarationOnly: true`
|
||||
6. Add `.vinxi`, `.tanstack`, `.nitro`, `.output` to dest root `.gitignore`
|
||||
7. Move hardcoded `--port` from `dev` script into `vite.config.ts` (`server: { port: N }`)
|
||||
8. Remove redundant npm scripts — `@nx/vite/plugin` infers `build`, `dev`, `preview`, `test` (see "Redundant npm Scripts" above)
|
||||
9. `npm install && nx reset && nx sync --yes`
|
||||
|
||||
### Quick Reference: React vs Vue
|
||||
|
||||
| Aspect | React | Vue |
|
||||
| ------------- | ------------------------ | ----------------------------------------- |
|
||||
| Vite plugin | `@vitejs/plugin-react` | `@vitejs/plugin-vue` |
|
||||
| Type checker | `tsc` | `vue-tsc` (auto-detected) |
|
||||
| SFC support | N/A | `vue-shims.d.ts` needed |
|
||||
| tsconfig jsx | `"react-jsx"` | `"preserve"` + `"jsxImportSource": "vue"` |
|
||||
| ESLint parser | Standard TS | `vue-eslint-parser` + TS sub-parser |
|
||||
| ESLint setup | Straightforward | Must install deps before `@nx/eslint` |
|
||||
| Test utils | `@testing-library/react` | `@vue/test-utils` |
|
||||
|
||||
### Quick Reference: Vite-Based React Frameworks
|
||||
|
||||
| Aspect | Vite (standalone) | React Router 7 | TanStack Start |
|
||||
| ------------------ | ----------------- | ----------------------- | ------------------------ |
|
||||
| Build config | `vite.config.ts` | `vite.config.ts` | `vite.config.ts` |
|
||||
| Build output | `dist/` | `build/` | `dist/` |
|
||||
| SSR bundle | No | Yes (`build/server/`) | Yes (`dist/server/`) |
|
||||
| tsconfig layout | app + node split | Single tsconfig | Single tsconfig |
|
||||
| Auto-committed | Depends on tool | Usually yes | **No — commit first** |
|
||||
| `nx import` plugin | `@nx/vite` | `@nx/vite`, `@nx/react` | `@nx/vite`, `@nx/vitest` |
|
||||
|
||||
---
|
||||
|
||||
## Iteration Log
|
||||
|
||||
### Scenario 6: Multiple non-Nx React apps (CRA, Next.js, React Router 7, TanStack Start, Vite) → TS preset (PASS)
|
||||
|
||||
- Sources: 5 standalone non-Nx repos with different build tools
|
||||
- Dest: CNW ts preset (Nx 22.5.1), npm workspaces, `packages/*`
|
||||
- Import: whole-repo for each, sequential into `packages/<name>`
|
||||
- Pre-import fixes:
|
||||
1. Removed `packages/.gitkeep` and committed
|
||||
2. `git init && git add . && git commit` in Vite app (no git at all)
|
||||
3. `git add . && git commit` in TanStack app (git init'd but no commits)
|
||||
- Import: `npm exec nx -- import <source> packages/<name> --source=. --ref=main --no-interactive`
|
||||
- Next.js import auto-installed `@nx/eslint`, `@nx/next`
|
||||
- React Router 7 import auto-installed `@nx/vite`, `@nx/react`, `@nx/docker` (Dockerfile present)
|
||||
- TanStack import auto-installed `@nx/vitest`
|
||||
- Post-import fixes:
|
||||
1. Removed stale `node_modules/`, `package-lock.json`, `.gitignore` from each package
|
||||
2. Removed Nx-rewritten scripts from `board-games-nextjs/package.json` (had `"build": "nx next:build"`, etc.)
|
||||
3. Updated root `tsconfig.base.json`: `nodenext` → `bundler`, added `dom`/`dom.iterable` to lib, added `jsx: react-jsx`
|
||||
4. Added `build` to dest root `.gitignore` (CRA and React Router 7 output there)
|
||||
5. Fixed `noEmit` → `composite + emitDeclarationOnly` in: `board-games-vite/tsconfig.app.json`, `board-games-vite/tsconfig.node.json`, `board-games-react-router/tsconfig.json`, `board-games-tanstack/tsconfig.json`
|
||||
6. Fixed `tsBuildInfoFile` paths from `./node_modules/.tmp/...` to `./dist/...`
|
||||
7. Installed root `@types/react`, `@types/react-dom`, `@types/node`
|
||||
- All targets green: `build` for all 5 projects; `typecheck` for Vite/React Router/TanStack; `next:build` for Next.js
|
||||
Reference in New Issue
Block a user