From ec5a5e63606b4b7a797ef1ff9d211ffa47dcef0c Mon Sep 17 00:00:00 2001
From: Jack Hsu <jack.hsu@gmail.com>
Date: Thu, 28 Nov 2024 22:18:45 -0500
Subject: [PATCH] feat(react): update app and lib generators to support new TS
 solution setup (#28808)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This PR updates app and lib generators in the following packages such
that they will generate files with the TS solution setup if it is
detected.

- `@nx/react`
- `@nx/next`
- `@nx/remix`
- `@nx/expo`
- `@nx/react-native`

React apps and libs will be linked using npm/pnpm/yarn/bun workspaces
feature rather than through tsconfig paths. This means that local
aliases like `@/` will work with Next.js and Remix apps.

Note: This will be behind `--workspaces` flag when using `npx
create-nx-workspace` and choosing React stack. If you use the None/TS
stack then adding plugins like `nx add @nx/react` then generating apps,
it will automatically pick up the new TS solution setup.


<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
React generators are not compatible with TS solution setup (i.e.
workspaces + TS project references).

## Expected Behavior
React generators work with new TS solution setup (Plain, Next.js, Remix,
Expo, React Native).

## Related Issue(s)
#28322

---------

Co-authored-by: Leosvel PĂ©rez Espinosa <leosvel.perez.espinosa@gmail.com>
Co-authored-by: Nicholas Cunningham <ndcunningham@gmail.com>
---
 docs/generated/cli/create-nx-workspace.md     |   2 +
 .../packages/expo/generators/application.json |   9 +-
 .../packages/expo/generators/library.json     |   7 +-
 .../packages/next/generators/application.json |  10 +-
 .../packages/next/generators/library.json     |  21 +-
 .../nx/documents/create-nx-workspace.md       |   2 +
 .../react-native/generators/application.json  |   9 +-
 .../react-native/generators/library.json      |   7 +-
 .../react/generators/application.json         |  34 +--
 .../packages/react/generators/library.json    |  25 +-
 .../remix/generators/application.json         |  11 +-
 .../packages/remix/generators/library.json    |  28 ++-
 .../packages/rspack/executors/rspack.json     |   2 +-
 .../packages/workspace/generators/new.json    |   7 +-
 .../packages/workspace/generators/preset.json |  13 +-
 e2e/eslint/src/linter-legacy.test.ts          |  17 +-
 e2e/eslint/src/linter.test.ts                 |  52 +++--
 e2e/expo/src/expo-legacy.test.ts              |  14 +-
 e2e/expo/src/expo.test.ts                     |   6 +-
 e2e/jest/src/jest-root.test.ts                |  12 +-
 e2e/next/src/next-styles.test.ts              |  12 +-
 e2e/next/src/next.test.ts                     |  34 ++-
 e2e/nx/src/workspace-legacy.test.ts           |   2 +-
 e2e/nx/src/workspace.test.ts                  |   8 +-
 .../src/react-native-legacy.test.ts           |  12 +-
 e2e/react-native/src/react-native.test.ts     |   4 +-
 e2e/react/src/react-vite.test.ts              |  14 +-
 e2e/react/src/react.test.ts                   |  36 +--
 e2e/remix/src/nx-remix.test.ts                |  26 ++-
 e2e/rspack/tests/rspack.spec.ts               |  12 +-
 e2e/utils/create-project-utils.ts             |  12 +
 e2e/vite/src/vite-legacy.test.ts              |   8 +-
 e2e/webpack/src/webpack.legacy.test.ts        |  12 +-
 .../bin/create-nx-workspace.ts                | 110 ++++++---
 .../src/create-workspace.ts                   |  26 ++-
 .../__directory__/tsconfig.json__ext__        |   3 +-
 .../generators/configuration/configuration.ts |  24 ++
 .../src/generators/application/application.ts |   8 +-
 .../generators/application/lib/add-project.ts |  33 ++-
 packages/detox/src/generators/init/init.ts    |   3 -
 .../workspace-rules-project.ts                |   1 +
 .../application/application.spec.ts           | 145 ++++++++++++
 .../src/generators/application/application.ts |  25 +-
 .../src/generators/application/lib/add-e2e.ts |  70 ++++--
 .../generators/application/lib/add-project.ts |  32 ++-
 .../src/generators/application/schema.d.ts    |   3 +
 .../src/generators/application/schema.json    |   9 +-
 packages/expo/src/generators/init/init.ts     |   3 -
 .../library/lib/normalize-options.ts          |   3 +
 .../src/generators/library/library.spec.ts    |   2 +
 .../expo/src/generators/library/library.ts    |  63 ++++-
 .../expo/src/generators/library/schema.json   |   7 +-
 .../files/tsconfig.spec.json__tmpl__          |   5 +-
 .../configuration/lib/create-files.ts         |   2 +-
 .../js/src/generators/library/library.spec.ts |  61 +++++
 packages/js/src/generators/library/library.ts |  17 ++
 .../js/src/plugins/typescript/plugin.spec.ts  |  10 +-
 packages/js/src/plugins/typescript/plugin.ts  |  90 +++++--
 .../src/utils/package-manager-workspaces.ts   |  19 +-
 .../src/utils/typescript/ts-solution-setup.ts |  81 ++++++-
 .../application/application.spec.ts           | 202 ++++++++++++++--
 .../src/generators/application/application.ts |  21 +-
 .../files/common/tsconfig.json__tmpl__        |  16 +-
 .../src/generators/application/lib/add-e2e.ts |  68 ++++--
 .../generators/application/lib/add-linting.ts |   2 +
 .../generators/application/lib/add-project.ts |  31 ++-
 .../lib/create-application-files.ts           |  20 +-
 .../src/generators/application/schema.d.ts    |   3 +
 .../src/generators/application/schema.json    |  10 +-
 .../generators/custom-server/custom-server.ts |  11 +-
 .../files/tsconfig.server.json__tmpl__        |   5 +-
 packages/next/src/generators/init/init.ts     |   3 -
 .../next/src/generators/library/library.ts    |  20 +-
 .../next/src/generators/library/schema.d.ts   |   2 +
 .../next/src/generators/library/schema.json   |  21 +-
 .../generators/configuration/configuration.ts |  10 +-
 .../application/application.spec.ts           | 150 ++++++++++++
 .../src/generators/application/application.ts |  26 ++-
 .../generators/application/lib/add-project.ts |  25 +-
 .../src/generators/application/schema.d.ts    |   3 +
 .../src/generators/application/schema.json    |   9 +-
 .../react-native/src/generators/init/init.ts  |   3 -
 .../library/lib/normalize-options.ts          |   3 +
 .../src/generators/library/library.spec.ts    |   2 +
 .../src/generators/library/library.ts         |  63 ++++-
 .../src/generators/library/schema.json        |   7 +-
 .../web-configuration/web-configuration.ts    |  19 +-
 packages/react-native/src/utils/versions.ts   |   1 +
 .../__snapshots__/application.spec.ts.snap    |  12 +-
 .../application/application.spec.ts           | 182 ++++++++++++++-
 .../src/generators/application/application.ts |  51 ++--
 .../base-rspack/tsconfig.app.json__tmpl__     |  25 +-
 .../files/base-vite/tsconfig.app.json__tmpl__ |  21 +-
 .../base-webpack/tsconfig.app.json__tmpl__    |  23 +-
 .../src/app/__fileName__.tsx__tmpl__          |   4 +-
 .../src/generators/application/lib/add-e2e.ts |  69 ++++--
 .../generators/application/lib/add-jest.ts    |   1 +
 .../generators/application/lib/add-project.ts |  24 +-
 .../lib/create-application-files.ts           |   4 +-
 .../application/lib/normalize-options.ts      |   2 +
 .../application/lib/update-jest-config.ts     |   5 +
 .../src/generators/application/schema.d.ts    |   5 +
 .../src/generators/application/schema.json    |  34 +--
 .../generators/component/component.spec.ts    |   2 +-
 .../src/generators/component/component.ts     |  15 +-
 .../component/lib/normalize-options.ts        |   3 +-
 .../src/generators/component/schema.d.ts      |   1 +
 .../src/generators/host/host.rspack.spec.ts   | 124 +++++++++-
 packages/react/src/generators/host/host.ts    |   6 +-
 .../lib/update-module-federation-tsconfig.ts  |  48 ++++
 packages/react/src/generators/init/init.ts    |   3 -
 .../library/files/common/package.json__tmpl__ |   4 -
 .../library/files/vite/package.json__tmpl__   |  12 -
 .../generators/library/lib/create-files.ts    |  27 ++-
 .../library/lib/normalize-options.ts          |   6 +
 .../src/generators/library/library.spec.ts    | 187 +++++++++++++++
 .../react/src/generators/library/library.ts   |  77 ++++--
 .../react/src/generators/library/schema.d.ts  |   1 +
 .../react/src/generators/library/schema.json  |  25 +-
 .../react/src/generators/remote/remote.ts     |   4 +-
 .../rules/update-module-federation-project.ts |   7 +
 packages/react/src/utils/create-ts-config.ts  | 117 +++++++++-
 packages/react/src/utils/versions.ts          |   3 -
 .../application/application.impl.spec.ts      | 219 +++++++++++++++++-
 .../application/application.impl.ts           |  70 ++++--
 .../.gitignore__tmpl__                        |   0
 .../package.json__tmpl__                      |   0
 .../files/ts-solution/package.json__tmpl__    |  32 +++
 .../ts-solution/tsconfig.app.json__tmpl__     |  39 ++++
 .../files/ts-solution/tsconfig.json__tmpl__   |  10 +
 .../src/generators/application/lib/add-e2e.ts |  68 ++++--
 .../src/generators/application/schema.d.ts    |   3 +
 .../src/generators/application/schema.json    |  11 +-
 packages/remix/src/generators/init/init.ts    |  14 +-
 .../src/generators/library/library.impl.ts    |  31 ++-
 .../remix/src/generators/library/schema.d.ts  |   3 +
 .../remix/src/generators/library/schema.json  |  28 ++-
 .../rspack/src/executors/rspack/schema.json   |   2 +-
 .../src/generators/application/application.ts |   3 -
 .../generators/configuration/configuration.ts |   3 -
 packages/rspack/src/generators/init/init.ts   |   3 -
 .../configuration/configuration.spec.ts       |  90 ++++++-
 .../generators/configuration/configuration.ts |  54 +++--
 .../src/generators/configuration/schema.d.ts  |   2 +
 .../vite/src/generators/vitest/schema.d.ts    |   2 +
 .../src/generators/vitest/vitest-generator.ts |  10 +-
 packages/vite/src/plugins/plugin.spec.ts      |  27 +++
 packages/vite/src/plugins/plugin.ts           |  27 ++-
 .../generators/configuration/configuration.ts |   3 -
 packages/webpack/src/generators/init/init.ts  |   3 -
 .../src/generators/new/generate-preset.ts     |   1 +
 .../new/generate-workspace-files.spec.ts      |  75 +++++-
 .../new/generate-workspace-files.ts           |  15 +-
 packages/workspace/src/generators/new/new.ts  |   8 +
 .../workspace/src/generators/new/schema.json  |   7 +-
 .../workspace/src/generators/preset/preset.ts |  13 ++
 .../src/generators/preset/schema.d.ts         |   1 +
 .../src/generators/preset/schema.json         |  13 +-
 158 files changed, 3457 insertions(+), 658 deletions(-)
 create mode 100644 packages/react/src/generators/host/lib/update-module-federation-tsconfig.ts
 delete mode 100644 packages/react/src/generators/library/files/common/package.json__tmpl__
 delete mode 100644 packages/react/src/generators/library/files/vite/package.json__tmpl__
 rename packages/remix/src/generators/application/files/{integrated => non-root}/.gitignore__tmpl__ (100%)
 rename packages/remix/src/generators/application/files/{integrated => non-root}/package.json__tmpl__ (100%)
 create mode 100644 packages/remix/src/generators/application/files/ts-solution/package.json__tmpl__
 create mode 100644 packages/remix/src/generators/application/files/ts-solution/tsconfig.app.json__tmpl__
 create mode 100644 packages/remix/src/generators/application/files/ts-solution/tsconfig.json__tmpl__

diff --git a/docs/generated/cli/create-nx-workspace.md b/docs/generated/cli/create-nx-workspace.md
index b6d88f73b3da70..bb2e303ad511a9 100644
--- a/docs/generated/cli/create-nx-workspace.md
+++ b/docs/generated/cli/create-nx-workspace.md
@@ -28,6 +28,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
 | `--defaultBase`    | string                                                                        | Default base to use for new projects. (Default: `main`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
 | `--docker`         | boolean                                                                       | Generate a Dockerfile for the Node API.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
 | `--e2eTestRunner`  | `playwright`, `cypress`, `none`                                               | Test runner to use for end to end (E2E) tests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
+| `--formatter`      | string                                                                        | Code formatter to use.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
 | `--framework`      | string                                                                        | Framework option to be used with certain stacks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
 | `--help`           | boolean                                                                       | Show help.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
 | `--interactive`    | boolean                                                                       | Enable interactive mode with presets. (Default: `true`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
@@ -45,6 +46,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
 | `--style`          | string                                                                        | Stylesheet type to be used with certain stacks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
 | `--useGitHub`      | boolean                                                                       | Will you be using GitHub as your git hosting provider? (Default: `false`)                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
 | `--version`        | boolean                                                                       | Show version number.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
+| `--workspaces`     | boolean                                                                       | Use package manager workspaces. (Default: `false`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
 | `--workspaceType`  | `integrated`, `package-based`, `standalone`                                   | The type of workspace to create.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
 
 ## Presets
diff --git a/docs/generated/packages/expo/generators/application.json b/docs/generated/packages/expo/generators/application.json
index 7eb94e7915e405..389e3f0c5e7b1a 100644
--- a/docs/generated/packages/expo/generators/application.json
+++ b/docs/generated/packages/expo/generators/application.json
@@ -44,13 +44,15 @@
         "description": "The tool to use for running lint checks.",
         "type": "string",
         "enum": ["eslint", "none"],
-        "default": "eslint"
+        "default": "none",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["jest", "none"],
         "description": "Test runner to use for unit tests",
-        "default": "jest"
+        "default": "none",
+        "x-priority": "important"
       },
       "tags": {
         "type": "string",
@@ -71,7 +73,8 @@
         "description": "Adds the specified e2e test runner",
         "type": "string",
         "enum": ["playwright", "cypress", "detox", "none"],
-        "default": "none"
+        "default": "none",
+        "x-priority": "important"
       },
       "standaloneConfig": {
         "description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
diff --git a/docs/generated/packages/expo/generators/library.json b/docs/generated/packages/expo/generators/library.json
index ce7f139f379e4d..ef35d1e653b739 100644
--- a/docs/generated/packages/expo/generators/library.json
+++ b/docs/generated/packages/expo/generators/library.json
@@ -29,13 +29,16 @@
         "description": "The tool to use for running lint checks.",
         "type": "string",
         "enum": ["eslint", "none"],
-        "default": "eslint"
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["jest", "none"],
         "description": "Test runner to use for unit tests.",
-        "default": "jest"
+        "default": "none",
+        "x-priority": "important"
       },
       "tags": {
         "type": "string",
diff --git a/docs/generated/packages/next/generators/application.json b/docs/generated/packages/next/generators/application.json
index f78caf9f89447a..fbba2beb03cd88 100644
--- a/docs/generated/packages/next/generators/application.json
+++ b/docs/generated/packages/next/generators/application.json
@@ -63,8 +63,10 @@
       "linter": {
         "description": "The tool to use for running lint checks.",
         "type": "string",
-        "enum": ["eslint"],
-        "default": "eslint"
+        "enum": ["eslint", "none"],
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "skipFormat": {
         "description": "Skip formatting files.",
@@ -76,7 +78,9 @@
         "type": "string",
         "enum": ["jest", "none"],
         "description": "Test runner to use for unit tests.",
-        "default": "jest"
+        "default": "none",
+        "x-prompt": "What unit test runner should be used?",
+        "x-priority": "important"
       },
       "e2eTestRunner": {
         "type": "string",
diff --git a/docs/generated/packages/next/generators/library.json b/docs/generated/packages/next/generators/library.json
index 19a4977ccd6374..d101fa42198346 100644
--- a/docs/generated/packages/next/generators/library.json
+++ b/docs/generated/packages/next/generators/library.json
@@ -56,17 +56,29 @@
           ]
         }
       },
+      "bundler": {
+        "type": "string",
+        "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
+        "enum": ["none", "vite", "rollup"],
+        "default": "none",
+        "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
+        "x-priority": "important"
+      },
       "linter": {
         "description": "The tool to use for running lint checks.",
         "type": "string",
-        "enum": ["eslint"],
-        "default": "eslint"
+        "enum": ["eslint", "none"],
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["vitest", "jest", "none"],
         "description": "Test runner to use for unit tests.",
-        "default": "vitest"
+        "default": "none",
+        "x-prompt": "What unit test runner should be used?",
+        "x-priority": "important"
       },
       "tags": {
         "type": "string",
@@ -99,7 +111,8 @@
       "buildable": {
         "type": "boolean",
         "default": false,
-        "description": "Generate a buildable library."
+        "description": "Generate a buildable library that uses rollup to bundle.",
+        "x-deprecated": "Use the `bundler` option for greater control (none, vite, rollup)."
       },
       "importPath": {
         "type": "string",
diff --git a/docs/generated/packages/nx/documents/create-nx-workspace.md b/docs/generated/packages/nx/documents/create-nx-workspace.md
index b6d88f73b3da70..bb2e303ad511a9 100644
--- a/docs/generated/packages/nx/documents/create-nx-workspace.md
+++ b/docs/generated/packages/nx/documents/create-nx-workspace.md
@@ -28,6 +28,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
 | `--defaultBase`    | string                                                                        | Default base to use for new projects. (Default: `main`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
 | `--docker`         | boolean                                                                       | Generate a Dockerfile for the Node API.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
 | `--e2eTestRunner`  | `playwright`, `cypress`, `none`                                               | Test runner to use for end to end (E2E) tests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
+| `--formatter`      | string                                                                        | Code formatter to use.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
 | `--framework`      | string                                                                        | Framework option to be used with certain stacks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
 | `--help`           | boolean                                                                       | Show help.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
 | `--interactive`    | boolean                                                                       | Enable interactive mode with presets. (Default: `true`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
@@ -45,6 +46,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
 | `--style`          | string                                                                        | Stylesheet type to be used with certain stacks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
 | `--useGitHub`      | boolean                                                                       | Will you be using GitHub as your git hosting provider? (Default: `false`)                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
 | `--version`        | boolean                                                                       | Show version number.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
+| `--workspaces`     | boolean                                                                       | Use package manager workspaces. (Default: `false`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
 | `--workspaceType`  | `integrated`, `package-based`, `standalone`                                   | The type of workspace to create.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
 
 ## Presets
diff --git a/docs/generated/packages/react-native/generators/application.json b/docs/generated/packages/react-native/generators/application.json
index a151285fec4fce..4100814e2fc7c2 100644
--- a/docs/generated/packages/react-native/generators/application.json
+++ b/docs/generated/packages/react-native/generators/application.json
@@ -44,13 +44,15 @@
         "description": "The tool to use for running lint checks.",
         "type": "string",
         "enum": ["eslint", "none"],
-        "default": "eslint"
+        "default": "none",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["jest", "none"],
         "description": "Test runner to use for unit tests",
-        "default": "jest"
+        "default": "none",
+        "x-priority": "important"
       },
       "tags": {
         "type": "string",
@@ -71,7 +73,8 @@
         "description": "Adds the specified e2e test runner.",
         "type": "string",
         "enum": ["playwright", "cypress", "detox", "none"],
-        "default": "playwright"
+        "default": "none",
+        "x-priority": "important"
       },
       "install": {
         "type": "boolean",
diff --git a/docs/generated/packages/react-native/generators/library.json b/docs/generated/packages/react-native/generators/library.json
index 4123a73aa224b7..919ddf8b688798 100644
--- a/docs/generated/packages/react-native/generators/library.json
+++ b/docs/generated/packages/react-native/generators/library.json
@@ -32,13 +32,16 @@
         "description": "The tool to use for running lint checks.",
         "type": "string",
         "enum": ["eslint", "none"],
-        "default": "eslint"
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["jest", "none"],
         "description": "Test runner to use for unit tests.",
-        "default": "jest"
+        "default": "none",
+        "x-priority": "important"
       },
       "tags": {
         "type": "string",
diff --git a/docs/generated/packages/react/generators/application.json b/docs/generated/packages/react/generators/application.json
index 4ecfc1f541a6f8..2a4962bd94a837 100644
--- a/docs/generated/packages/react/generators/application.json
+++ b/docs/generated/packages/react/generators/application.json
@@ -74,12 +74,6 @@
           ]
         }
       },
-      "linter": {
-        "description": "The tool to use for running lint checks.",
-        "type": "string",
-        "enum": ["eslint", "none"],
-        "default": "eslint"
-      },
       "routing": {
         "type": "boolean",
         "description": "Generate application with routes.",
@@ -98,11 +92,29 @@
         "default": false,
         "x-priority": "internal"
       },
+      "bundler": {
+        "description": "The bundler to use.",
+        "type": "string",
+        "enum": ["vite", "webpack", "rspack"],
+        "x-prompt": "Which bundler do you want to use to build the application?",
+        "default": "vite",
+        "x-priority": "important"
+      },
+      "linter": {
+        "description": "The tool to use for running lint checks.",
+        "type": "string",
+        "enum": ["eslint", "none"],
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
+      },
       "unitTestRunner": {
         "type": "string",
         "enum": ["vitest", "jest", "none"],
         "description": "Test runner to use for unit tests.",
-        "default": "vitest"
+        "default": "none",
+        "x-prompt": "What unit test runner should be used?",
+        "x-priority": "important"
       },
       "inSourceTests": {
         "type": "boolean",
@@ -165,14 +177,6 @@
         "default": false,
         "hidden": true
       },
-      "bundler": {
-        "description": "The bundler to use.",
-        "type": "string",
-        "enum": ["vite", "webpack", "rspack"],
-        "x-prompt": "Which bundler do you want to use to build the application?",
-        "default": "vite",
-        "x-priority": "important"
-      },
       "minimal": {
         "description": "Generate a React app with a minimal setup, no separate test files.",
         "type": "boolean",
diff --git a/docs/generated/packages/react/generators/library.json b/docs/generated/packages/react/generators/library.json
index 1366c05768ddc4..fa5b8dc3b5ad85 100644
--- a/docs/generated/packages/react/generators/library.json
+++ b/docs/generated/packages/react/generators/library.json
@@ -65,18 +65,29 @@
           ]
         }
       },
+      "bundler": {
+        "type": "string",
+        "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
+        "enum": ["none", "vite", "rollup"],
+        "default": "none",
+        "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
+        "x-priority": "important"
+      },
       "linter": {
         "description": "The tool to use for running lint checks.",
         "type": "string",
         "enum": ["eslint", "none"],
-        "default": "eslint"
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["vitest", "jest", "none"],
-        "default": "vitest",
+        "default": "none",
         "description": "Test runner to use for unit tests.",
-        "x-prompt": "What unit test runner should be used?"
+        "x-prompt": "What unit test runner should be used?",
+        "x-priority": "important"
       },
       "inSourceTests": {
         "type": "boolean",
@@ -148,14 +159,6 @@
         "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
         "default": false
       },
-      "bundler": {
-        "type": "string",
-        "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
-        "enum": ["none", "vite", "rollup"],
-        "default": "none",
-        "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
-        "x-priority": "important"
-      },
       "compiler": {
         "type": "string",
         "enum": ["babel", "swc"],
diff --git a/docs/generated/packages/remix/generators/application.json b/docs/generated/packages/remix/generators/application.json
index 2ddb29ae33ffec..773e6e4b840a98 100644
--- a/docs/generated/packages/remix/generators/application.json
+++ b/docs/generated/packages/remix/generators/application.json
@@ -24,19 +24,22 @@
         "description": "The tool to use for running lint checks.",
         "type": "string",
         "enum": ["eslint", "none"],
-        "default": "eslint"
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["vitest", "jest", "none"],
-        "default": "vitest",
+        "default": "none",
         "description": "Test runner to use for unit tests.",
-        "x-prompt": "What unit test runner should be used?"
+        "x-prompt": "What unit test runner should be used?",
+        "x-priority": "important"
       },
       "e2eTestRunner": {
         "type": "string",
         "enum": ["playwright", "cypress", "none"],
-        "default": "playwright",
+        "default": "none",
         "description": "Test runner to use for e2e tests",
         "x-prompt": "Which E2E test runner would you like to use?"
       },
diff --git a/docs/generated/packages/remix/generators/library.json b/docs/generated/packages/remix/generators/library.json
index f4400b418cb26d..0844b41c46c824 100644
--- a/docs/generated/packages/remix/generators/library.json
+++ b/docs/generated/packages/remix/generators/library.json
@@ -37,17 +37,29 @@
         "enum": ["none", "css"],
         "default": "css"
       },
-      "buildable": {
-        "type": "boolean",
-        "description": "Should the library be buildable?",
-        "default": false
+      "bundler": {
+        "type": "string",
+        "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
+        "enum": ["none", "vite", "rollup"],
+        "default": "none",
+        "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
+        "x-priority": "important"
+      },
+      "linter": {
+        "description": "The tool to use for running lint checks.",
+        "type": "string",
+        "enum": ["eslint", "none"],
+        "default": "none",
+        "x-prompt": "Which linter would you like to use?",
+        "x-priority": "important"
       },
       "unitTestRunner": {
         "type": "string",
         "enum": ["vitest", "jest", "none"],
         "description": "Test Runner to use for Unit Tests",
         "x-prompt": "What test runner should be used?",
-        "default": "vitest"
+        "default": "none",
+        "x-priority": "important"
       },
       "importPath": {
         "type": "string",
@@ -63,6 +75,12 @@
         "description": "Skip formatting files after generator runs",
         "default": false,
         "x-priority": "internal"
+      },
+      "buildable": {
+        "type": "boolean",
+        "default": false,
+        "description": "Generate a buildable library that uses rollup to bundle.",
+        "x-deprecated": "Use the `bundler` option for greater control (none, vite, rollup)."
       }
     },
     "required": ["directory"],
diff --git a/docs/generated/packages/rspack/executors/rspack.json b/docs/generated/packages/rspack/executors/rspack.json
index 21d9dec4ae21b1..3164e778891c1d 100644
--- a/docs/generated/packages/rspack/executors/rspack.json
+++ b/docs/generated/packages/rspack/executors/rspack.json
@@ -119,7 +119,7 @@
       "extractLicenses": {
         "type": "boolean",
         "description": "Extract all licenses in a separate file.",
-        "default": true
+        "default": false
       },
       "fileReplacements": {
         "description": "Replace files with other files in the build.",
diff --git a/docs/generated/packages/workspace/generators/new.json b/docs/generated/packages/workspace/generators/new.json
index 966acc73429257..8ea49dbecb6715 100644
--- a/docs/generated/packages/workspace/generators/new.json
+++ b/docs/generated/packages/workspace/generators/new.json
@@ -47,7 +47,7 @@
       "linter": {
         "description": "The tool to use for running lint checks.",
         "type": "string",
-        "enum": ["eslint"],
+        "enum": ["eslint", "none"],
         "default": "eslint"
       },
       "packageManager": {
@@ -89,6 +89,11 @@
         "type": "string",
         "enum": ["none", "prettier"],
         "default": "none"
+      },
+      "workspaces": {
+        "description": "Whether to use package manager workspaces.",
+        "type": "boolean",
+        "default": false
       }
     },
     "additionalProperties": true,
diff --git a/docs/generated/packages/workspace/generators/preset.json b/docs/generated/packages/workspace/generators/preset.json
index b6dafd5b72c1f9..3ebfe23c9410b3 100644
--- a/docs/generated/packages/workspace/generators/preset.json
+++ b/docs/generated/packages/workspace/generators/preset.json
@@ -17,7 +17,7 @@
       "linter": {
         "description": "The tool to use for running lint checks.",
         "type": "string",
-        "enum": ["eslint"],
+        "enum": ["eslint", "none"],
         "default": "eslint"
       },
       "routing": {
@@ -100,6 +100,17 @@
       "prefix": {
         "description": "The prefix to use for Angular component and directive selectors.",
         "type": "string"
+      },
+      "formatter": {
+        "description": "The tool to use for code formatting.",
+        "type": "string",
+        "enum": ["none", "prettier"],
+        "default": "none"
+      },
+      "workspaces": {
+        "description": "Whether to use package manager workspaces.",
+        "type": "boolean",
+        "default": false
       }
     },
     "required": ["preset", "name"],
diff --git a/e2e/eslint/src/linter-legacy.test.ts b/e2e/eslint/src/linter-legacy.test.ts
index 0e33e0b910740a..b561d4419fbb8b 100644
--- a/e2e/eslint/src/linter-legacy.test.ts
+++ b/e2e/eslint/src/linter-legacy.test.ts
@@ -27,10 +27,13 @@ describe('Linter (legacy)', () => {
       newProject({
         packages: ['@nx/react', '@nx/js', '@nx/eslint'],
       });
-      runCLI(`generate @nx/react:app apps/${myapp} --tags=validtag`, {
-        env: { NX_ADD_PLUGINS: 'false' },
-      });
-      runCLI(`generate @nx/js:lib apps/${mylib}`, {
+      runCLI(
+        `generate @nx/react:app apps/${myapp} --tags=validtag --linter=eslint`,
+        {
+          env: { NX_ADD_PLUGINS: 'false' },
+        }
+      );
+      runCLI(`generate @nx/js:lib apps/${mylib} --linter=eslint`, {
         env: { NX_ADD_PLUGINS: 'false' },
       });
     });
@@ -135,10 +138,10 @@ describe('Linter (legacy)', () => {
         bundler: 'vite',
         e2eTestRunner: 'none',
       });
-      runCLI(`generate @nx/js:lib libs/${mylib}`, {
+      runCLI(`generate @nx/js:lib libs/${mylib} --linter=eslint`, {
         env: { NX_ADD_PLUGINS: 'false' },
       });
-      runCLI(`generate @nx/js:lib libs/${mylib2}`, {
+      runCLI(`generate @nx/js:lib libs/${mylib2} --linter=eslint`, {
         env: { NX_ADD_PLUGINS: 'false' },
       });
 
@@ -190,7 +193,7 @@ describe('Linter (legacy)', () => {
         bundler: 'vite',
         e2eTestRunner: 'none',
       });
-      runCLI(`generate @nx/js:lib ${mylib}`, {
+      runCLI(`generate @nx/js:lib ${mylib} --linter=eslint`, {
         env: { NX_ADD_PLUGINS: 'false' },
       });
 
diff --git a/e2e/eslint/src/linter.test.ts b/e2e/eslint/src/linter.test.ts
index 49859e1371f5e7..31a4c9a14dfc64 100644
--- a/e2e/eslint/src/linter.test.ts
+++ b/e2e/eslint/src/linter.test.ts
@@ -35,8 +35,10 @@ describe('Linter', () => {
       projScope = newProject({
         packages: ['@nx/react', '@nx/js', '@nx/eslint'],
       });
-      runCLI(`generate @nx/react:app apps/${myapp} --tags=validtag`);
-      runCLI(`generate @nx/js:lib libs/${mylib}`);
+      runCLI(
+        `generate @nx/react:app apps/${myapp} --tags=validtag --linter eslint --unitTestRunner vitest`
+      );
+      runCLI(`generate @nx/js:lib libs/${mylib} --linter eslint`);
     });
     afterAll(() => cleanupProject());
 
@@ -218,10 +220,14 @@ describe('Linter', () => {
         const invalidtaglib = uniq('invalidtaglib');
         const validtaglib = uniq('validtaglib');
 
-        runCLI(`generate @nx/react:app apps/${myapp2}`);
-        runCLI(`generate @nx/react:lib libs/${lazylib}`);
-        runCLI(`generate @nx/js:lib libs/${invalidtaglib} --tags=invalidtag`);
-        runCLI(`generate @nx/js:lib libs/${validtaglib} --tags=validtag`);
+        runCLI(`generate @nx/react:app apps/${myapp2} --linter eslint`);
+        runCLI(`generate @nx/react:lib libs/${lazylib} --linter eslint`);
+        runCLI(
+          `generate @nx/js:lib libs/${invalidtaglib} --linter eslint --tags=invalidtag`
+        );
+        runCLI(
+          `generate @nx/js:lib libs/${validtaglib} --linter eslint --tags=validtag`
+        );
 
         const eslint = readJson('.eslintrc.json');
         eslint.overrides[0].rules[
@@ -283,9 +289,15 @@ describe('Linter', () => {
 
       beforeAll(() => {
         // make these libs non-buildable to avoid dep-checks triggering lint errors
-        runCLI(`generate @nx/js:lib libs/${libA} --bundler=none`);
-        runCLI(`generate @nx/js:lib libs/${libB} --bundler=none`);
-        runCLI(`generate @nx/js:lib libs/${libC} --bundler=none`);
+        runCLI(
+          `generate @nx/js:lib libs/${libA} --bundler=none --linter eslint`
+        );
+        runCLI(
+          `generate @nx/js:lib libs/${libB} --bundler=none --linter eslint`
+        );
+        runCLI(
+          `generate @nx/js:lib libs/${libC} --bundler=none --linter eslint`
+        );
 
         /**
          * create tslib-a structure
@@ -599,8 +611,8 @@ describe('Linter', () => {
         const reactLib = uniq('react-lib');
         const jsLib = uniq('js-lib');
 
-        runCLI(`generate @nx/react:lib ${reactLib}`);
-        runCLI(`generate @nx/js:lib ${jsLib}`);
+        runCLI(`generate @nx/react:lib ${reactLib} --linter eslint`);
+        runCLI(`generate @nx/js:lib ${jsLib} --linter eslint`);
 
         checkFilesExist(
           `${reactLib}/eslint.config.js`,
@@ -687,7 +699,7 @@ describe('Linter', () => {
       const mylib = uniq('mylib');
 
       runCLI(
-        `generate @nx/react:app --name=${myapp} --unitTestRunner=jest --directory="."`
+        `generate @nx/react:app --name=${myapp} --unitTestRunner=jest --linter eslint --directory="."`
       );
       verifySuccessfulStandaloneSetup(myapp);
 
@@ -701,7 +713,9 @@ describe('Linter', () => {
       let e2eOverrides = JSON.stringify(e2eEslint.overrides);
       expect(e2eOverrides).toContain('plugin:@nx/javascript');
 
-      runCLI(`generate @nx/js:lib libs/${mylib} --unitTestRunner=jest`);
+      runCLI(
+        `generate @nx/js:lib libs/${mylib} --unitTestRunner=jest --linter eslint`
+      );
       verifySuccessfulMigratedSetup(myapp, mylib);
 
       appEslint = readJson(`.eslintrc.json`);
@@ -721,7 +735,7 @@ describe('Linter', () => {
       const mylib = uniq('mylib');
 
       runCLI(
-        `generate @nx/angular:app --name=${myapp} --directory="." --no-interactive`
+        `generate @nx/angular:app --name=${myapp} --directory="." --linter eslint --no-interactive`
       );
       verifySuccessfulStandaloneSetup(myapp);
 
@@ -734,7 +748,9 @@ describe('Linter', () => {
       let e2eOverrides = JSON.stringify(e2eEslint.overrides);
       expect(e2eOverrides).toContain('plugin:@nx/javascript');
 
-      runCLI(`generate @nx/js:lib libs/${mylib} --no-interactive`);
+      runCLI(
+        `generate @nx/js:lib libs/${mylib} --linter eslint --no-interactive`
+      );
       verifySuccessfulMigratedSetup(myapp, mylib);
 
       appEslint = readJson(`.eslintrc.json`);
@@ -752,7 +768,7 @@ describe('Linter', () => {
       const mylib = uniq('mylib');
 
       runCLI(
-        `generate @nx/node:app --name=${myapp} --directory="." --no-interactive`
+        `generate @nx/node:app --name=${myapp} --linter eslint --directory="." --no-interactive`
       );
       verifySuccessfulStandaloneSetup(myapp);
 
@@ -767,7 +783,9 @@ describe('Linter', () => {
       expect(e2eOverrides).toContain('plugin:@nx/javascript');
       expect(e2eOverrides).toContain('plugin:@nx/typescript');
 
-      runCLI(`generate @nx/js:lib libs/${mylib} --no-interactive`);
+      runCLI(
+        `generate @nx/js:lib libs/${mylib} --linter eslint --no-interactive`
+      );
       verifySuccessfulMigratedSetup(myapp, mylib);
 
       appEslint = readJson(`.eslintrc.json`);
diff --git a/e2e/expo/src/expo-legacy.test.ts b/e2e/expo/src/expo-legacy.test.ts
index 82f852de687a38..39e2b5cea5bcbd 100644
--- a/e2e/expo/src/expo-legacy.test.ts
+++ b/e2e/expo/src/expo-legacy.test.ts
@@ -40,10 +40,10 @@ describe('@nx/expo (legacy)', () => {
       return nxJson;
     });
     runCLI(
-      `generate @nx/expo:application apps/${appName} --e2eTestRunner=cypress --no-interactive`
+      `generate @nx/expo:application apps/${appName} --e2eTestRunner=cypress --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     runCLI(
-      `generate @nx/expo:library libs/${libName} --buildable --publishable --importPath=${proj}/${libName}`
+      `generate @nx/expo:library libs/${libName} --buildable --publishable --importPath=${proj}/${libName} --unitTestRunner=jest --linter=eslint`
     );
   });
   afterAll(() => {
@@ -210,7 +210,9 @@ describe('@nx/expo (legacy)', () => {
     const appName = uniq('app1');
     const libName = uniq('@my-org/lib1');
 
-    runCLI(`generate @nx/expo:application ${appName} --no-interactive`);
+    runCLI(
+      `generate @nx/expo:application ${appName} --no-interactive --unitTestRunner=jest --linter=eslint`
+    );
 
     // check files are generated without the layout directory ("apps/") and
     // using the project name as the directory when no directory is provided
@@ -221,7 +223,9 @@ describe('@nx/expo (legacy)', () => {
       `Successfully ran target test for project ${appName}`
     );
 
-    runCLI(`generate @nx/expo:library ${libName} --buildable`);
+    runCLI(
+      `generate @nx/expo:library ${libName} --buildable --unitTestRunner=jest --linter=eslint`
+    );
 
     // check files are generated without the layout directory ("libs/") and
     // using the project name as the directory when no directory is provided
@@ -274,7 +278,7 @@ describe('@nx/expo (legacy)', () => {
   it('should run e2e for playwright', async () => {
     const appName2 = uniq('my-app');
     runCLI(
-      `generate @nx/expo:application ${appName2} --e2eTestRunner=playwright --no-interactive`
+      `generate @nx/expo:application ${appName2} --e2eTestRunner=playwright --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     if (runE2ETests()) {
       const results = runCLI(`e2e ${appName2}-e2e`, { verbose: true });
diff --git a/e2e/expo/src/expo.test.ts b/e2e/expo/src/expo.test.ts
index 3e5dfc7a7d638d..c03e1b1fc2a516 100644
--- a/e2e/expo/src/expo.test.ts
+++ b/e2e/expo/src/expo.test.ts
@@ -23,7 +23,9 @@ describe('@nx/expo', () => {
   beforeAll(() => {
     newProject();
     appName = uniq('app');
-    runCLI(`generate @nx/expo:app ${appName} --no-interactive`);
+    runCLI(
+      `generate @nx/expo:app ${appName} --no-interactive --unitTestRunner=jest --linter=eslint`
+    );
   });
 
   afterAll(() => cleanupProject());
@@ -152,7 +154,7 @@ describe('@nx/expo', () => {
 
   it('should create storybook with application', async () => {
     runCLI(
-      `generate @nx/react:storybook-configuration ${appName} --generateStories --no-interactive`
+      `generate @nx/react:storybook-configuration ${appName} --generateStories --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     checkFilesExist(
       `${appName}/.storybook/main.ts`,
diff --git a/e2e/jest/src/jest-root.test.ts b/e2e/jest/src/jest-root.test.ts
index 562ba69b83db90..90b4c24dfa29ed 100644
--- a/e2e/jest/src/jest-root.test.ts
+++ b/e2e/jest/src/jest-root.test.ts
@@ -10,7 +10,7 @@ describe('Jest root projects', () => {
         packages: ['@nx/angular'],
       });
       runCLI(
-        `generate @nx/angular:app --name=${myapp} --directory . --rootProject --no-interactive`
+        `generate @nx/angular:app --name=${myapp} --directory . --rootProject --no-interactive --unitTestRunner=jest --linter=eslint`
       );
     });
 
@@ -19,7 +19,9 @@ describe('Jest root projects', () => {
     }, 300_000);
 
     it('should add lib project and tests should still work', async () => {
-      runCLI(`generate @nx/angular:lib ${mylib} --no-interactive`);
+      runCLI(
+        `generate @nx/angular:lib ${mylib} --no-interactive --unitTestRunner=jest --linter=eslint`
+      );
 
       expect(() => runCLI(`test ${mylib}`)).not.toThrow();
       expect(() => runCLI(`test ${myapp}`)).not.toThrow();
@@ -32,7 +34,7 @@ describe('Jest root projects', () => {
         packages: ['@nx/react'],
       });
       runCLI(
-        `generate @nx/react:app --name=${myapp} --directory . --rootProject`
+        `generate @nx/react:app --name=${myapp} --directory . --rootProject --unitTestRunner=jest --linter=eslint`
       );
     });
 
@@ -41,7 +43,9 @@ describe('Jest root projects', () => {
     }, 300_000);
 
     it('should add lib project and tests should still work', async () => {
-      runCLI(`generate @nx/react:lib ${mylib} --unitTestRunner=jest`);
+      runCLI(
+        `generate @nx/react:lib ${mylib} --unitTestRunner=jest --linter=eslint`
+      );
 
       expect(() => runCLI(`test ${mylib}`)).not.toThrow();
       expect(() => runCLI(`test ${myapp}`)).not.toThrow();
diff --git a/e2e/next/src/next-styles.test.ts b/e2e/next/src/next-styles.test.ts
index 219557036a1cde..b8d58707864d86 100644
--- a/e2e/next/src/next-styles.test.ts
+++ b/e2e/next/src/next-styles.test.ts
@@ -32,7 +32,7 @@ describe('Next.js Styles', () => {
     const lessApp = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${lessApp} --no-interactive --style=less --appDir=false --src=false`
+      `generate @nx/next:app ${lessApp} --no-interactive --style=less --appDir=false --src=false --unitTestRunner=jest --linter=eslint`
     );
 
     await checkApp(lessApp, {
@@ -44,7 +44,7 @@ describe('Next.js Styles', () => {
     const scApp = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${scApp} --no-interactive --style=styled-components --appDir=false`
+      `generate @nx/next:app ${scApp} --no-interactive --style=styled-components --appDir=false --unitTestRunner=jest --linter=eslint`
     );
 
     await checkApp(scApp, {
@@ -56,7 +56,7 @@ describe('Next.js Styles', () => {
     const scAppWithAppRouter = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${scAppWithAppRouter} --no-interactive --style=styled-components --appDir=true`
+      `generate @nx/next:app ${scAppWithAppRouter} --no-interactive --style=styled-components --appDir=true --unitTestRunner=jest --linter=eslint`
     );
 
     await checkApp(scAppWithAppRouter, {
@@ -68,7 +68,7 @@ describe('Next.js Styles', () => {
     const emotionApp = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${emotionApp} --no-interactive --style=@emotion/styled --appDir=false`
+      `generate @nx/next:app ${emotionApp} --no-interactive --style=@emotion/styled --appDir=false --unitTestRunner=jest --linter=eslint`
     );
 
     await checkApp(emotionApp, {
@@ -83,7 +83,7 @@ describe('Next.js Styles', () => {
       const tailwindApp = uniq('app');
 
       runCLI(
-        `generate @nx/next:app ${tailwindApp} --no-interactive --style=tailwind --appDir=false --src=false`
+        `generate @nx/next:app ${tailwindApp} --no-interactive --style=tailwind --appDir=false --src=false --unitTestRunner=jest --linter=eslint`
       );
 
       await checkApp(tailwindApp, {
@@ -107,7 +107,7 @@ describe('Next.js Styles', () => {
       const tailwindApp = uniq('app');
 
       runCLI(
-        `generate @nx/next:app ${tailwindApp} --no-interactive --style=tailwind --appDir=true --src=false`
+        `generate @nx/next:app ${tailwindApp} --no-interactive --style=tailwind --appDir=true --src=false --unitTestRunner=jest --linter=eslint`
       );
 
       await checkApp(tailwindApp, {
diff --git a/e2e/next/src/next.test.ts b/e2e/next/src/next.test.ts
index 5cc90aeaa6a859..fcf104e28b9f14 100644
--- a/e2e/next/src/next.test.ts
+++ b/e2e/next/src/next.test.ts
@@ -37,7 +37,9 @@ describe('Next.js Applications', () => {
     const appName = uniq('app1');
     const libName = uniq('@my-org/lib1');
 
-    runCLI(`generate @nx/next:app ${appName} --no-interactive`);
+    runCLI(
+      `generate @nx/next:app ${appName} --no-interactive --linter=eslint --unitTestRunner=jest`
+    );
 
     // check files are generated without the layout directory ("apps/") and
     // using the project name as the directory when no directory is provided
@@ -52,7 +54,9 @@ describe('Next.js Applications', () => {
       `Successfully ran target test for project ${appName}`
     );
 
-    runCLI(`generate @nx/next:lib ${libName} --buildable --no-interactive`);
+    runCLI(
+      `generate @nx/next:lib ${libName} --buildable --no-interactive --linter=eslint --unitTestRunner=jest`
+    );
 
     // check files are generated without the layout directory ("libs/") and
     // using the project name as the directory when no directory is provided
@@ -67,7 +71,7 @@ describe('Next.js Applications', () => {
     const appName = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${appName} --no-interactive --style=css --appDir=false`
+      `generate @nx/next:app ${appName} --no-interactive --style=css --appDir=false --linter=eslint --unitTestRunner=jest`
     );
 
     checkFilesDoNotExist(`${appName}/.next/build-manifest.json`);
@@ -82,7 +86,7 @@ describe('Next.js Applications', () => {
     const appName = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${appName} --no-interactive --js --appDir=false --e2eTestRunner=playwright`
+      `generate @nx/next:app ${appName} --no-interactive --js --appDir=false --e2eTestRunner=playwright --linter=eslint --unitTestRunner=jest`
     );
 
     checkFilesExist(`${appName}/src/pages/index.js`);
@@ -97,7 +101,7 @@ describe('Next.js Applications', () => {
     const libName = uniq('lib');
 
     runCLI(
-      `generate @nx/next:lib ${libName} --no-interactive --style=none --js`
+      `generate @nx/next:lib ${libName} --no-interactive --style=none --js --linter=eslint --unitTestRunner=jest`
     );
 
     const mainPath = `${appName}/src/pages/index.js`;
@@ -133,7 +137,9 @@ describe('Next.js Applications', () => {
   it('should support --no-swc flag', async () => {
     const appName = uniq('app');
 
-    runCLI(`generate @nx/next:app ${appName} --no-interactive --no-swc`);
+    runCLI(
+      `generate @nx/next:app ${appName} --no-interactive --no-swc --linter=eslint --unitTestRunner=jest`
+    );
 
     // Next.js enables SWC when custom .babelrc is not provided.
     checkFilesExist(`${appName}/.babelrc`);
@@ -148,7 +154,9 @@ describe('Next.js Applications', () => {
   it('should support --custom-server flag (swc)', async () => {
     const appName = uniq('app');
 
-    runCLI(`generate @nx/next:app ${appName} --no-interactive --custom-server`);
+    runCLI(
+      `generate @nx/next:app ${appName} --no-interactive --custom-server --linter=eslint --unitTestRunner=jest`
+    );
 
     checkFilesExist(`${appName}/server/main.ts`);
 
@@ -165,7 +173,7 @@ describe('Next.js Applications', () => {
     const appName = uniq('app');
 
     runCLI(
-      `generate @nx/next:app ${appName} --swc=false --no-interactive --custom-server`
+      `generate @nx/next:app ${appName} --swc=false --no-interactive --custom-server --linter=eslint --unitTestRunner=jest`
     );
 
     checkFilesExist(`${appName}/server/main.ts`);
@@ -182,7 +190,9 @@ describe('Next.js Applications', () => {
   it('should run e2e-ci test', async () => {
     const appName = uniq('app');
 
-    runCLI(`generate @nx/next:app ${appName} --no-interactive --style=css`);
+    runCLI(
+      `generate @nx/next:app ${appName} --no-interactive --style=css --linter=eslint --unitTestRunner=jest`
+    );
 
     if (runE2ETests('playwright')) {
       const e2eResults = runCLI(`e2e-ci ${appName}-e2e --verbose`, {
@@ -202,9 +212,11 @@ describe('Next.js Applications', () => {
     const appName = uniq('app');
     const pagesAppName = uniq('pages-app');
 
-    runCLI(`generate @nx/next:app ${appName} --style=css --no-interactive`);
     runCLI(
-      `generate @nx/next:app ${pagesAppName} --appDir=false --style=css --no-interactive`
+      `generate @nx/next:app ${appName} --style=css --no-interactive --linter=eslint --unitTestRunner=jest`
+    );
+    runCLI(
+      `generate @nx/next:app ${pagesAppName} --appDir=false --style=css --no-interactive --linter=eslint --unitTestRunner=jest`
     );
 
     const appDirNextEnv = `${appName}/next-env.d.ts`;
diff --git a/e2e/nx/src/workspace-legacy.test.ts b/e2e/nx/src/workspace-legacy.test.ts
index ae7c96ec6f5f65..f3283e7fcf6e2d 100644
--- a/e2e/nx/src/workspace-legacy.test.ts
+++ b/e2e/nx/src/workspace-legacy.test.ts
@@ -19,7 +19,7 @@ describe('@nx/workspace:convert-to-monorepo', () => {
   it('should convert a standalone webpack and jest react project to a monorepo (legacy)', async () => {
     const reactApp = uniq('reactapp');
     runCLI(
-      `generate @nx/react:app --name=${reactApp} --directory="." --bundler=webpack --unitTestRunner=jest --e2eTestRunner=cypress --no-interactive`,
+      `generate @nx/react:app --name=${reactApp} --directory="." --bundler=webpack --unitTestRunner=jest --e2eTestRunner=cypress --no-interactive --linter=eslint`,
       {
         env: {
           NX_ADD_PLUGINS: 'false',
diff --git a/e2e/nx/src/workspace.test.ts b/e2e/nx/src/workspace.test.ts
index 14f853054d1cce..6c6b1fb85e08c9 100644
--- a/e2e/nx/src/workspace.test.ts
+++ b/e2e/nx/src/workspace.test.ts
@@ -32,7 +32,7 @@ describe('@nx/workspace:infer-targets', () => {
     // default case, everything is generated with crystal, everything should be skipped
     const remixApp = uniq('remix');
     runCLI(
-      `generate @nx/remix:app apps/${remixApp} --unitTestRunner jest --e2eTestRunner=playwright --no-interactive`
+      `generate @nx/remix:app apps/${remixApp} --linter eslint --unitTestRunner jest --e2eTestRunner=playwright --no-interactive`
     );
 
     const output = runCLI(`generate infer-targets --no-interactive --verbose`);
@@ -70,7 +70,7 @@ describe('@nx/workspace:infer-targets', () => {
     // default case, everything is generated with crystal, relevant plugins should be skipped
     const remixApp = uniq('remix');
     runCLI(
-      `generate @nx/remix:app apps/${remixApp} --unitTestRunner jest --e2eTestRunner=playwright --no-interactive`
+      `generate @nx/remix:app apps/${remixApp} --linter eslint --unitTestRunner jest --e2eTestRunner=playwright --no-interactive`
     );
 
     const output = runCLI(
@@ -116,7 +116,7 @@ describe('@nx/workspace:infer-targets', () => {
     // even if we make sure there are executors for remix & remix-e2e, only remix conversions will run with --project option
     const remixApp = uniq('remix');
     runCLI(
-      `generate @nx/remix:app apps/${remixApp} --unitTestRunner jest --e2eTestRunner=playwright --no-interactive`
+      `generate @nx/remix:app apps/${remixApp} --linter eslint --unitTestRunner jest --e2eTestRunner=playwright --no-interactive`
     );
 
     updateJson('nx.json', (json) => {
@@ -167,7 +167,7 @@ describe('@nx/workspace:convert-to-monorepo', () => {
   it('should be convert a standalone vite and playwright react project to a monorepo', async () => {
     const reactApp = uniq('reactapp');
     runCLI(
-      `generate @nx/react:app --name=${reactApp} --directory="." --rootProject=true --bundler=vite --unitTestRunner vitest --e2eTestRunner=playwright --no-interactive`
+      `generate @nx/react:app --name=${reactApp} --directory="." --rootProject=true --linter eslint --bundler=vite --unitTestRunner vitest --e2eTestRunner=playwright --no-interactive`
     );
 
     runCLI('generate @nx/workspace:convert-to-monorepo --no-interactive');
diff --git a/e2e/react-native/src/react-native-legacy.test.ts b/e2e/react-native/src/react-native-legacy.test.ts
index 4b5186a01a1393..4032caf85f5227 100644
--- a/e2e/react-native/src/react-native-legacy.test.ts
+++ b/e2e/react-native/src/react-native-legacy.test.ts
@@ -39,10 +39,10 @@ describe('@nx/react-native (legacy)', () => {
       return nxJson;
     });
     runCLI(
-      `generate @nx/react-native:application ${appName} --directory=apps/${appName} --bunlder=webpack --e2eTestRunner=cypress --install=false --no-interactive`
+      `generate @nx/react-native:application ${appName} --directory=apps/${appName} --bundler=webpack --e2eTestRunner=cypress --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     runCLI(
-      `generate @nx/react-native:library ${libName} --directory=libs/${libName} --buildable --publishable --importPath=${proj}/${libName} --no-interactive`
+      `generate @nx/react-native:library ${libName} --directory=libs/${libName} --buildable --publishable --importPath=${proj}/${libName} --no-interactive --unitTestRunner=jest --linter=eslint`
     );
   });
   afterAll(() => {
@@ -265,7 +265,7 @@ describe('@nx/react-native (legacy)', () => {
     const libName = uniq('@my-org/lib1');
 
     runCLI(
-      `generate @nx/react-native:application ${appName} --install=false --no-interactive`
+      `generate @nx/react-native:application ${appName} --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
     );
 
     // check files are generated without the layout directory ("apps/") and
@@ -274,7 +274,9 @@ describe('@nx/react-native (legacy)', () => {
     // check tests pass
     expect(() => runCLI(`test ${appName}`)).not.toThrow();
 
-    runCLI(`generate @nx/react-native:library ${libName} --buildable`);
+    runCLI(
+      `generate @nx/react-native:library ${libName} --buildable --unitTestRunner=jest --linter=eslint`
+    );
 
     // check files are generated without the layout directory ("libs/") and
     // using the project name as the directory when no directory is provided
@@ -286,7 +288,7 @@ describe('@nx/react-native (legacy)', () => {
   it('should run build with vite bundler and e2e with playwright', async () => {
     const appName2 = uniq('my-app');
     runCLI(
-      `generate @nx/react-native:application ${appName2} --directory=apps/${appName2} --bundler=vite --e2eTestRunner=playwright --install=false --no-interactive`
+      `generate @nx/react-native:application ${appName2} --directory=apps/${appName2} --bundler=vite --e2eTestRunner=playwright --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     expect(() => runCLI(`build ${appName2}`)).not.toThrow();
     if (runE2ETests()) {
diff --git a/e2e/react-native/src/react-native.test.ts b/e2e/react-native/src/react-native.test.ts
index 28cac4386c3b1b..544c01d279ef20 100644
--- a/e2e/react-native/src/react-native.test.ts
+++ b/e2e/react-native/src/react-native.test.ts
@@ -18,7 +18,7 @@ describe('@nx/react-native', () => {
     newProject();
     appName = uniq('app');
     runCLI(
-      `generate @nx/react-native:app ${appName} --install=false --no-interactive`
+      `generate @nx/react-native:app ${appName} --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
     );
   });
 
@@ -115,7 +115,7 @@ describe('@nx/react-native', () => {
   it('should run build with vite bundler and e2e with playwright', async () => {
     const appName2 = uniq('my-app');
     runCLI(
-      `generate @nx/react-native:application ${appName2} --directory=apps/${appName2} --bundler=vite --e2eTestRunner=playwright --install=false --no-interactive`
+      `generate @nx/react-native:application ${appName2} --directory=apps/${appName2} --bundler=vite --e2eTestRunner=playwright --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     expect(() => runCLI(`build ${appName2}`)).not.toThrow();
     if (runE2ETests()) {
diff --git a/e2e/react/src/react-vite.test.ts b/e2e/react/src/react-vite.test.ts
index 29193e84965a15..ec3d4770dc8962 100644
--- a/e2e/react/src/react-vite.test.ts
+++ b/e2e/react/src/react-vite.test.ts
@@ -22,7 +22,7 @@ describe('Build React applications and libraries with Vite', () => {
     const viteApp = uniq('viteapp');
 
     runCLI(
-      `generate @nx/react:app apps/${viteApp} --bundler=vite --compiler=babel --unitTestRunner=vitest --no-interactive`
+      `generate @nx/react:app apps/${viteApp} --bundler=vite --compiler=babel --unitTestRunner=vitest --no-interactive --linter=eslint`
     );
 
     const appTestResults = await runCLIAsync(`test ${viteApp}`);
@@ -43,7 +43,7 @@ describe('Build React applications and libraries with Vite', () => {
     const viteApp = uniq('viteapp');
 
     runCLI(
-      `generate @nx/react:app apps/${viteApp} --bundler=vite --compiler=swc --unitTestRunner=vitest --no-interactive`
+      `generate @nx/react:app apps/${viteApp} --bundler=vite --compiler=swc --unitTestRunner=vitest --no-interactive --linter=eslint`
     );
 
     const appTestResults = await runCLIAsync(`test ${viteApp}`);
@@ -65,7 +65,7 @@ describe('Build React applications and libraries with Vite', () => {
     const viteLib = uniq('vitelib');
 
     runCLI(
-      `generate @nx/react:app apps/${viteApp} --bundler=vite --unitTestRunner=vitest --inSourceTests --no-interactive`
+      `generate @nx/react:app apps/${viteApp} --bundler=vite --unitTestRunner=vitest --inSourceTests --no-interactive --linter=eslint`
     );
     expect(() => {
       checkFilesExist(`apps/${viteApp}/src/app/app.spec.tsx`);
@@ -85,7 +85,7 @@ describe('Build React applications and libraries with Vite', () => {
     checkFilesExist(`dist/apps/${viteApp}/index.html`);
 
     runCLI(
-      `generate @nx/react:lib libs/${viteLib} --bundler=vite --inSourceTests --unitTestRunner=vitest --no-interactive`
+      `generate @nx/react:lib libs/${viteLib} --bundler=vite --inSourceTests --unitTestRunner=vitest --no-interactive --linter=eslint`
     );
     expect(() => {
       checkFilesExist(`libs/${viteLib}/src/lib/${viteLib}.spec.tsx`);
@@ -125,7 +125,7 @@ describe('Build React applications and libraries with Vite', () => {
     const viteLib = uniq('vitelib');
 
     runCLI(
-      `generate @nx/react:lib libs/${viteLib} --bundler=vite --no-interactive --unit-test-runner=none`
+      `generate @nx/react:lib libs/${viteLib} --bundler=vite --no-interactive --unit-test-runner=none --linter=eslint`
     );
 
     await runCLIAsync(`build ${viteLib}`);
@@ -139,7 +139,7 @@ describe('Build React applications and libraries with Vite', () => {
     // Convert non-buildable lib to buildable one
     const nonBuildableLib = uniq('nonbuildablelib');
     runCLI(
-      `generate @nx/react:lib libs/${nonBuildableLib} --no-interactive --unitTestRunner=jest`
+      `generate @nx/react:lib libs/${nonBuildableLib} --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     runCLI(
       `generate @nx/vite:configuration ${nonBuildableLib} --uiFramework=react --no-interactive`
@@ -157,7 +157,7 @@ describe('Build React applications and libraries with Vite', () => {
     const viteApp = uniq('viteapp');
 
     runCLI(
-      `generate @nx/react:app apps/${viteApp} --bundler=vite --unitTestRunner=jest --no-interactive`
+      `generate @nx/react:app apps/${viteApp} --bundler=vite --unitTestRunner=jest --no-interactive --linter=eslint`
     );
 
     const appTestResults = await runCLIAsync(`test ${viteApp}`);
diff --git a/e2e/react/src/react.test.ts b/e2e/react/src/react.test.ts
index 08120d47774e2e..531703008168ad 100644
--- a/e2e/react/src/react.test.ts
+++ b/e2e/react/src/react.test.ts
@@ -34,10 +34,10 @@ describe('React Applications', () => {
       const libName = uniq('lib');
 
       runCLI(
-        `generate @nx/react:app apps/${appName} --name=${appName} --bundler=vite --no-interactive --skipFormat`
+        `generate @nx/react:app apps/${appName} --name=${appName} --bundler=vite --no-interactive --skipFormat --linter=eslint --unitTestRunner=vitest`
       );
       runCLI(
-        `generate @nx/react:lib libs/${libName} --bundler=none --no-interactive --unit-test-runner=vitest --skipFormat`
+        `generate @nx/react:lib libs/${libName} --bundler=none --no-interactive --unit-test-runner=vitest --skipFormat --linter=eslint`
       );
 
       // Library generated with Vite
@@ -68,10 +68,10 @@ describe('React Applications', () => {
       const libName = uniq('lib');
 
       runCLI(
-        `generate @nx/react:app ${appName} --bundler=rspack --unit-test-runner=vitest --no-interactive --skipFormat`
+        `generate @nx/react:app ${appName} --bundler=rspack --unit-test-runner=vitest --no-interactive --skipFormat --linter=eslint`
       );
       runCLI(
-        `generate @nx/react:lib ${libName} --bundler=none --no-interactive --unit-test-runner=vitest --skipFormat`
+        `generate @nx/react:lib ${libName} --bundler=none --no-interactive --unit-test-runner=vitest --skipFormat --linter=eslint`
       );
 
       // Library generated with Vite
@@ -109,13 +109,13 @@ describe('React Applications', () => {
       const redSvg = `<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" viewBox="0 0 30 30"><rect x="10" y="10" width="10" height="10" fill="red"/></svg>`;
 
       runCLI(
-        `generate @nx/react:app apps/${appName} --style=css --bundler=webpack --unit-test-runner=jest --no-interactive --skipFormat`
+        `generate @nx/react:app apps/${appName} --style=css --bundler=webpack --unit-test-runner=jest --no-interactive --skipFormat --linter=eslint`
       );
       runCLI(
-        `generate @nx/react:lib libs/${libName} --style=css --no-interactive --unit-test-runner=jest --skipFormat`
+        `generate @nx/react:lib libs/${libName} --style=css --no-interactive --unit-test-runner=jest --skipFormat --linter=eslint`
       );
       runCLI(
-        `generate @nx/react:lib libs/${libWithNoComponents} --no-interactive --no-component --unit-test-runner=jest --skipFormat`
+        `generate @nx/react:lib libs/${libWithNoComponents} --no-interactive --no-component --unit-test-runner=jest --skipFormat --linter=eslint`
       );
 
       // Libs should not include package.json by default
@@ -201,7 +201,7 @@ describe('React Applications', () => {
       const appName = uniq('app');
 
       runCLI(
-        `generate @nx/react:app apps/${appName} --routing --bundler=webpack --no-interactive --skipFormat`
+        `generate @nx/react:app apps/${appName} --routing --bundler=webpack --no-interactive --skipFormat --linter=eslint --unitTestRunner=jest`
       );
 
       runCLI(`build ${appName}`);
@@ -218,7 +218,7 @@ describe('React Applications', () => {
       const libName = uniq('lib');
 
       runCLI(
-        `g @nx/react:app apps/${appName} --bundler=webpack --no-interactive --skipFormat`
+        `g @nx/react:app apps/${appName} --bundler=webpack --no-interactive --skipFormat --unitTestRunner=jest --linter=eslint`
       );
       runCLI(
         `g @nx/react:redux apps/${appName}/src/app/lemon/lemon --skipFormat`
@@ -254,7 +254,7 @@ describe('React Applications', () => {
       const libName = uniq('@my-org/lib1');
 
       runCLI(
-        `generate @nx/react:app ${appName} --bundler=webpack --no-interactive --skipFormat`
+        `generate @nx/react:app ${appName} --bundler=webpack --no-interactive --skipFormat --linter=eslint --unitTestRunner=jest`
       );
 
       // check files are generated without the layout directory ("apps/") and
@@ -271,7 +271,7 @@ describe('React Applications', () => {
       );
 
       runCLI(
-        `generate @nx/react:lib ${libName} --unit-test-runner=jest --buildable --no-interactive --skipFormat`
+        `generate @nx/react:lib ${libName} --unit-test-runner=jest --buildable --no-interactive --skipFormat --linter=eslint`
       );
 
       // check files are generated without the layout directory ("libs/") and
@@ -293,7 +293,7 @@ describe('React Applications', () => {
       xit('should support styled-jsx', async () => {
         const appName = uniq('app');
         runCLI(
-          `generate @nx/react:app ${appName} --style=styled-jsx --bundler=vite --no-interactive --skipFormat`
+          `generate @nx/react:app ${appName} --style=styled-jsx --bundler=vite --no-interactive --skipFormat --linter=eslint --unitTestRunner=vitest`
         );
 
         // update app to use styled-jsx
@@ -342,7 +342,7 @@ describe('React Applications', () => {
       it('should support tailwind', async () => {
         const appName = uniq('app');
         runCLI(
-          `generate @nx/react:app apps/${appName} --style=tailwind --bundler=vite --no-interactive --skipFormat`
+          `generate @nx/react:app apps/${appName} --style=tailwind --bundler=vite --no-interactive --skipFormat --linter=eslint --unitTestRunner=vitest`
         );
 
         // update app to use styled-jsx
@@ -386,7 +386,7 @@ describe('React Applications', () => {
       it('should be formatted on freshly created apps', async () => {
         const appName = uniq('app');
         runCLI(
-          `generate @nx/react:app ${appName} --bundler=webpack --no-interactive`
+          `generate @nx/react:app ${appName} --bundler=webpack --no-interactive --linter=eslint --unitTestRunner=jest`
         );
 
         const stdout = runCLI(`format:check --projects=${appName}`, {
@@ -416,15 +416,15 @@ describe('React Applications', () => {
       const plainJsLib = uniq('jslib');
 
       runCLI(
-        `generate @nx/react:app apps/${appName} --bundler=webpack --unit-test-runner=jest --no-interactive --js --skipFormat`
+        `generate @nx/react:app apps/${appName} --bundler=webpack --unit-test-runner=jest --no-interactive --js --skipFormat --linter=eslint`
       );
       runCLI(
-        `generate @nx/react:lib libs/${libName} --no-interactive --js --unit-test-runner=none --skipFormat`
+        `generate @nx/react:lib libs/${libName} --no-interactive --js --unit-test-runner=none --skipFormat --linter=eslint`
       );
       // Make sure plain JS libs can be imported as well.
       // There was an issue previously: https://github.com/nrwl/nx/issues/10990
       runCLI(
-        `generate @nx/js:lib libs/${plainJsLib} --js --unit-test-runner=none --bundler=none --compiler=tsc --no-interactive --skipFormat`
+        `generate @nx/js:lib libs/${plainJsLib} --js --unit-test-runner=none --bundler=none --compiler=tsc --no-interactive --skipFormat --linter=eslint`
       );
 
       const mainPath = `apps/${appName}/src/main.js`;
@@ -450,7 +450,7 @@ describe('React Applications', () => {
     `('should support global and css modules', async ({ style }) => {
       const appName = uniq('app');
       runCLI(
-        `generate @nx/react:app apps/${appName} --style=${style} --bundler=webpack --no-interactive --skipFormat`
+        `generate @nx/react:app apps/${appName} --style=${style} --bundler=webpack --no-interactive --skipFormat --linter=eslint --unitTestRunner=jest`
       );
 
       // make sure stylePreprocessorOptions works
diff --git a/e2e/remix/src/nx-remix.test.ts b/e2e/remix/src/nx-remix.test.ts
index d96addeb6f5036..4066485a9788bb 100644
--- a/e2e/remix/src/nx-remix.test.ts
+++ b/e2e/remix/src/nx-remix.test.ts
@@ -26,7 +26,9 @@ describe('Remix E2E Tests', () => {
 
     it('should not cause peer dependency conflicts', async () => {
       const plugin = uniq('remix');
-      runCLI(`generate @nx/remix:app ${plugin}`);
+      runCLI(
+        `generate @nx/remix:app ${plugin} --linter=eslint --unitTestRunner=vitest`
+      );
 
       await runCommandAsync('npm install');
     }, 120000);
@@ -43,7 +45,9 @@ describe('Remix E2E Tests', () => {
 
     it('should create app', async () => {
       const plugin = uniq('remix');
-      runCLI(`generate @nx/remix:app ${plugin}`);
+      runCLI(
+        `generate @nx/remix:app ${plugin} --linter=eslint --unitTestRunner=vitest`
+      );
 
       const buildResult = runCLI(`build ${plugin}`);
       expect(buildResult).toContain('Successfully ran target build');
@@ -56,7 +60,7 @@ describe('Remix E2E Tests', () => {
       it('should create src in the specified directory', async () => {
         const plugin = uniq('remix');
         runCLI(
-          `generate @nx/remix:app --name=${plugin} --directory=subdir --rootProject=false --no-interactive`
+          `generate @nx/remix:app --name=${plugin} --directory=subdir --rootProject=false --no-interactive --linter=eslint --unitTestRunner=vitest`
         );
 
         const result = runCLI(`build ${plugin}`);
@@ -69,7 +73,7 @@ describe('Remix E2E Tests', () => {
       it('should add tags to the project', async () => {
         const plugin = uniq('remix');
         runCLI(
-          `generate @nx/remix:app apps/${plugin} --tags e2etag,e2ePackage`
+          `generate @nx/remix:app apps/${plugin} --tags e2etag,e2ePackage --linter=eslint --unitTestRunner=vitest`
         );
         const project = readJson(`apps/${plugin}/project.json`);
         expect(project.tags).toEqual(['e2etag', 'e2ePackage']);
@@ -79,7 +83,9 @@ describe('Remix E2E Tests', () => {
     describe('--js', () => {
       it('should create js app and build correctly', async () => {
         const plugin = uniq('remix');
-        runCLI(`generate @nx/remix:app ${plugin} --js=true`);
+        runCLI(
+          `generate @nx/remix:app ${plugin} --js=true --linter=eslint --unitTestRunner=vitest`
+        );
 
         const result = runCLI(`build ${plugin}`);
         expect(result).toContain('Successfully ran target build');
@@ -89,7 +95,9 @@ describe('Remix E2E Tests', () => {
     describe('--unitTestRunner', () => {
       it('should generate a library with vitest and test correctly', async () => {
         const plugin = uniq('remix');
-        runCLI(`generate @nx/remix:library ${plugin} --unitTestRunner=vitest`);
+        runCLI(
+          `generate @nx/remix:library ${plugin} --unitTestRunner=vitest --linter=eslint`
+        );
 
         const result = runCLI(`test ${plugin}`);
         expect(result).toContain(`Successfully ran target test`);
@@ -98,11 +106,11 @@ describe('Remix E2E Tests', () => {
       it('should generate a library with jest and test correctly', async () => {
         const reactapp = uniq('react');
         runCLI(
-          `generate @nx/react:application ${reactapp} --unitTestRunner=jest`
+          `generate @nx/react:application ${reactapp} --unitTestRunner=jest --linter=eslint`
         );
         const plugin = uniq('remix');
         runCLI(
-          `generate @nx/remix:application ${plugin} --unitTestRunner=jest`
+          `generate @nx/remix:application ${plugin} --unitTestRunner=jest --linter=eslint`
         );
 
         const result = runCLI(`test ${plugin}`);
@@ -118,7 +126,7 @@ describe('Remix E2E Tests', () => {
 
       beforeAll(async () => {
         runCLI(
-          `generate @nx/remix:app apps/${plugin} --tags e2etag,e2ePackage`
+          `generate @nx/remix:app apps/${plugin} --tags e2etag,e2ePackage --linter=eslint --unitTestRunner=vitest`
         );
       }, 120000);
 
diff --git a/e2e/rspack/tests/rspack.spec.ts b/e2e/rspack/tests/rspack.spec.ts
index c9e0d1be30677c..732728605d35eb 100644
--- a/e2e/rspack/tests/rspack.spec.ts
+++ b/e2e/rspack/tests/rspack.spec.ts
@@ -67,9 +67,9 @@ describe('rspack e2e', () => {
     // Make sure expected files are present.
     /**
      * The files that are generated are:
-     * ["3rdpartylicenses.txt", "assets", "favicon.ico", "index.html", "main.bf7851e6.js", "runtime.e4294127.js"]
+     * ["assets", "favicon.ico", "index.html", "main.bf7851e6.js", "runtime.e4294127.js"]
      */
-    expect(listFiles(`dist/${project}`)).toHaveLength(6);
+    expect(listFiles(`dist/${project}`)).toHaveLength(5);
 
     result = runCLI(`test ${project}`);
     expect(result).toContain('Successfully ran target test');
@@ -87,7 +87,7 @@ describe('rspack e2e', () => {
       env: { NODE_ENV: 'production' },
     });
     expect(result).toContain('Successfully ran target build');
-    expect(listFiles(`dist/${project}`)).toHaveLength(6); // same length as before
+    expect(listFiles(`dist/${project}`)).toHaveLength(5); // same length as before
 
     // Generate a new app and check that the files are correct
     const app2 = uniq('app2');
@@ -120,7 +120,7 @@ describe('rspack e2e', () => {
     });
     expect(result).toContain('Successfully ran target build');
     // Make sure expected files are present.
-    expect(listFiles(`dist/${app2}`)).toHaveLength(6);
+    expect(listFiles(`dist/${app2}`)).toHaveLength(5);
 
     result = runCLI(`test ${app2}`);
     expect(result).toContain('Successfully ran target test');
@@ -139,11 +139,11 @@ describe('rspack e2e', () => {
     result = runCLI(`build ${app3}`);
     expect(result).toContain('Successfully ran target build');
     // Make sure expected files are present.
-    expect(listFiles(`dist/${app3}`)).toHaveLength(3);
+    expect(listFiles(`dist/${app3}`)).toHaveLength(2);
 
     result = runCLI(`build ${app3} --generatePackageJson=true`);
     expect(result).toContain('Successfully ran target build');
     // Make sure expected files are present.
-    expect(listFiles(`dist/${app3}`)).toHaveLength(5);
+    expect(listFiles(`dist/${app3}`)).toHaveLength(4);
   }, 200_000);
 });
diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts
index 25bf031ba8554e..05406751870dfb 100644
--- a/e2e/utils/create-project-utils.ts
+++ b/e2e/utils/create-project-utils.ts
@@ -222,6 +222,8 @@ export function runCreateWorkspace(
     docker,
     nextAppDir,
     nextSrcDir,
+    linter = 'eslint',
+    formatter = 'prettier',
     e2eTestRunner,
     ssr,
     framework,
@@ -241,7 +243,9 @@ export function runCreateWorkspace(
     docker?: boolean;
     nextAppDir?: boolean;
     nextSrcDir?: boolean;
+    linter?: 'none' | 'eslint';
     e2eTestRunner?: 'cypress' | 'playwright' | 'jest' | 'detox' | 'none';
+    formatter?: 'prettier' | 'none';
     ssr?: boolean;
     framework?: string;
     prefix?: string;
@@ -291,6 +295,14 @@ export function runCreateWorkspace(
     command += ` --package-manager=${packageManager}`;
   }
 
+  if (linter) {
+    command += ` --linter=${linter}`;
+  }
+
+  if (formatter) {
+    command += ` --formatter=${formatter}`;
+  }
+
   if (e2eTestRunner) {
     command += ` --e2eTestRunner=${e2eTestRunner}`;
   }
diff --git a/e2e/vite/src/vite-legacy.test.ts b/e2e/vite/src/vite-legacy.test.ts
index 33841fa4bdca30..cc0117dd520ec7 100644
--- a/e2e/vite/src/vite-legacy.test.ts
+++ b/e2e/vite/src/vite-legacy.test.ts
@@ -48,7 +48,9 @@ describe('Vite Plugin', () => {
 
       beforeAll(() => {
         myApp = uniq('my-app');
-        runCLI(`generate @nx/react:app ${myApp} --bundler=vite`);
+        runCLI(
+          `generate @nx/react:app ${myApp} --bundler=vite --unitTestRunner=vitest`
+        );
       });
 
       afterEach(() => {
@@ -95,7 +97,7 @@ describe('Vite Plugin', () => {
       beforeEach(() => {
         myApp = uniq('my-app');
         runCLI(
-          `generate @nx/web:app ${myApp} --bundler=vite --directory=${myApp}`
+          `generate @nx/web:app ${myApp} --bundler=vite --unitTestRunner=vitest --directory=${myApp}`
         );
       });
       it('should build application', async () => {
@@ -187,7 +189,7 @@ describe('Vite Plugin', () => {
         packages: ['@nx/react'],
       });
       runCLI(
-        `generate @nx/react:app ${app} --bundler=vite --no-interactive  --directory=${app}`
+        `generate @nx/react:app ${app} --bundler=vite --unitTestRunner=vitest --no-interactive  --directory=${app}`
       );
 
       // only this project will be directly used from dist
diff --git a/e2e/webpack/src/webpack.legacy.test.ts b/e2e/webpack/src/webpack.legacy.test.ts
index f1e5b9b63701cb..d50ca3a11b5c92 100644
--- a/e2e/webpack/src/webpack.legacy.test.ts
+++ b/e2e/webpack/src/webpack.legacy.test.ts
@@ -24,10 +24,10 @@ describe('Webpack Plugin (legacy)', () => {
       packages: ['@nx/react'],
     });
     runCLI(
-      `generate @nx/react:app ${appName} --bundler webpack --e2eTestRunner=cypress --rootProject --no-interactive`
+      `generate @nx/react:app ${appName} --bundler webpack --e2eTestRunner=cypress --rootProject --no-interactive --unitTestRunner=jest --linter=eslint`
     );
     runCLI(
-      `generate @nx/react:lib ${libName} --unitTestRunner jest --no-interactive`
+      `generate @nx/react:lib ${libName} --unitTestRunner jest --no-interactive --linter=eslint`
     );
   });
 
@@ -72,7 +72,9 @@ describe('Webpack Plugin (legacy)', () => {
   // Issue: https://github.com/nrwl/nx/issues/20179
   it('should allow main/styles entries to be spread within composePlugins() function (#20179)', () => {
     const appName = uniq('app');
-    runCLI(`generate @nx/web:app ${appName} --bundler webpack`);
+    runCLI(
+      `generate @nx/web:app ${appName} --bundler webpack --unitTestRunner=jest --linter=eslint`
+    );
 
     checkFilesExist(`${appName}/src/main.ts`);
     updateFile(`${appName}/src/main.ts`, `console.log('Hello');\n`);
@@ -109,7 +111,7 @@ describe('Webpack Plugin (legacy)', () => {
   it('should support standard webpack config with executors', () => {
     const appName = uniq('app');
     runCLI(
-      `generate @nx/web:app ${appName} --bundler webpack --e2eTestRunner=playwright`
+      `generate @nx/web:app ${appName} --bundler webpack --e2eTestRunner=playwright --unitTestRunner=jest --linter=eslint`
     );
     updateFile(
       `${appName}/src/main.ts`,
@@ -153,7 +155,7 @@ describe('Webpack Plugin (legacy)', () => {
     it('should convert withNx webpack config to a standard config using NxWebpackPlugin', () => {
       const appName = 'app3224373'; // Needs to be reserved so that the snapshot projectName matches
       runCLI(
-        `generate @nx/web:app ${appName} --bundler webpack --e2eTestRunner=playwright`
+        `generate @nx/web:app ${appName} --bundler webpack --e2eTestRunner=playwright --unitTestRunner=vitest --linter=eslint`
       );
       updateFile(
         `${appName}/src/main.ts`,
diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts
index 59911cdbf2a140..623e42a5d7ede9 100644
--- a/packages/create-nx-workspace/bin/create-nx-workspace.ts
+++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts
@@ -52,6 +52,9 @@ interface ReactArguments extends BaseArguments {
   nextAppDir: boolean;
   nextSrcDir: boolean;
   e2eTestRunner: 'none' | 'cypress' | 'playwright';
+  linter?: 'none' | 'eslint';
+  formatter?: 'none' | 'prettier';
+  workspaces?: boolean;
 }
 
 interface AngularArguments extends BaseArguments {
@@ -157,6 +160,15 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
             describe: chalk.dim`Bundler to be used to build the app.`,
             type: 'string',
           })
+          .option('workspaces', {
+            describe: chalk.dim`Use package manager workspaces.`,
+            type: 'boolean',
+            default: false,
+          })
+          .option('formatter', {
+            describe: chalk.dim`Code formatter to use.`,
+            type: 'string',
+          })
           .option('framework', {
             describe: chalk.dim`Framework option to be used with certain stacks.`,
             type: 'string',
@@ -440,6 +452,52 @@ async function determinePresetOptions(
   }
 }
 
+async function determineFormatterOptions(args: {
+  formatter?: 'none' | 'prettier';
+  interactive?: boolean;
+}) {
+  if (args.formatter) return args.formatter;
+  const reply = await enquirer.prompt<{ prettier: 'Yes' | 'No' }>([
+    {
+      name: 'prettier',
+      message: `Would you like to use Prettier for code formatting?`,
+      type: 'autocomplete',
+      choices: [
+        {
+          name: 'Yes',
+        },
+        {
+          name: 'No',
+        },
+      ],
+      initial: 1,
+      skip: !args.interactive || isCI(),
+    },
+  ]);
+  return reply.prettier === 'Yes' ? 'prettier' : 'none';
+}
+
+async function determineLinterOptions(args: { interactive?: boolean }) {
+  const reply = await enquirer.prompt<{ eslint: 'Yes' | 'No' }>([
+    {
+      name: 'eslint',
+      message: `Would you like to use ESLint?`,
+      type: 'autocomplete',
+      choices: [
+        {
+          name: 'Yes',
+        },
+        {
+          name: 'No',
+        },
+      ],
+      initial: 1,
+      skip: !args.interactive || isCI(),
+    },
+  ]);
+  return reply.eslint === 'Yes' ? 'eslint' : 'none';
+}
+
 async function determineNoneOptions(
   parsedArgs: yargs.Arguments<NoneArguments>
 ): Promise<Partial<NoneArguments>> {
@@ -448,26 +506,9 @@ async function determineNoneOptions(
     process.env.NX_ADD_PLUGINS !== 'false' &&
     process.env.NX_ADD_TS_PLUGIN !== 'false'
   ) {
-    const reply = await enquirer.prompt<{ prettier: 'Yes' | 'No' }>([
-      {
-        name: 'prettier',
-        message: `Would you like to use Prettier for code formatting?`,
-        type: 'autocomplete',
-        choices: [
-          {
-            name: 'Yes',
-          },
-          {
-            name: 'No',
-          },
-        ],
-        initial: 1,
-        skip: !parsedArgs.interactive || isCI(),
-      },
-    ]);
     return {
       preset: Preset.TS,
-      formatter: reply.prettier === 'Yes' ? 'prettier' : 'none',
+      formatter: await determineFormatterOptions(parsedArgs),
     };
   } else {
     let preset: Preset;
@@ -535,6 +576,10 @@ async function determineReactOptions(
   let e2eTestRunner: undefined | 'none' | 'cypress' | 'playwright' = undefined;
   let nextAppDir = false;
   let nextSrcDir = false;
+  let linter: undefined | 'none' | 'eslint';
+  let formatter: undefined | 'none' | 'prettier';
+
+  const workspaces = parsedArgs.workspaces ?? false;
 
   if (parsedArgs.preset && parsedArgs.preset !== Preset.React) {
     preset = parsedArgs.preset;
@@ -550,27 +595,25 @@ async function determineReactOptions(
   } else {
     const framework = await determineReactFramework(parsedArgs);
 
-    // React Native and Expo only support integrated monorepos for now.
-    // TODO(jack): Add standalone support for React Native and Expo.
-    const workspaceType =
-      framework === 'react-native' || framework === 'expo'
-        ? 'integrated'
-        : await determineStandaloneOrMonorepo();
+    const isStandalone =
+      workspaces || framework === 'react-native' || framework === 'expo'
+        ? false
+        : (await determineStandaloneOrMonorepo()) === 'standalone';
 
-    if (workspaceType === 'standalone') {
+    if (isStandalone) {
       appName = parsedArgs.name;
     } else {
       appName = await determineAppName(parsedArgs);
     }
 
     if (framework === 'nextjs') {
-      if (workspaceType === 'standalone') {
+      if (isStandalone) {
         preset = Preset.NextJsStandalone;
       } else {
         preset = Preset.NextJs;
       }
     } else if (framework === 'remix') {
-      if (workspaceType === 'standalone') {
+      if (isStandalone) {
         preset = Preset.RemixStandalone;
       } else {
         preset = Preset.RemixMonorepo;
@@ -580,7 +623,7 @@ async function determineReactOptions(
     } else if (framework === 'expo') {
       preset = Preset.Expo;
     } else {
-      if (workspaceType === 'standalone') {
+      if (isStandalone) {
         preset = Preset.ReactStandalone;
       } else {
         preset = Preset.ReactMonorepo;
@@ -657,6 +700,14 @@ async function determineReactOptions(
     style = reply.style;
   }
 
+  if (workspaces) {
+    linter = await determineLinterOptions(parsedArgs);
+    formatter = await determineFormatterOptions(parsedArgs);
+  } else {
+    linter = 'eslint';
+    formatter = 'prettier';
+  }
+
   return {
     preset,
     style,
@@ -665,6 +716,9 @@ async function determineReactOptions(
     nextAppDir,
     nextSrcDir,
     e2eTestRunner,
+    linter,
+    formatter,
+    workspaces,
   };
 }
 
diff --git a/packages/create-nx-workspace/src/create-workspace.ts b/packages/create-nx-workspace/src/create-workspace.ts
index 3d6cbf1d48192b..728238309a4b8c 100644
--- a/packages/create-nx-workspace/src/create-workspace.ts
+++ b/packages/create-nx-workspace/src/create-workspace.ts
@@ -8,6 +8,7 @@ import { setupCI } from './utils/ci/setup-ci';
 import { initializeGitRepo } from './utils/git/git';
 import { getPackageNameFromThirdPartyPreset } from './utils/preset/get-third-party-preset';
 import { mapErrorToBodyLines } from './utils/error-utils';
+import { Preset } from './utils/preset/preset';
 
 export async function createWorkspace<T extends CreateWorkspaceOptions>(
   preset: string,
@@ -30,12 +31,14 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
 
   const tmpDir = await createSandbox(packageManager);
 
+  const workspaceGlobs = getWorkspaceGlobsFromPreset(preset);
+
   // nx new requires a preset currently. We should probably make it optional.
   const directory = await createEmptyWorkspace<T>(
     tmpDir,
     name,
     packageManager,
-    { ...options, preset }
+    { ...options, preset, workspaceGlobs }
   );
 
   // If the preset is a third-party preset, we need to call createPreset to install it
@@ -96,3 +99,24 @@ export function extractConnectUrl(text: string): string | null {
   const match = text.match(urlPattern);
   return match ? match[0] : null;
 }
+
+function getWorkspaceGlobsFromPreset(preset: string): string[] {
+  // Should match how apps are created in `packages/workspace/src/generators/preset/preset.ts`.
+  switch (preset) {
+    case Preset.AngularMonorepo:
+    case Preset.Expo:
+    case Preset.Express:
+    case Preset.Nest:
+    case Preset.NextJs:
+    case Preset.NodeMonorepo:
+    case Preset.Nuxt:
+    case Preset.ReactNative:
+    case Preset.ReactMonorepo:
+    case Preset.RemixMonorepo:
+    case Preset.VueMonorepo:
+    case Preset.WebComponents:
+      return ['apps/**', 'packages/**'];
+    default:
+      return ['packages/**'];
+  }
+}
diff --git a/packages/cypress/src/generators/base-setup/files/tsconfig/ts-solution/__directory__/tsconfig.json__ext__ b/packages/cypress/src/generators/base-setup/files/tsconfig/ts-solution/__directory__/tsconfig.json__ext__
index 871e69aadc0b95..88dc50152e31ce 100644
--- a/packages/cypress/src/generators/base-setup/files/tsconfig/ts-solution/__directory__/tsconfig.json__ext__
+++ b/packages/cypress/src/generators/base-setup/files/tsconfig/ts-solution/__directory__/tsconfig.json__ext__
@@ -16,5 +16,6 @@
     "<%= offsetFromProjectRoot %>**/*.cy.js",
     <%_ if (jsx) { _%>"<%= offsetFromProjectRoot %>**/*.cy.jsx",<%_ } _%>
     "<%= offsetFromProjectRoot %>**/*.d.ts"
-  ]
+  ],
+  "exclude": ["dist"<% if (linter === 'eslint') { %>, "eslint.config.js"<% } %>]
 }
diff --git a/packages/cypress/src/generators/configuration/configuration.ts b/packages/cypress/src/generators/configuration/configuration.ts
index 096296f4e29441..3671a480b416ae 100644
--- a/packages/cypress/src/generators/configuration/configuration.ts
+++ b/packages/cypress/src/generators/configuration/configuration.ts
@@ -105,6 +105,26 @@ export async function configurationGeneratorInternal(
     addTarget(tree, opts, projectGraph);
   }
 
+  const projectTsConfigPath = joinPathFragments(
+    opts.projectRoot,
+    'tsconfig.json'
+  );
+  if (tree.exists(projectTsConfigPath)) {
+    updateJson(tree, projectTsConfigPath, (json) => {
+      // Cypress uses commonjs, unless the project is also using commonjs (or does not set "module" i.e. uses default of commonjs),
+      // then we need to set the moduleResolution to node10 or else Cypress will fail with TS5095 error.
+      // See: https://github.com/cypress-io/cypress/issues/27731
+      if (
+        (json.compilerOptions?.module ||
+          json.compilerOptions?.module !== 'commonjs') &&
+        json.compilerOptions?.moduleResolution
+      ) {
+        json.compilerOptions.moduleResolution = 'node10';
+      }
+      return json;
+    });
+  }
+
   const { root: projectRoot } = readProjectConfiguration(tree, options.project);
   const isTsSolutionSetup = isUsingTsSolutionSetup(tree);
   if (isTsSolutionSetup) {
@@ -201,6 +221,7 @@ In this case you need to provide a devServerTarget,'<projectName>:<targetName>[:
   return {
     ...options,
     bundler: options.bundler ?? 'webpack',
+    projectRoot: projectConfig.root,
     rootProject: options.rootProject ?? projectConfig.root === '.',
     linter,
     devServerTarget,
@@ -408,6 +429,9 @@ function createPackageJson(tree: Tree, options: NormalizedSchema) {
     name: importPath,
     version: '0.0.1',
     private: true,
+    nx: {
+      name: options.project,
+    },
   };
   writeJson(tree, packageJsonPath, packageJson);
 }
diff --git a/packages/detox/src/generators/application/application.ts b/packages/detox/src/generators/application/application.ts
index 3cd37e4d9998d7..9b42fdf537bf01 100644
--- a/packages/detox/src/generators/application/application.ts
+++ b/packages/detox/src/generators/application/application.ts
@@ -1,5 +1,5 @@
 import { formatFiles, runTasksInSerial, Tree } from '@nx/devkit';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { initGenerator as jsInitGenerator } from '@nx/js';
 
 import detoxInitGenerator from '../init/init';
 import { addGitIgnoreEntry } from './lib/add-git-ignore-entry';
@@ -21,7 +21,9 @@ export async function detoxApplicationGeneratorInternal(
   host: Tree,
   schema: Schema
 ) {
-  assertNotUsingTsSolutionSetup(host, 'detox', 'application');
+  const jsInitTask = await jsInitGenerator(host, {
+    skipFormat: true,
+  });
 
   const options = await normalizeOptions(host, schema);
 
@@ -40,7 +42,7 @@ export async function detoxApplicationGeneratorInternal(
     await formatFiles(host);
   }
 
-  return runTasksInSerial(initTask, lintingTask, depsTask);
+  return runTasksInSerial(jsInitTask, initTask, lintingTask, depsTask);
 }
 
 export default detoxApplicationGenerator;
diff --git a/packages/detox/src/generators/application/lib/add-project.ts b/packages/detox/src/generators/application/lib/add-project.ts
index c3f44f57b785ab..ebbdf53a98977c 100644
--- a/packages/detox/src/generators/application/lib/add-project.ts
+++ b/packages/detox/src/generators/application/lib/add-project.ts
@@ -1,8 +1,10 @@
 import {
   addProjectConfiguration,
+  joinPathFragments,
   readNxJson,
   TargetConfiguration,
   Tree,
+  writeJson,
 } from '@nx/devkit';
 import {
   expoBuildTarget,
@@ -11,6 +13,7 @@ import {
   reactNativeTestTarget,
 } from './get-targets';
 import { NormalizedSchema } from './normalize-options';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function addProject(host: Tree, options: NormalizedSchema) {
   const nxJson = readNxJson(host);
@@ -20,14 +23,28 @@ export function addProject(host: Tree, options: NormalizedSchema) {
       : p.plugin === '@nx/detox/plugin'
   );
 
-  addProjectConfiguration(host, options.e2eProjectName, {
-    root: options.e2eProjectRoot,
-    sourceRoot: `${options.e2eProjectRoot}/src`,
-    projectType: 'application',
-    targets: hasPlugin ? {} : getTargets(options),
-    tags: [],
-    implicitDependencies: [options.appProject],
-  });
+  if (isUsingTsSolutionSetup(host)) {
+    writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
+      name: options.e2eProjectName,
+      version: '0.0.1',
+      private: true,
+      nx: {
+        sourceRoot: `${options.e2eProjectRoot}/src`,
+        projectType: 'application',
+        targets: hasPlugin ? undefined : getTargets(options),
+        implicitDependencies: [options.appProject],
+      },
+    });
+  } else {
+    addProjectConfiguration(host, options.e2eProjectName, {
+      root: options.e2eProjectRoot,
+      sourceRoot: `${options.e2eProjectRoot}/src`,
+      projectType: 'application',
+      targets: hasPlugin ? {} : getTargets(options),
+      tags: [],
+      implicitDependencies: [options.appProject],
+    });
+  }
 }
 
 function getTargets(options: NormalizedSchema) {
diff --git a/packages/detox/src/generators/init/init.ts b/packages/detox/src/generators/init/init.ts
index a66360be9f4f24..543ea76ed86f9c 100644
--- a/packages/detox/src/generators/init/init.ts
+++ b/packages/detox/src/generators/init/init.ts
@@ -9,7 +9,6 @@ import {
   Tree,
 } from '@nx/devkit';
 import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { createNodes } from '../../plugins/plugin';
 import { detoxVersion, nxVersion } from '../../utils/versions';
 import { Schema } from './schema';
@@ -19,8 +18,6 @@ export function detoxInitGenerator(host: Tree, schema: Schema) {
 }
 
 export async function detoxInitGeneratorInternal(host: Tree, schema: Schema) {
-  assertNotUsingTsSolutionSetup(host, 'detox', 'init');
-
   const tasks: GeneratorCallback[] = [];
 
   const nxJson = readNxJson(host);
diff --git a/packages/eslint/src/generators/workspace-rules-project/workspace-rules-project.ts b/packages/eslint/src/generators/workspace-rules-project/workspace-rules-project.ts
index 6b99850a039a49..c1f85c66d3e1ad 100644
--- a/packages/eslint/src/generators/workspace-rules-project/workspace-rules-project.ts
+++ b/packages/eslint/src/generators/workspace-rules-project/workspace-rules-project.ts
@@ -90,6 +90,7 @@ export async function lintWorkspaceRulesProjectGenerator(
     join(workspaceLintPluginDir, 'tsconfig.spec.json'),
     (json) => {
       delete json.compilerOptions?.module;
+      delete json.compilerOptions?.moduleResolution;
 
       if (json.include) {
         json.include = json.include.map((v) => {
diff --git a/packages/expo/src/generators/application/application.spec.ts b/packages/expo/src/generators/application/application.spec.ts
index f51d0690f7c2c3..3753b0a2353587 100644
--- a/packages/expo/src/generators/application/application.spec.ts
+++ b/packages/expo/src/generators/application/application.spec.ts
@@ -6,6 +6,8 @@ import {
   readNxJson,
   readProjectConfiguration,
   Tree,
+  updateJson,
+  writeJson,
 } from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import { Linter } from '@nx/eslint';
@@ -327,4 +329,147 @@ describe('app', () => {
       `);
     });
   });
+
+  describe('TS solution setup', () => {
+    it('should add project references when using TS solution', async () => {
+      const tree = createTreeWithEmptyWorkspace();
+      tree.write('.gitignore', '');
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+
+      await expoApplicationGenerator(tree, {
+        directory: 'my-app',
+        displayName: 'myApp',
+        linter: Linter.EsLint,
+        e2eTestRunner: 'none',
+        skipFormat: false,
+        js: false,
+        unitTestRunner: 'jest',
+        addPlugin: true,
+      });
+
+      expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./my-app",
+          },
+        ]
+      `);
+      expect(readJson(tree, 'my-app/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowSyntheticDefaultImports": true,
+            "declaration": true,
+            "jsx": "react-native",
+            "lib": [
+              "dom",
+              "esnext",
+            ],
+            "moduleResolution": "node",
+            "resolveJsonModule": true,
+            "skipLibCheck": true,
+            "strict": true,
+          },
+          "extends": "../tsconfig.base.json",
+          "files": [],
+          "include": [],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+            {
+              "path": "./tsconfig.spec.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'my-app/tsconfig.app.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "noUnusedLocals": false,
+            "outDir": "out-tsc/my-app",
+            "rootDir": "src",
+            "types": [
+              "node",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "jest.config.ts",
+            "**/*.spec.ts",
+            "**/*.spec.tsx",
+            "src/test-setup.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.ts",
+            "eslint.config.js",
+            "eslint.config.cjs",
+            "eslint.config.mjs",
+          ],
+          "extends": "../tsconfig.base.json",
+          "files": [
+            "../node_modules/@nx/expo/typings/svg.d.ts",
+          ],
+          "include": [
+            "**/*.ts",
+            "**/*.tsx",
+            "**/*.js",
+            "**/*.jsx",
+          ],
+        }
+      `);
+      expect(readJson(tree, 'my-app/tsconfig.spec.json'))
+        .toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "noUnusedLocals": false,
+            "outDir": "./out-tsc/jest",
+            "types": [
+              "jest",
+              "node",
+            ],
+          },
+          "extends": "../tsconfig.base.json",
+          "files": [
+            "src/test-setup.ts",
+          ],
+          "include": [
+            "jest.config.ts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.js",
+            "src/**/*.spec.js",
+            "src/**/*.test.jsx",
+            "src/**/*.spec.jsx",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+          ],
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/expo/src/generators/application/application.ts b/packages/expo/src/generators/application/application.ts
index 058dc24445f304..4c971cbc324b12 100644
--- a/packages/expo/src/generators/application/application.ts
+++ b/packages/expo/src/generators/application/application.ts
@@ -6,7 +6,7 @@ import {
   Tree,
 } from '@nx/devkit';
 import { initGenerator as jsInitGenerator } from '@nx/js';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 import { addLinting } from '../../utils/add-linting';
 import { addJest } from '../../utils/add-jest';
@@ -36,16 +36,16 @@ export async function expoApplicationGeneratorInternal(
   host: Tree,
   schema: Schema
 ): Promise<GeneratorCallback> {
-  assertNotUsingTsSolutionSetup(host, 'expo', 'application');
-
-  const options = await normalizeOptions(host, schema);
-
   const tasks: GeneratorCallback[] = [];
   const jsInitTask = await jsInitGenerator(host, {
     ...schema,
     skipFormat: true,
+    addTsPlugin: schema.useTsSolution,
+    formatter: schema.formatter,
   });
 
+  const options = await normalizeOptions(host, schema);
+
   tasks.push(jsInitTask);
   const initTask = await initGenerator(host, { ...options, skipFormat: true });
   tasks.push(initTask);
@@ -80,6 +80,21 @@ export async function expoApplicationGeneratorInternal(
   tasks.push(e2eTask);
   addEasScripts(host);
 
+  updateTsconfigFiles(
+    host,
+    options.appProjectRoot,
+    'tsconfig.app.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+      noUnusedLocals: false,
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
diff --git a/packages/expo/src/generators/application/lib/add-e2e.ts b/packages/expo/src/generators/application/lib/add-e2e.ts
index 67d16a84e15c59..4734949259b301 100644
--- a/packages/expo/src/generators/application/lib/add-e2e.ts
+++ b/packages/expo/src/generators/application/lib/add-e2e.ts
@@ -1,10 +1,11 @@
-import { GeneratorCallback, Tree } from '@nx/devkit';
 import {
   addProjectConfiguration,
   ensurePackage,
-  getPackageManagerCommand,
+  GeneratorCallback,
   joinPathFragments,
   readNxJson,
+  Tree,
+  writeJson,
 } from '@nx/devkit';
 import { webStaticServeGenerator } from '@nx/web';
 
@@ -14,6 +15,7 @@ import { NormalizedSchema } from './normalize-options';
 import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
 import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
 import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function addE2e(
   tree: Tree,
@@ -40,14 +42,31 @@ export async function addE2e(
         typeof import('@nx/cypress')
       >('@nx/cypress', nxVersion);
 
-      addProjectConfiguration(tree, options.e2eProjectName, {
-        projectType: 'application',
-        root: options.e2eProjectRoot,
-        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-        targets: {},
-        implicitDependencies: [options.projectName],
-        tags: [],
-      });
+      if (isUsingTsSolutionSetup(tree)) {
+        writeJson(
+          tree,
+          joinPathFragments(options.e2eProjectRoot, 'package.json'),
+          {
+            name: options.e2eProjectName,
+            version: '0.0.1',
+            private: true,
+            nx: {
+              projectType: 'application',
+              sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+              implicitDependencies: [options.projectName],
+            },
+          }
+        );
+      } else {
+        addProjectConfiguration(tree, options.e2eProjectName, {
+          projectType: 'application',
+          root: options.e2eProjectRoot,
+          sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+          targets: {},
+          implicitDependencies: [options.projectName],
+          tags: [],
+        });
+      }
 
       const e2eTask = await configurationGenerator(tree, {
         ...options,
@@ -106,13 +125,30 @@ export async function addE2e(
       const { configurationGenerator } = ensurePackage<
         typeof import('@nx/playwright')
       >('@nx/playwright', nxVersion);
-      addProjectConfiguration(tree, options.e2eProjectName, {
-        projectType: 'application',
-        root: options.e2eProjectRoot,
-        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-        targets: {},
-        implicitDependencies: [options.projectName],
-      });
+      if (isUsingTsSolutionSetup(tree)) {
+        writeJson(
+          tree,
+          joinPathFragments(options.e2eProjectRoot, 'package.json'),
+          {
+            name: options.e2eProjectName,
+            version: '0.0.1',
+            private: true,
+            nx: {
+              projectType: 'application',
+              sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+              implicitDependencies: [options.projectName],
+            },
+          }
+        );
+      } else {
+        addProjectConfiguration(tree, options.e2eProjectName, {
+          projectType: 'application',
+          root: options.e2eProjectRoot,
+          sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+          targets: {},
+          implicitDependencies: [options.projectName],
+        });
+      }
 
       const e2eTask = await configurationGenerator(tree, {
         project: options.e2eProjectName,
diff --git a/packages/expo/src/generators/application/lib/add-project.ts b/packages/expo/src/generators/application/lib/add-project.ts
index 1f79ea08c95c0c..6067f11810d6ed 100644
--- a/packages/expo/src/generators/application/lib/add-project.ts
+++ b/packages/expo/src/generators/application/lib/add-project.ts
@@ -1,14 +1,18 @@
 import {
   addProjectConfiguration,
+  joinPathFragments,
   ProjectConfiguration,
   readNxJson,
   TargetConfiguration,
   Tree,
+  writeJson,
 } from '@nx/devkit';
 
 import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
 import { NormalizedSchema } from './normalize-options';
 import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { getImportPath } from '@nx/js/src/utils/get-import-path';
 
 export function addProject(host: Tree, options: NormalizedSchema) {
   const nxJson = readNxJson(host);
@@ -26,12 +30,28 @@ export function addProject(host: Tree, options: NormalizedSchema) {
     tags: options.parsedTags,
   };
 
-  addProjectConfiguration(
-    host,
-    options.projectName,
-    projectConfiguration,
-    options.standaloneConfig
-  );
+  if (isUsingTsSolutionSetup(host)) {
+    const packageName = getImportPath(host, options.name);
+    writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
+      name: packageName,
+      version: '0.0.1',
+      private: true,
+      nx: {
+        name: packageName === options.name ? undefined : options.name,
+        projectType: 'application',
+        sourceRoot: `${options.appProjectRoot}/src`,
+        targets: hasPlugin ? undefined : getTargets(options),
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  } else {
+    addProjectConfiguration(
+      host,
+      options.projectName,
+      projectConfiguration,
+      options.standaloneConfig
+    );
+  }
 }
 
 function getTargets(options: NormalizedSchema) {
diff --git a/packages/expo/src/generators/application/schema.d.ts b/packages/expo/src/generators/application/schema.d.ts
index d62942760e0718..692602357bf49e 100644
--- a/packages/expo/src/generators/application/schema.d.ts
+++ b/packages/expo/src/generators/application/schema.d.ts
@@ -15,6 +15,9 @@ export interface Schema {
   e2eTestRunner: 'cypress' | 'playwright' | 'detox' | 'none'; // default is none
   standaloneConfig?: boolean;
   skipPackageJson?: boolean; // default is false
+  // Internal options
   addPlugin?: boolean;
   nxCloudToken?: string;
+  useTsSolution?: boolean;
+  formatter?: 'prettier' | 'none';
 }
diff --git a/packages/expo/src/generators/application/schema.json b/packages/expo/src/generators/application/schema.json
index 197f2a7840c051..1cea5ca793433c 100644
--- a/packages/expo/src/generators/application/schema.json
+++ b/packages/expo/src/generators/application/schema.json
@@ -44,13 +44,15 @@
       "description": "The tool to use for running lint checks.",
       "type": "string",
       "enum": ["eslint", "none"],
-      "default": "eslint"
+      "default": "none",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["jest", "none"],
       "description": "Test runner to use for unit tests",
-      "default": "jest"
+      "default": "none",
+      "x-priority": "important"
     },
     "tags": {
       "type": "string",
@@ -71,7 +73,8 @@
       "description": "Adds the specified e2e test runner",
       "type": "string",
       "enum": ["playwright", "cypress", "detox", "none"],
-      "default": "none"
+      "default": "none",
+      "x-priority": "important"
     },
     "standaloneConfig": {
       "description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
diff --git a/packages/expo/src/generators/init/init.ts b/packages/expo/src/generators/init/init.ts
index 1050bff1a59a90..5e35458920d11b 100644
--- a/packages/expo/src/generators/init/init.ts
+++ b/packages/expo/src/generators/init/init.ts
@@ -9,7 +9,6 @@ import {
   Tree,
 } from '@nx/devkit';
 import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { createNodes } from '../../../plugins/plugin';
 import {
   expoCliVersion,
@@ -28,8 +27,6 @@ export function expoInitGenerator(tree: Tree, schema: Schema) {
 }
 
 export async function expoInitGeneratorInternal(host: Tree, schema: Schema) {
-  assertNotUsingTsSolutionSetup(host, 'expo', 'init');
-
   const nxJson = readNxJson(host);
   const addPluginDefault =
     process.env.NX_ADD_PLUGINS !== 'false' &&
diff --git a/packages/expo/src/generators/library/lib/normalize-options.ts b/packages/expo/src/generators/library/lib/normalize-options.ts
index 3bd1c679648892..e0c37f2e845150 100644
--- a/packages/expo/src/generators/library/lib/normalize-options.ts
+++ b/packages/expo/src/generators/library/lib/normalize-options.ts
@@ -4,6 +4,7 @@ import {
   ensureProjectName,
 } from '@nx/devkit/src/generators/project-name-and-root-utils';
 import { Schema } from '../schema';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export interface NormalizedSchema extends Schema {
   name: string;
@@ -12,6 +13,7 @@ export interface NormalizedSchema extends Schema {
   routePath: string;
   parsedTags: string[];
   appMain: string;
+  isUsingTsSolutionConfig: boolean;
 }
 
 export async function normalizeOptions(
@@ -50,6 +52,7 @@ export async function normalizeOptions(
     parsedTags,
     importPath,
     appMain,
+    isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
   };
 
   return normalized;
diff --git a/packages/expo/src/generators/library/library.spec.ts b/packages/expo/src/generators/library/library.spec.ts
index 887140b01d7501..674abc5d2e322b 100644
--- a/packages/expo/src/generators/library/library.spec.ts
+++ b/packages/expo/src/generators/library/library.spec.ts
@@ -233,6 +233,8 @@ describe('lib', () => {
           "compilerOptions": {
             "outDir": "../dist/out-tsc",
             "module": "commonjs",
+            "moduleResolution": "node10",
+            "jsx": "react-jsx",
             "types": ["jest", "node"]
           },
           "files": ["src/test-setup.ts"],
diff --git a/packages/expo/src/generators/library/library.ts b/packages/expo/src/generators/library/library.ts
index 2c94266ed804af..83743bf5a6e444 100644
--- a/packages/expo/src/generators/library/library.ts
+++ b/packages/expo/src/generators/library/library.ts
@@ -4,6 +4,7 @@ import {
   formatFiles,
   generateFiles,
   GeneratorCallback,
+  installPackagesTask,
   joinPathFragments,
   names,
   offsetFromRoot,
@@ -13,6 +14,7 @@ import {
   Tree,
   updateJson,
   updateProjectConfiguration,
+  writeJson,
 } from '@nx/devkit';
 
 import {
@@ -20,7 +22,6 @@ import {
   getRelativePathToRootTsConfig,
   initGenerator as jsInitGenerator,
 } from '@nx/js';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import init from '../init/init';
 import { addLinting } from '../../utils/add-linting';
 import { addJest } from '../../utils/add-jest';
@@ -35,6 +36,8 @@ import { ensureDependencies } from '../../utils/ensure-dependencies';
 import { initRootBabelConfig } from '../../utils/init-root-babel-config';
 import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { getImportPath } from '@nx/js/src/utils/get-import-path';
 
 export async function expoLibraryGenerator(
   host: Tree,
@@ -50,7 +53,13 @@ export async function expoLibraryGeneratorInternal(
   host: Tree,
   schema: Schema
 ): Promise<GeneratorCallback> {
-  assertNotUsingTsSolutionSetup(host, 'expo', 'library');
+  const tasks: GeneratorCallback[] = [];
+
+  const jsInitTask = await jsInitGenerator(host, {
+    ...schema,
+    skipFormat: true,
+  });
+  tasks.push(jsInitTask);
 
   const options = await normalizeOptions(host, schema);
   if (options.publishable === true && !schema.importPath) {
@@ -59,13 +68,6 @@ export async function expoLibraryGeneratorInternal(
     );
   }
 
-  const tasks: GeneratorCallback[] = [];
-
-  const jsInitTask = await jsInitGenerator(host, {
-    ...schema,
-    skipFormat: true,
-  });
-  tasks.push(jsInitTask);
   const initTask = await init(host, { ...options, skipFormat: true });
   tasks.push(initTask);
   if (!options.skipPackageJson) {
@@ -114,10 +116,29 @@ export async function expoLibraryGeneratorInternal(
     ]);
   }
 
+  updateTsconfigFiles(
+    host,
+    options.projectRoot,
+    'tsconfig.lib.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
 
+  // Always run install to link packages.
+  if (options.isUsingTsSolutionConfig) {
+    tasks.push(() => installPackagesTask(host));
+  }
+
   tasks.push(() => {
     logShowProjectCommand(options.name);
   });
@@ -136,7 +157,29 @@ async function addProject(
     tags: options.parsedTags,
     targets: {},
   };
-  addProjectConfiguration(host, options.name, project);
+
+  if (options.isUsingTsSolutionConfig) {
+    const packageName = getImportPath(host, options.name);
+    const sourceEntry = !options.buildable
+      ? options.js
+        ? './src/index.js'
+        : './src/index.ts'
+      : undefined;
+    writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
+      name: packageName,
+      version: '0.0.1',
+      main: sourceEntry,
+      types: sourceEntry,
+      nx: {
+        name: packageName === options.name ? undefined : options.name,
+        projectType: 'library',
+        sourceRoot: joinPathFragments(options.projectRoot, 'src'),
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  } else {
+    addProjectConfiguration(host, options.name, project);
+  }
 
   if (!options.publishable && !options.buildable) {
     return () => {};
diff --git a/packages/expo/src/generators/library/schema.json b/packages/expo/src/generators/library/schema.json
index 11c7c50439b395..ea0d5c2f038388 100644
--- a/packages/expo/src/generators/library/schema.json
+++ b/packages/expo/src/generators/library/schema.json
@@ -29,13 +29,16 @@
       "description": "The tool to use for running lint checks.",
       "type": "string",
       "enum": ["eslint", "none"],
-      "default": "eslint"
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["jest", "none"],
       "description": "Test runner to use for unit tests.",
-      "default": "jest"
+      "default": "none",
+      "x-priority": "important"
     },
     "tags": {
       "type": "string",
diff --git a/packages/jest/src/generators/configuration/files/tsconfig.spec.json__tmpl__ b/packages/jest/src/generators/configuration/files/tsconfig.spec.json__tmpl__
index 0e758a58c5bc03..366365d19e53e0 100644
--- a/packages/jest/src/generators/configuration/files/tsconfig.spec.json__tmpl__
+++ b/packages/jest/src/generators/configuration/files/tsconfig.spec.json__tmpl__
@@ -2,8 +2,9 @@
   "extends": "<%= extendedConfig %>",
   "compilerOptions": {
     "outDir": "<%= outDir %>",<% if (module) { %>
-    "module": "<%= module %>",<% } %>
-    "types": ["jest", "node"]
+    "module": "<%= module %>",<% } if (module === 'commonjs') { %>
+    "moduleResolution": "node10",<% } if (supportTsx) { %>
+    "jsx": "react-jsx",<% } %>"types": ["jest", "node"]
   },<% if(setupFile !== 'none') { %>
   "files": ["src/test-setup.ts"],<% } %>
   "include": [
diff --git a/packages/jest/src/generators/configuration/lib/create-files.ts b/packages/jest/src/generators/configuration/lib/create-files.ts
index 847501f93136a1..e40d7ccab24fb3 100644
--- a/packages/jest/src/generators/configuration/lib/create-files.ts
+++ b/packages/jest/src/generators/configuration/lib/create-files.ts
@@ -4,10 +4,10 @@ import {
   readProjectConfiguration,
   Tree,
 } from '@nx/devkit';
-import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { join } from 'path';
 import type { JestPresetExtension } from '../../../utils/config/config-file';
 import { NormalizedJestProjectSchema } from '../schema';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function createFiles(
   tree: Tree,
diff --git a/packages/js/src/generators/library/library.spec.ts b/packages/js/src/generators/library/library.spec.ts
index 5622a876026152..86713cfc4c45e2 100644
--- a/packages/js/src/generators/library/library.spec.ts
+++ b/packages/js/src/generators/library/library.spec.ts
@@ -8,6 +8,7 @@ import {
   readProjectConfiguration,
   Tree,
   updateJson,
+  writeJson,
 } from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import { libraryGenerator } from './library';
@@ -1611,4 +1612,64 @@ describe('lib', () => {
       `);
     });
   });
+
+  describe('TS solution setup', () => {
+    beforeEach(() => {
+      tree = createTreeWithEmptyWorkspace();
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+    });
+
+    it('should map non-buildable libraries to source', async () => {
+      await libraryGenerator(tree, {
+        ...defaultOptions,
+        directory: 'my-ts-lib',
+        bundler: 'none',
+        unitTestRunner: 'none',
+        linter: 'none',
+      });
+      await libraryGenerator(tree, {
+        ...defaultOptions,
+        directory: 'my-js-lib',
+        js: true,
+        bundler: 'none',
+        unitTestRunner: 'none',
+        linter: 'none',
+      });
+
+      expect(readJson(tree, 'my-ts-lib/package.json')).toMatchInlineSnapshot(`
+        {
+          "dependencies": {},
+          "main": "./src/index.ts",
+          "name": "@proj/my-ts-lib",
+          "private": true,
+          "types": "./src/index.ts",
+          "version": "0.0.1",
+        }
+      `);
+      expect(readJson(tree, 'my-js-lib/package.json')).toMatchInlineSnapshot(`
+        {
+          "dependencies": {},
+          "main": "./src/index.js",
+          "name": "@proj/my-js-lib",
+          "private": true,
+          "types": "./src/index.js",
+          "version": "0.0.1",
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts
index 022af8f92f4689..7dbaa8afc0738b 100644
--- a/packages/js/src/generators/library/library.ts
+++ b/packages/js/src/generators/library/library.ts
@@ -1,5 +1,6 @@
 import {
   addDependenciesToPackageJson,
+  installPackagesTask,
   addProjectConfiguration,
   ensurePackage,
   formatFiles,
@@ -234,6 +235,11 @@ export async function libraryGeneratorInternal(
     });
   }
 
+  // Always run install to link packages.
+  if (options.isUsingTsSolutionConfig) {
+    tasks.push(() => installPackagesTask(tree));
+  }
+
   tasks.push(() => {
     logShowProjectCommand(options.name);
   });
@@ -1125,6 +1131,17 @@ function determineEntryFields(
         // Safest option is to not set a type field.
         // Allow the user to decide which module format their library is using
         type: undefined,
+        // For non-buildable libraries, point to source so we can still use them in apps via bundlers like Vite.
+        main: options.isUsingTsSolutionConfig
+          ? options.js
+            ? './src/index.js'
+            : './src/index.ts'
+          : undefined,
+        types: options.isUsingTsSolutionConfig
+          ? options.js
+            ? './src/index.js'
+            : './src/index.ts'
+          : undefined,
       };
     }
   }
diff --git a/packages/js/src/plugins/typescript/plugin.spec.ts b/packages/js/src/plugins/typescript/plugin.spec.ts
index 9c98679117552f..a425dffa7c8622 100644
--- a/packages/js/src/plugins/typescript/plugin.spec.ts
+++ b/packages/js/src/plugins/typescript/plugin.spec.ts
@@ -268,7 +268,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
       `);
     });
 
-    it('should not invoke tsc with `--emitDeclarationOnly` when `noEmit` is set in the tsconfig.json file', async () => {
+    it('should not invoke `tsc --build` when `noEmit` is set in the tsconfig.json file', async () => {
       // set directly in tsconfig.json file
       await applyFilesToTempFsAndContext(tempFs, context, {
         'libs/my-lib/tsconfig.json': JSON.stringify({
@@ -285,7 +285,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
               "targets": {
                 "typecheck": {
                   "cache": true,
-                  "command": "tsc --build --pretty --verbose",
+                  "command": "echo "The 'typecheck' target is disabled because one or more project references set 'noEmit: true' in their tsconfig. Remove this property to resolve this issue."",
                   "dependsOn": [
                     "^typecheck",
                   ],
@@ -345,7 +345,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
               "targets": {
                 "typecheck": {
                   "cache": true,
-                  "command": "tsc --build --pretty --verbose",
+                  "command": "echo "The 'typecheck' target is disabled because one or more project references set 'noEmit: true' in their tsconfig. Remove this property to resolve this issue."",
                   "dependsOn": [
                     "^typecheck",
                   ],
@@ -387,7 +387,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
       `);
     });
 
-    it('should not invoke tsc with `--emitDeclarationOnly` when `noEmit` is set in any of the referenced tsconfig.json files', async () => {
+    it('should not invoke `tsc --build` when `noEmit` is set in any of the referenced tsconfig.json files', async () => {
       await applyFilesToTempFsAndContext(tempFs, context, {
         'libs/my-lib/tsconfig.json': JSON.stringify({
           files: [],
@@ -407,7 +407,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
               "targets": {
                 "typecheck": {
                   "cache": true,
-                  "command": "tsc --build --pretty --verbose",
+                  "command": "echo "The 'typecheck' target is disabled because one or more project references set 'noEmit: true' in their tsconfig. Remove this property to resolve this issue."",
                   "dependsOn": [
                     "^typecheck",
                   ],
diff --git a/packages/js/src/plugins/typescript/plugin.ts b/packages/js/src/plugins/typescript/plugin.ts
index 350d0f6835ec73..9c4cb22397ed7a 100644
--- a/packages/js/src/plugins/typescript/plugin.ts
+++ b/packages/js/src/plugins/typescript/plugin.ts
@@ -168,12 +168,23 @@ async function createNodesInternal(
     return {};
   }
 
+  // Do not create project for Next.js projects since they are not compatible with
+  // project references and typecheck will fail.
+  if (
+    siblingFiles.includes('next.config.js') ||
+    siblingFiles.includes('next.config.cjs') ||
+    siblingFiles.includes('next.config.mjs') ||
+    siblingFiles.includes('next.config.ts')
+  ) {
+    return {};
+  }
+
   /**
    * The cache key is composed by:
    * - hashes of the content of the relevant files that can affect what's inferred by the plugin:
    *   - current config file
    *   - config files extended by the current config file (recursively up to the root config file)
-   *   - referenced config files that are internal to the owning Nx project of the current config file
+   *   - referenced config files that are internal to the owning Nx project of the current config file, or is a shallow external reference of the owning Nx project
    *   - lock file
    * - hash of the plugin options
    * - current config file path
@@ -185,11 +196,17 @@ async function createNodesInternal(
     context.workspaceRoot,
     projectRoot
   );
+  const externalProjectReferences = resolveShallowExternalProjectReferences(
+    tsConfig,
+    context.workspaceRoot,
+    projectRoot
+  );
   const nodeHash = hashArray([
     ...[
       fullConfigPath,
       ...extendedConfigFiles.files,
       ...Object.keys(internalReferencedFiles),
+      ...Object.keys(externalProjectReferences),
       join(context.workspaceRoot, lockFileName),
     ].map(hashFile),
     hashObject(options),
@@ -239,6 +256,11 @@ function buildTscTargets(
       context.workspaceRoot,
       projectRoot
     );
+    const externalProjectReferences = resolveShallowExternalProjectReferences(
+      tsConfig,
+      context.workspaceRoot,
+      projectRoot
+    );
     const targetName = options.typecheck.targetName;
     if (!targets[targetName]) {
       let command = `tsc --build --emitDeclarationOnly --pretty --verbose`;
@@ -246,11 +268,13 @@ function buildTscTargets(
         tsConfig.options.noEmit ||
         Object.values(internalProjectReferences).some(
           (ref) => ref.options.noEmit
+        ) ||
+        Object.values(externalProjectReferences).some(
+          (ref) => ref.options.noEmit
         )
       ) {
-        // `--emitDeclarationOnly` and `--noEmit` are mutually exclusive, so
-        // we remove `--emitDeclarationOnly` if `--noEmit` is set.
-        command = `tsc --build --pretty --verbose`;
+        // `tsc --build` does not work with `noEmit: true`
+        command = `echo "The 'typecheck' target is disabled because one or more project references set 'noEmit: true' in their tsconfig. Remove this property to resolve this issue."`;
       }
 
       targets[targetName] = {
@@ -607,6 +631,48 @@ function resolveInternalProjectReferences(
   workspaceRoot: string,
   projectRoot: string,
   projectReferences: Record<string, ParsedCommandLine> = {}
+): Record<string, ParsedCommandLine> {
+  walkProjectReferences(
+    tsConfig,
+    workspaceRoot,
+    projectRoot,
+    (configPath, config) => {
+      if (isExternalProjectReference(configPath, workspaceRoot, projectRoot)) {
+        return false;
+      } else {
+        projectReferences[configPath] = config;
+      }
+    }
+  );
+  return projectReferences;
+}
+
+function resolveShallowExternalProjectReferences(
+  tsConfig: ParsedCommandLine,
+  workspaceRoot: string,
+  projectRoot: string,
+  projectReferences: Record<string, ParsedCommandLine> = {}
+): Record<string, ParsedCommandLine> {
+  walkProjectReferences(
+    tsConfig,
+    workspaceRoot,
+    projectRoot,
+    (configPath, config) => {
+      if (isExternalProjectReference(configPath, workspaceRoot, projectRoot)) {
+        projectReferences[configPath] = config;
+      }
+      return false;
+    }
+  );
+  return projectReferences;
+}
+
+function walkProjectReferences(
+  tsConfig: ParsedCommandLine,
+  workspaceRoot: string,
+  projectRoot: string,
+  visitor: (configPath: string, config: ParsedCommandLine) => void | false, // false stops recursion
+  projectReferences: Record<string, ParsedCommandLine> = {}
 ): Record<string, ParsedCommandLine> {
   if (!tsConfig.projectReferences?.length) {
     return projectReferences;
@@ -624,22 +690,14 @@ function resolveInternalProjectReferences(
       continue;
     }
 
-    if (isExternalProjectReference(refConfigPath, workspaceRoot, projectRoot)) {
-      continue;
-    }
-
     if (!refConfigPath.endsWith('.json')) {
       refConfigPath = join(refConfigPath, 'tsconfig.json');
     }
     const refTsConfig = readCachedTsConfig(refConfigPath);
-    projectReferences[refConfigPath] = refTsConfig;
-
-    resolveInternalProjectReferences(
-      refTsConfig,
-      workspaceRoot,
-      projectRoot,
-      projectReferences
-    );
+    const result = visitor(refConfigPath, refTsConfig);
+    if (result !== false) {
+      walkProjectReferences(refTsConfig, workspaceRoot, projectRoot, visitor);
+    }
   }
 
   return projectReferences;
diff --git a/packages/js/src/utils/package-manager-workspaces.ts b/packages/js/src/utils/package-manager-workspaces.ts
index f04337b6db761b..50a5262808f248 100644
--- a/packages/js/src/utils/package-manager-workspaces.ts
+++ b/packages/js/src/utils/package-manager-workspaces.ts
@@ -1,7 +1,6 @@
 import {
   detectPackageManager,
   getPackageManagerVersion,
-  isWorkspacesEnabled,
   output,
   readJson,
   type GeneratorCallback,
@@ -10,6 +9,7 @@ import {
 import { minimatch } from 'minimatch';
 import { join } from 'node:path/posix';
 import { getGlobPatternsFromPackageManagerWorkspaces } from 'nx/src/plugins/package-json';
+import { PackageJson } from 'nx/src/utils/package-json';
 import { lt } from 'semver';
 
 export type ProjectPackageManagerWorkspaceState =
@@ -37,7 +37,22 @@ export function getProjectPackageManagerWorkspaceState(
 }
 
 export function isUsingPackageManagerWorkspaces(tree: Tree): boolean {
-  return isWorkspacesEnabled(detectPackageManager(tree.root), tree.root);
+  return isWorkspacesEnabled(tree);
+}
+
+export function isWorkspacesEnabled(
+  tree: Tree
+  // packageManager: PackageManager = detectPackageManager(),
+  // root: string = workspaceRoot
+): boolean {
+  const packageManager = detectPackageManager(tree.root);
+  if (packageManager === 'pnpm') {
+    return tree.exists('pnpm-workspace.yaml');
+  }
+
+  // yarn and npm both use the same 'workspaces' property in package.json
+  const packageJson = readJson<PackageJson>(tree, 'package.json');
+  return !!packageJson?.workspaces;
 }
 
 export function getProjectPackageManagerWorkspaceStateWarningTask(
diff --git a/packages/js/src/utils/typescript/ts-solution-setup.ts b/packages/js/src/utils/typescript/ts-solution-setup.ts
index 8b544b9788ac02..d50d9fdb7c724b 100644
--- a/packages/js/src/utils/typescript/ts-solution-setup.ts
+++ b/packages/js/src/utils/typescript/ts-solution-setup.ts
@@ -1,12 +1,16 @@
 import {
+  joinPathFragments,
+  offsetFromRoot,
   output,
   readJson,
   readNxJson,
-  workspaceRoot,
   type Tree,
+  updateJson,
+  workspaceRoot,
 } from '@nx/devkit';
 import { FsTree } from 'nx/src/generators/tree';
 import { isUsingPackageManagerWorkspaces } from '../package-manager-workspaces';
+import { relative } from 'node:path/posix';
 
 export function isUsingTypeScriptPlugin(tree: Tree): boolean {
   const nxJson = readNxJson(tree);
@@ -96,3 +100,78 @@ export function assertNotUsingTsSolutionSetup(
 
   process.exit(1);
 }
+
+export function updateTsconfigFiles(
+  tree: Tree,
+  projectRoot: string,
+  runtimeTsconfigFileName: string,
+  compilerOptions: Record<string, string | boolean | string[]>,
+  exclude: string[] = [],
+  rootDir = 'src'
+) {
+  if (!isUsingTsSolutionSetup(tree)) return;
+
+  const offset = offsetFromRoot(projectRoot);
+  const tsconfig = `${projectRoot}/${runtimeTsconfigFileName}`;
+  const tsconfigSpec = `${projectRoot}/tsconfig.spec.json`;
+  const e2eRoot = `${projectRoot}-e2e`;
+  const tsconfigE2E = `${e2eRoot}/tsconfig.json`;
+
+  if (tree.exists(tsconfig)) {
+    updateJson(tree, tsconfig, (json) => {
+      json.extends = joinPathFragments(offset, 'tsconfig.base.json');
+
+      json.compilerOptions = {
+        ...json.compilerOptions,
+        // Make sure d.ts files from typecheck does not conflict with bundlers.
+        // Other tooling like jest write to "out-tsc/jest" to we just default to "out-tsc/<project-name>".
+        outDir: joinPathFragments('out-tsc', projectRoot.split('/').at(-1)),
+        rootDir,
+        ...compilerOptions,
+      };
+
+      const excludeSet: Set<string> = json.exclude
+        ? new Set(['dist', ...json.exclude, ...exclude])
+        : new Set(exclude);
+      json.exclude = Array.from(excludeSet);
+
+      return json;
+    });
+  }
+
+  if (tree.exists(tsconfigSpec)) {
+    updateJson(tree, tsconfigSpec, (json) => {
+      json.extends = joinPathFragments(offset, 'tsconfig.base.json');
+      json.compilerOptions = {
+        ...json.compilerOptions,
+        ...compilerOptions,
+      };
+      const runtimePath = `./${runtimeTsconfigFileName}`;
+      json.references ??= [];
+      if (!json.references.some((x) => x.path === runtimePath))
+        json.references.push({ path: runtimePath });
+      return json;
+    });
+  }
+
+  if (tree.exists(tsconfigE2E)) {
+    // tsconfig.json for e2e projects need to have references array
+    updateJson(tree, tsconfigE2E, (json) => {
+      json.references ??= [];
+      const projectPath = relative(e2eRoot, projectRoot);
+      if (!json.references.some((x) => x.path === projectPath))
+        json.references.push({ path: projectPath });
+      return json;
+    });
+  }
+
+  if (tree.exists('tsconfig.json')) {
+    updateJson(tree, 'tsconfig.json', (json) => {
+      const projectPath = './' + projectRoot;
+      json.references ??= [];
+      if (!json.references.some((x) => x.path === projectPath))
+        json.references.push({ path: projectPath });
+      return json;
+    });
+  }
+}
diff --git a/packages/next/src/generators/application/application.spec.ts b/packages/next/src/generators/application/application.spec.ts
index 0342656015707f..e2c5173944b452 100644
--- a/packages/next/src/generators/application/application.spec.ts
+++ b/packages/next/src/generators/application/application.spec.ts
@@ -5,6 +5,8 @@ import {
   readNxJson,
   readProjectConfiguration,
   Tree,
+  updateJson,
+  writeJson,
 } from '@nx/devkit';
 
 import { Schema } from './schema';
@@ -174,23 +176,22 @@ describe('app', () => {
 
   describe('--style scss', () => {
     it('should generate scss styles', async () => {
-      const name = uniq();
       await applicationGenerator(tree, {
-        directory: name,
+        directory: 'myapp',
         style: 'scss',
       });
 
-      expect(tree.exists(`${name}/src/app/page.module.scss`)).toBeTruthy();
-      expect(tree.exists(`${name}/src/app/global.css`)).toBeTruthy();
+      expect(tree.exists(`myapp/src/app/page.module.scss`)).toBeTruthy();
+      expect(tree.exists(`myapp/src/app/global.css`)).toBeTruthy();
 
-      const indexContent = tree.read(`${name}/src/app/page.tsx`, 'utf-8');
+      const indexContent = tree.read(`myapp/src/app/page.tsx`, 'utf-8');
       expect(indexContent).toContain(`import styles from './page.module.scss'`);
-      expect(tree.read(`${name}/src/app/layout.tsx`, 'utf-8'))
+      expect(tree.read(`myapp/src/app/layout.tsx`, 'utf-8'))
         .toMatchInlineSnapshot(`
         "import './global.css';
 
         export const metadata = {
-          title: 'Welcome to ${name}',
+          title: 'Welcome to myapp',
           description: 'Generated by create-nx-workspace',
         };
 
@@ -212,23 +213,22 @@ describe('app', () => {
 
   describe('--style less', () => {
     it('should generate less styles', async () => {
-      const name = uniq();
       await applicationGenerator(tree, {
-        directory: name,
+        directory: 'myapp',
         style: 'less',
       });
 
-      expect(tree.exists(`${name}/src/app/page.module.less`)).toBeTruthy();
-      expect(tree.exists(`${name}/src/app/global.less`)).toBeTruthy();
+      expect(tree.exists(`myapp/src/app/page.module.less`)).toBeTruthy();
+      expect(tree.exists(`myapp/src/app/global.less`)).toBeTruthy();
 
-      const indexContent = tree.read(`${name}/src/app/page.tsx`, 'utf-8');
+      const indexContent = tree.read(`myapp/src/app/page.tsx`, 'utf-8');
       expect(indexContent).toContain(`import styles from './page.module.less'`);
-      expect(tree.read(`${name}/src/app/layout.tsx`, 'utf-8'))
+      expect(tree.read(`myapp/src/app/layout.tsx`, 'utf-8'))
         .toMatchInlineSnapshot(`
         "import './global.less';
 
         export const metadata = {
-          title: 'Welcome to ${name}',
+          title: 'Welcome to myapp',
           description: 'Generated by create-nx-workspace',
         };
 
@@ -616,10 +616,8 @@ describe('app', () => {
       });
 
       it('should add .eslintrc.json and dependencies', async () => {
-        const name = uniq();
-
         await applicationGenerator(tree, {
-          directory: name,
+          directory: 'myapp',
           style: 'css',
         });
 
@@ -631,7 +629,7 @@ describe('app', () => {
           },
         });
 
-        const eslintJson = readJson(tree, `${name}/.eslintrc.json`);
+        const eslintJson = readJson(tree, `myapp/.eslintrc.json`);
         expect(eslintJson).toMatchInlineSnapshot(`
           {
             "extends": [
@@ -655,7 +653,7 @@ describe('app', () => {
                 "rules": {
                   "@next/next/no-html-link-for-pages": [
                     "error",
-                    "${name}/pages",
+                    "myapp/pages",
                   ],
                 },
               },
@@ -838,6 +836,172 @@ describe('app (legacy)', () => {
     expect(projectConfiguration.targets.build).toBeDefined();
     expect(projectConfiguration.targets.serve).toBeDefined();
   });
+
+  describe('TS solution setup', () => {
+    beforeEach(() => {
+      tree = createTreeWithEmptyWorkspace();
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+    });
+
+    it('should add project references when using TS solution', async () => {
+      await applicationGenerator(tree, {
+        ...schema,
+        addPlugin: true,
+        directory: 'myapp',
+        name: 'myapp',
+      });
+
+      expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./myapp-e2e",
+          },
+          {
+            "path": "./myapp",
+          },
+        ]
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowJs": true,
+            "allowSyntheticDefaultImports": true,
+            "esModuleInterop": true,
+            "forceConsistentCasingInFileNames": true,
+            "incremental": true,
+            "isolatedModules": true,
+            "jsx": "preserve",
+            "lib": [
+              "dom",
+              "dom.iterable",
+              "esnext",
+            ],
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "noEmit": true,
+            "outDir": "out-tsc/myapp",
+            "paths": {
+              "@/*": [
+                "./src/*",
+              ],
+            },
+            "plugins": [
+              {
+                "name": "next",
+              },
+            ],
+            "resolveJsonModule": true,
+            "rootDir": "src",
+            "strict": true,
+            "types": [
+              "jest",
+              "node",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "node_modules",
+            "jest.config.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.ts",
+            ".next",
+            "eslint.config.js",
+            "eslint.config.cjs",
+            "eslint.config.mjs",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "src/**/*.ts",
+            "src/**/*.tsx",
+            "src/**/*.js",
+            "src/**/*.jsx",
+            "../myapp/.next/types/**/*.ts",
+            "../dist/myapp/.next/types/**/*.ts",
+            "next-env.d.ts",
+          ],
+        }
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.spec.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "preserve",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "./out-tsc/jest",
+            "types": [
+              "jest",
+              "node",
+            ],
+          },
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "jest.config.ts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.js",
+            "src/**/*.spec.js",
+            "src/**/*.test.jsx",
+            "src/**/*.spec.jsx",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "./tsconfig.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'myapp-e2e/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowJs": true,
+            "outDir": "dist",
+            "sourceMap": false,
+            "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
+            "types": [
+              "cypress",
+              "node",
+            ],
+          },
+          "exclude": [
+            "dist",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "**/*.ts",
+            "**/*.js",
+            "cypress.config.ts",
+            "**/*.cy.ts",
+            "**/*.cy.tsx",
+            "**/*.cy.js",
+            "**/*.cy.jsx",
+            "**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "../myapp",
+            },
+          ],
+        }
+      `);
+    });
+  });
 });
 
 function uniq() {
diff --git a/packages/next/src/generators/application/application.ts b/packages/next/src/generators/application/application.ts
index 30fca7bcdaf59c..c17d968e74df5e 100644
--- a/packages/next/src/generators/application/application.ts
+++ b/packages/next/src/generators/application/application.ts
@@ -7,7 +7,6 @@ import {
   Tree,
 } from '@nx/devkit';
 import { initGenerator as jsInitGenerator } from '@nx/js';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { setupTailwindGenerator } from '@nx/react';
 import {
   testingLibraryReactVersion,
@@ -31,6 +30,7 @@ import { updateCypressTsConfig } from './lib/update-cypress-tsconfig';
 import { showPossibleWarnings } from './lib/show-possible-warnings';
 import { tsLibVersion } from '../../utils/versions';
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function applicationGenerator(host: Tree, schema: Schema) {
   return await applicationGeneratorInternal(host, {
@@ -40,8 +40,6 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
 }
 
 export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
-  assertNotUsingTsSolutionSetup(host, 'next', 'application');
-
   const tasks: GeneratorCallback[] = [];
   const options = await normalizeOptions(host, schema);
 
@@ -51,6 +49,8 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
     js: options.js,
     skipPackageJson: options.skipPackageJson,
     skipFormat: true,
+    addTsPlugin: schema.useTsSolution,
+    formatter: schema.formatter,
   });
   tasks.push(jsInitTask);
 
@@ -117,6 +117,21 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
     );
   }
 
+  updateTsconfigFiles(
+    host,
+    options.appProjectRoot,
+    'tsconfig.json',
+    {
+      jsx: 'preserve',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['.next', 'eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : ['.next'],
+    options.src ? 'src' : '.'
+  );
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
diff --git a/packages/next/src/generators/application/files/common/tsconfig.json__tmpl__ b/packages/next/src/generators/application/files/common/tsconfig.json__tmpl__
index 6ec03249199f3a..e82f281c5a6f68 100644
--- a/packages/next/src/generators/application/files/common/tsconfig.json__tmpl__
+++ b/packages/next/src/generators/application/files/common/tsconfig.json__tmpl__
@@ -3,16 +3,22 @@
   "compilerOptions": {
     "jsx": "preserve",
     <% if (style === '@emotion/styled') { %>"jsxImportSource": "@emotion/react",<% } %>
-    "allowJs": true,
-    "esModuleInterop": true,
-    "allowSyntheticDefaultImports": true,
     "strict": true,
-    "forceConsistentCasingInFileNames": true,
     "noEmit": true,
+    "esModuleInterop": true,
+    "module": "esnext",
+    "moduleResolution": "bundler",
     "resolveJsonModule": true,
     "isolatedModules": true,
+    "lib": ["dom", "dom.iterable", "esnext"],
+    "allowJs": true,
+    "allowSyntheticDefaultImports": true,
+    "forceConsistentCasingInFileNames": true,
     "incremental": true,
-    "plugins": [{ "name": "next" }]
+    "plugins": [{ "name": "next" }]<% if (isUsingTsSolutionSetup) { %>,
+    "paths": {
+      "@/*": [<% if (src) { %>"./src/*"<% } else { %>"./*"<% } %>]
+    }<% } %>
   },
   "include": [
     "<%= rootPath %>**/*.ts",
diff --git a/packages/next/src/generators/application/lib/add-e2e.ts b/packages/next/src/generators/application/lib/add-e2e.ts
index 0b37908cf0da01..6d3077927274f5 100644
--- a/packages/next/src/generators/application/lib/add-e2e.ts
+++ b/packages/next/src/generators/application/lib/add-e2e.ts
@@ -1,10 +1,10 @@
 import {
   addProjectConfiguration,
   ensurePackage,
-  getPackageManagerCommand,
   joinPathFragments,
   readNxJson,
   Tree,
+  writeJson,
 } from '@nx/devkit';
 import { Linter } from '@nx/eslint';
 
@@ -14,6 +14,7 @@ import { webStaticServeGenerator } from '@nx/web';
 import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
 import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
 import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function addE2e(host: Tree, options: NormalizedSchema) {
   const nxJson = readNxJson(host);
@@ -44,13 +45,31 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
       });
     }
 
-    addProjectConfiguration(host, options.e2eProjectName, {
-      root: options.e2eProjectRoot,
-      sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-      targets: {},
-      tags: [],
-      implicitDependencies: [options.projectName],
-    });
+    if (isUsingTsSolutionSetup(host)) {
+      writeJson(
+        host,
+        joinPathFragments(options.e2eProjectRoot, 'package.json'),
+        {
+          name: options.e2eProjectName,
+          version: '0.0.1',
+          private: true,
+          nx: {
+            projectType: 'application',
+            sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+            implicitDependencies: [options.projectName],
+          },
+        }
+      );
+    } else {
+      addProjectConfiguration(host, options.e2eProjectName, {
+        root: options.e2eProjectRoot,
+        projectType: 'application',
+        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+        targets: {},
+        tags: [],
+        implicitDependencies: [options.projectName],
+      });
+    }
 
     const e2eTask = await configurationGenerator(host, {
       ...options,
@@ -107,13 +126,32 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
     const { configurationGenerator } = ensurePackage<
       typeof import('@nx/playwright')
     >('@nx/playwright', nxVersion);
-    addProjectConfiguration(host, options.e2eProjectName, {
-      root: options.e2eProjectRoot,
-      sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-      targets: {},
-      tags: [],
-      implicitDependencies: [options.projectName],
-    });
+    if (isUsingTsSolutionSetup(host)) {
+      writeJson(
+        host,
+        joinPathFragments(options.e2eProjectRoot, 'package.json'),
+        {
+          name: options.e2eProjectName,
+          version: '0.0.1',
+          private: true,
+          nx: {
+            projectType: 'application',
+            sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+            implicitDependencies: [options.projectName],
+          },
+        }
+      );
+    } else {
+      addProjectConfiguration(host, options.e2eProjectName, {
+        root: options.e2eProjectRoot,
+        projectType: 'application',
+        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+        targets: {},
+        tags: [],
+        implicitDependencies: [options.projectName],
+      });
+    }
+
     const e2eTask = await configurationGenerator(host, {
       rootProject: options.rootProject,
       project: options.e2eProjectName,
diff --git a/packages/next/src/generators/application/lib/add-linting.ts b/packages/next/src/generators/application/lib/add-linting.ts
index bc131ccb514846..18ce42a6ef64a3 100644
--- a/packages/next/src/generators/application/lib/add-linting.ts
+++ b/packages/next/src/generators/application/lib/add-linting.ts
@@ -22,6 +22,8 @@ export async function addLinting(
   host: Tree,
   options: NormalizedSchema
 ): Promise<GeneratorCallback> {
+  if (options.linter !== 'eslint') return () => {};
+
   const tasks: GeneratorCallback[] = [];
 
   tasks.push(
diff --git a/packages/next/src/generators/application/lib/add-project.ts b/packages/next/src/generators/application/lib/add-project.ts
index 378a9ac676cf4c..49d837a9653cbc 100644
--- a/packages/next/src/generators/application/lib/add-project.ts
+++ b/packages/next/src/generators/application/lib/add-project.ts
@@ -1,11 +1,17 @@
 import { NormalizedSchema } from './normalize-options';
 import {
   addProjectConfiguration,
+  joinPathFragments,
   ProjectConfiguration,
   readNxJson,
   Tree,
+  writeJson,
 } from '@nx/devkit';
 import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { getImportPath } from '@nx/js/src/utils/get-import-path';
+import { nextVersion } from '../../../utils/versions';
+import { reactDomVersion, reactVersion } from '@nx/react';
 
 export function addProject(host: Tree, options: NormalizedSchema) {
   const targets: Record<string, any> = {};
@@ -66,7 +72,26 @@ export function addProject(host: Tree, options: NormalizedSchema) {
     tags: options.parsedTags,
   };
 
-  addProjectConfiguration(host, options.projectName, {
-    ...project,
-  });
+  if (isUsingTsSolutionSetup(host)) {
+    writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
+      name: getImportPath(host, options.name),
+      version: '0.0.1',
+      private: true,
+      dependencies: {
+        next: nextVersion,
+        react: reactVersion,
+        'react-dom': reactDomVersion,
+      },
+      nx: {
+        name: options.name,
+        projectType: 'application',
+        sourceRoot: options.appProjectRoot,
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  } else {
+    addProjectConfiguration(host, options.projectName, {
+      ...project,
+    });
+  }
 }
diff --git a/packages/next/src/generators/application/lib/create-application-files.ts b/packages/next/src/generators/application/lib/create-application-files.ts
index 143fd1840abdca..faf8f7868b234a 100644
--- a/packages/next/src/generators/application/lib/create-application-files.ts
+++ b/packages/next/src/generators/application/lib/create-application-files.ts
@@ -16,6 +16,7 @@ import {
   createAppJsx,
   createStyleRules,
 } from './create-application-files.helpers';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
   const offsetFromRoot = _offsetFromRoot(options.appProjectRoot);
@@ -30,14 +31,15 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
     '.next/types/**/*.ts'
   );
 
-  // scope tsconfig to the project directory so that it doesn't include other projects/libs
-  const rootPath = options.rootProject
-    ? options.src
-      ? 'src/'
-      : options.appDir
-      ? 'app/'
-      : 'pages/'
-    : '';
+  const rootPath =
+    options.rootProject || isUsingTsSolutionSetup(host)
+      ? options.src
+        ? 'src/'
+        : options.appDir
+        ? 'app/'
+        : 'pages/'
+      : '';
+
   const templateVariables = {
     ...names(options.name),
     ...options,
@@ -55,8 +57,8 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
     appContent: createAppJsx(options.projectName),
     styleContent: createStyleRules(),
     pageStyleContent: `.page {}`,
-
     stylesExt: options.style === 'less' ? options.style : 'css',
+    isUsingTsSolutionSetup: isUsingTsSolutionSetup(host),
   };
 
   const generatedAppFilePath = options.src
diff --git a/packages/next/src/generators/application/schema.d.ts b/packages/next/src/generators/application/schema.d.ts
index 205f3ed4d14673..eea51daa2b2a1d 100644
--- a/packages/next/src/generators/application/schema.d.ts
+++ b/packages/next/src/generators/application/schema.d.ts
@@ -17,6 +17,9 @@ export interface Schema {
   skipPackageJson?: boolean;
   appDir?: boolean;
   src?: boolean;
+  // Internal options
   rootProject?: boolean;
   addPlugin?: boolean;
+  useTsSolution?: boolean;
+  formatter?: 'prettier' | 'none';
 }
diff --git a/packages/next/src/generators/application/schema.json b/packages/next/src/generators/application/schema.json
index b9a0a81af2a338..b28be3e05a2158 100644
--- a/packages/next/src/generators/application/schema.json
+++ b/packages/next/src/generators/application/schema.json
@@ -69,8 +69,10 @@
     "linter": {
       "description": "The tool to use for running lint checks.",
       "type": "string",
-      "enum": ["eslint"],
-      "default": "eslint"
+      "enum": ["eslint", "none"],
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "skipFormat": {
       "description": "Skip formatting files.",
@@ -82,7 +84,9 @@
       "type": "string",
       "enum": ["jest", "none"],
       "description": "Test runner to use for unit tests.",
-      "default": "jest"
+      "default": "none",
+      "x-prompt": "What unit test runner should be used?",
+      "x-priority": "important"
     },
     "e2eTestRunner": {
       "type": "string",
diff --git a/packages/next/src/generators/custom-server/custom-server.ts b/packages/next/src/generators/custom-server/custom-server.ts
index 48b34f8e4623ed..4c2e6af45d42cf 100644
--- a/packages/next/src/generators/custom-server/custom-server.ts
+++ b/packages/next/src/generators/custom-server/custom-server.ts
@@ -1,4 +1,4 @@
-import type { Tree } from '@nx/devkit';
+import { joinPathFragments, Tree } from '@nx/devkit';
 import {
   updateJson,
   generateFiles,
@@ -11,6 +11,7 @@ import {
 import { CustomServerSchema } from './schema';
 import { join } from 'path';
 import { configureForSwc } from '../../utils/add-swc-to-custom-server';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function customServerGenerator(
   host: Tree,
@@ -71,12 +72,18 @@ export async function customServerGenerator(
     project.root
   }`;
 
+  const offset = offsetFromRoot(project.root);
+  const isTsSolution = isUsingTsSolutionSetup(host);
+
   generateFiles(host, join(__dirname, 'files'), project.root, {
     ...options,
     hasPlugin,
     projectPathFromDist,
-    offsetFromRoot: offsetFromRoot(project.root),
+    offsetFromRoot: offset,
     projectRoot: project.root,
+    baseTsConfigPath: isTsSolution
+      ? joinPathFragments(offset, 'tsconfig.base.json')
+      : './tsconfig.json',
     tmpl: '',
   });
 
diff --git a/packages/next/src/generators/custom-server/files/tsconfig.server.json__tmpl__ b/packages/next/src/generators/custom-server/files/tsconfig.server.json__tmpl__
index add47ecc0077a8..cb1f0313bf4fb7 100644
--- a/packages/next/src/generators/custom-server/files/tsconfig.server.json__tmpl__
+++ b/packages/next/src/generators/custom-server/files/tsconfig.server.json__tmpl__
@@ -1,7 +1,8 @@
 {
-  "extends": "./tsconfig.json",
+  "extends": "<%= baseTsConfigPath %>",
   "compilerOptions": {
-    "module": "commonjs",
+    "module": "nodenext",
+    "moduleResolution": "nodenext",
     "noEmit": false,
     "incremental": true,
     <% if(hasPlugin && compiler === 'tsc') { %>
diff --git a/packages/next/src/generators/init/init.ts b/packages/next/src/generators/init/init.ts
index b4796f64b06551..5d0c5e1faa865a 100644
--- a/packages/next/src/generators/init/init.ts
+++ b/packages/next/src/generators/init/init.ts
@@ -8,7 +8,6 @@ import {
   createProjectGraphAsync,
 } from '@nx/devkit';
 import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { reactDomVersion, reactVersion } from '@nx/react/src/utils/versions';
 import { addGitIgnoreEntry } from '../../utils/add-gitignore-entry';
 import { nextVersion, nxVersion } from '../../utils/versions';
@@ -46,8 +45,6 @@ export async function nextInitGeneratorInternal(
   host: Tree,
   schema: InitSchema
 ) {
-  assertNotUsingTsSolutionSetup(host, 'next', 'init');
-
   const nxJson = readNxJson(host);
   const addPluginDefault =
     process.env.NX_ADD_PLUGINS !== 'false' &&
diff --git a/packages/next/src/generators/library/library.ts b/packages/next/src/generators/library/library.ts
index f785ab1132e3e3..0269a3cf36a2cf 100644
--- a/packages/next/src/generators/library/library.ts
+++ b/packages/next/src/generators/library/library.ts
@@ -9,13 +9,13 @@ import {
 } from '@nx/devkit';
 import { libraryGenerator as reactLibraryGenerator } from '@nx/react/src/generators/library/library';
 import { addTsConfigPath, initGenerator as jsInitGenerator } from '@nx/js';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { testingLibraryReactVersion } from '@nx/react/src/utils/versions';
 
 import { nextInitGenerator } from '../init/init';
 import { Schema } from './schema';
 import { normalizeOptions } from './lib/normalize-options';
 import { eslintConfigNextVersion, tsLibVersion } from '../../utils/versions';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function libraryGenerator(host: Tree, rawOptions: Schema) {
   return await libraryGeneratorInternal(host, {
@@ -25,8 +25,6 @@ export async function libraryGenerator(host: Tree, rawOptions: Schema) {
 }
 
 export async function libraryGeneratorInternal(host: Tree, rawOptions: Schema) {
-  assertNotUsingTsSolutionSetup(host, 'next', 'library');
-
   const options = await normalizeOptions(host, rawOptions);
   const tasks: GeneratorCallback[] = [];
 
@@ -45,7 +43,7 @@ export async function libraryGeneratorInternal(host: Tree, rawOptions: Schema) {
 
   const libTask = await reactLibraryGenerator(host, {
     ...options,
-    compiler: 'swc',
+    bundler: 'none',
     skipFormat: true,
   });
   tasks.push(libTask);
@@ -142,6 +140,20 @@ export async function libraryGeneratorInternal(host: Tree, rawOptions: Schema) {
     }
   );
 
+  updateTsconfigFiles(
+    host,
+    options.projectRoot,
+    'tsconfig.lib.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
diff --git a/packages/next/src/generators/library/schema.d.ts b/packages/next/src/generators/library/schema.d.ts
index 72c7a282a4504a..8418bdd0ede74d 100644
--- a/packages/next/src/generators/library/schema.d.ts
+++ b/packages/next/src/generators/library/schema.d.ts
@@ -14,7 +14,9 @@ export interface Schema {
   linter: Linter | LinterType;
   component?: boolean;
   publishable?: boolean;
+  /** @deprecated Use bundler instead. */
   buildable?: boolean;
+  bundler?: 'none' | 'vite' | 'rollup';
   importPath?: string;
   js?: boolean;
   globalCss?: boolean;
diff --git a/packages/next/src/generators/library/schema.json b/packages/next/src/generators/library/schema.json
index 76fbfe2338c199..4ac42721138fa4 100644
--- a/packages/next/src/generators/library/schema.json
+++ b/packages/next/src/generators/library/schema.json
@@ -62,17 +62,29 @@
         ]
       }
     },
+    "bundler": {
+      "type": "string",
+      "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
+      "enum": ["none", "vite", "rollup"],
+      "default": "none",
+      "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
+      "x-priority": "important"
+    },
     "linter": {
       "description": "The tool to use for running lint checks.",
       "type": "string",
-      "enum": ["eslint"],
-      "default": "eslint"
+      "enum": ["eslint", "none"],
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["vitest", "jest", "none"],
       "description": "Test runner to use for unit tests.",
-      "default": "vitest"
+      "default": "none",
+      "x-prompt": "What unit test runner should be used?",
+      "x-priority": "important"
     },
     "tags": {
       "type": "string",
@@ -105,7 +117,8 @@
     "buildable": {
       "type": "boolean",
       "default": false,
-      "description": "Generate a buildable library."
+      "description": "Generate a buildable library that uses rollup to bundle.",
+      "x-deprecated": "Use the `bundler` option for greater control (none, vite, rollup)."
     },
     "importPath": {
       "type": "string",
diff --git a/packages/playwright/src/generators/configuration/configuration.ts b/packages/playwright/src/generators/configuration/configuration.ts
index dab57e23d9e98e..e245e8c4d22962 100644
--- a/packages/playwright/src/generators/configuration/configuration.ts
+++ b/packages/playwright/src/generators/configuration/configuration.ts
@@ -95,12 +95,17 @@ export async function configurationGeneratorInternal(
     };
 
     if (isTsSolutionSetup) {
+      // skip eslint from typechecking since it extends from root file that is outside rootDir
+      if (options.linter === 'eslint') {
+        tsconfig.exclude = ['dist', 'eslint.config.js'];
+      }
+
       tsconfig.compilerOptions.outDir = 'dist';
       tsconfig.compilerOptions.tsBuildInfoFile = 'dist/tsconfig.tsbuildinfo';
 
       if (!options.rootProject) {
-        // add the project tsconfog to the workspace root tsconfig.json references
         updateJson(tree, 'tsconfig.json', (json) => {
+          // add the project tsconfig to the workspace root tsconfig.json references
           json.references ??= [];
           json.references.push({ path: './' + projectConfig.root });
           return json;
@@ -130,6 +135,9 @@ export async function configurationGeneratorInternal(
         name: importPath,
         version: '0.0.1',
         private: true,
+        nx: {
+          name: options.project,
+        },
       };
       writeJson(tree, packageJsonPath, packageJson);
     }
diff --git a/packages/react-native/src/generators/application/application.spec.ts b/packages/react-native/src/generators/application/application.spec.ts
index 6dc0ea743aa177..5d2381ef171d19 100644
--- a/packages/react-native/src/generators/application/application.spec.ts
+++ b/packages/react-native/src/generators/application/application.spec.ts
@@ -5,6 +5,8 @@ import {
   getProjects,
   readJson,
   readProjectConfiguration,
+  updateJson,
+  writeJson,
 } from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import { Linter } from '@nx/eslint';
@@ -249,4 +251,152 @@ describe('app', () => {
       expect(readJson(appTree, 'package.json')).toEqual(packageJsonBefore);
     });
   });
+
+  describe('TS solution setup', () => {
+    it('should add project references when using TS solution', async () => {
+      const tree = createTreeWithEmptyWorkspace();
+      tree.write('.gitignore', '');
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+
+      await reactNativeApplicationGenerator(tree, {
+        directory: 'my-app',
+        displayName: 'myApp',
+        tags: 'one,two',
+        linter: Linter.EsLint,
+        e2eTestRunner: 'none',
+        install: false,
+        unitTestRunner: 'jest',
+        bundler: 'vite',
+        addPlugin: true,
+      });
+
+      expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./my-app",
+          },
+        ]
+      `);
+      expect(readJson(tree, 'my-app/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowSyntheticDefaultImports": true,
+            "declaration": true,
+            "jsx": "react-native",
+            "lib": [
+              "dom",
+              "esnext",
+            ],
+            "moduleResolution": "node",
+            "resolveJsonModule": true,
+            "skipLibCheck": true,
+          },
+          "extends": "../tsconfig.base.json",
+          "files": [],
+          "include": [],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+            {
+              "path": "./tsconfig.spec.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'my-app/tsconfig.app.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "lib": [
+              "dom",
+            ],
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "noUnusedLocals": false,
+            "outDir": "out-tsc/my-app",
+            "rootDir": "src",
+            "types": [
+              "node",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "jest.config.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.spec.tsx",
+            "src/test-setup.ts",
+            "src/**/*.test.ts",
+            "eslint.config.js",
+            "eslint.config.cjs",
+            "eslint.config.mjs",
+          ],
+          "extends": "../tsconfig.base.json",
+          "files": [
+            "../node_modules/@nx/react-native/typings/svg.d.ts",
+          ],
+          "include": [
+            "src/**/*.ts",
+            "src/**/*.tsx",
+            "src/**/*.js",
+            "src/**/*.jsx",
+          ],
+        }
+      `);
+      expect(readJson(tree, 'my-app/tsconfig.spec.json'))
+        .toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "lib": [
+              "dom",
+            ],
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "noUnusedLocals": false,
+            "outDir": "./out-tsc/jest",
+            "types": [
+              "jest",
+              "node",
+            ],
+          },
+          "extends": "../tsconfig.base.json",
+          "files": [
+            "src/test-setup.ts",
+          ],
+          "include": [
+            "jest.config.ts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.js",
+            "src/**/*.spec.js",
+            "src/**/*.test.jsx",
+            "src/**/*.spec.jsx",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+          ],
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/react-native/src/generators/application/application.ts b/packages/react-native/src/generators/application/application.ts
index 69a39350d0eccd..5518a43a0347a2 100644
--- a/packages/react-native/src/generators/application/application.ts
+++ b/packages/react-native/src/generators/application/application.ts
@@ -9,7 +9,6 @@ import {
 } from '@nx/devkit';
 import { initGenerator as jsInitGenerator } from '@nx/js';
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 import { addLinting } from '../../utils/add-linting';
 import { addJest } from '../../utils/add-jest';
@@ -26,6 +25,7 @@ import { Schema } from './schema';
 import { ensureDependencies } from '../../utils/ensure-dependencies';
 import { syncDeps } from '../../executors/sync-deps/sync-deps.impl';
 import { PackageJson } from 'nx/src/utils/package-json';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function reactNativeApplicationGenerator(
   host: Tree,
@@ -41,16 +41,16 @@ export async function reactNativeApplicationGeneratorInternal(
   host: Tree,
   schema: Schema
 ): Promise<GeneratorCallback> {
-  assertNotUsingTsSolutionSetup(host, 'react-native', 'application');
-
-  const options = await normalizeOptions(host, schema);
-
   const tasks: GeneratorCallback[] = [];
   const jsInitTask = await jsInitGenerator(host, {
     ...schema,
     skipFormat: true,
+    addTsPlugin: schema.useTsSolution,
+    formatter: schema.formatter,
   });
   tasks.push(jsInitTask);
+
+  const options = await normalizeOptions(host, schema);
   const initTask = await initGenerator(host, { ...options, skipFormat: true });
   tasks.push(initTask);
 
@@ -127,6 +127,22 @@ export async function reactNativeApplicationGeneratorInternal(
     });
   }
 
+  updateTsconfigFiles(
+    host,
+    options.appProjectRoot,
+    'tsconfig.app.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+      noUnusedLocals: false,
+      lib: ['dom'],
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
diff --git a/packages/react-native/src/generators/application/lib/add-project.ts b/packages/react-native/src/generators/application/lib/add-project.ts
index 6d9563c450ba24..b61a98b34c980b 100644
--- a/packages/react-native/src/generators/application/lib/add-project.ts
+++ b/packages/react-native/src/generators/application/lib/add-project.ts
@@ -1,11 +1,15 @@
 import {
   addProjectConfiguration,
+  joinPathFragments,
   ProjectConfiguration,
   readNxJson,
   TargetConfiguration,
   Tree,
+  writeJson,
 } from '@nx/devkit';
 import { NormalizedSchema } from './normalize-options';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { getImportPath } from '@nx/js/src/utils/get-import-path';
 
 export function addProject(host: Tree, options: NormalizedSchema) {
   const nxJson = readNxJson(host);
@@ -23,9 +27,24 @@ export function addProject(host: Tree, options: NormalizedSchema) {
     tags: options.parsedTags,
   };
 
-  addProjectConfiguration(host, options.projectName, {
-    ...project,
-  });
+  if (isUsingTsSolutionSetup(host)) {
+    writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
+      name: getImportPath(host, options.name),
+      version: '0.0.1',
+      private: true,
+      nx: {
+        name: options.name,
+        projectType: 'application',
+        sourceRoot: `${options.appProjectRoot}/src`,
+        targets: hasPlugin ? {} : getTargets(options),
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  } else {
+    addProjectConfiguration(host, options.projectName, {
+      ...project,
+    });
+  }
 }
 
 function getTargets(options: NormalizedSchema) {
diff --git a/packages/react-native/src/generators/application/schema.d.ts b/packages/react-native/src/generators/application/schema.d.ts
index b0066e4bd8a995..c7fba6dec1bf98 100644
--- a/packages/react-native/src/generators/application/schema.d.ts
+++ b/packages/react-native/src/generators/application/schema.d.ts
@@ -16,6 +16,9 @@ export interface Schema {
   bundler: 'webpack' | 'vite'; // default is webpack
   install: boolean; // default is true
   skipPackageJson?: boolean; //default is false
+  // Internal options
   addPlugin?: boolean;
   nxCloudToken?: string;
+  useTsSolution?: boolean;
+  formatter?: 'prettier' | 'none';
 }
diff --git a/packages/react-native/src/generators/application/schema.json b/packages/react-native/src/generators/application/schema.json
index a788cc695dd87a..8bbc3a51c112ec 100644
--- a/packages/react-native/src/generators/application/schema.json
+++ b/packages/react-native/src/generators/application/schema.json
@@ -44,13 +44,15 @@
       "description": "The tool to use for running lint checks.",
       "type": "string",
       "enum": ["eslint", "none"],
-      "default": "eslint"
+      "default": "none",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["jest", "none"],
       "description": "Test runner to use for unit tests",
-      "default": "jest"
+      "default": "none",
+      "x-priority": "important"
     },
     "tags": {
       "type": "string",
@@ -71,7 +73,8 @@
       "description": "Adds the specified e2e test runner.",
       "type": "string",
       "enum": ["playwright", "cypress", "detox", "none"],
-      "default": "playwright"
+      "default": "none",
+      "x-priority": "important"
     },
     "install": {
       "type": "boolean",
diff --git a/packages/react-native/src/generators/init/init.ts b/packages/react-native/src/generators/init/init.ts
index aba59a20254d60..c4719d5bf6e959 100644
--- a/packages/react-native/src/generators/init/init.ts
+++ b/packages/react-native/src/generators/init/init.ts
@@ -9,7 +9,6 @@ import {
   Tree,
 } from '@nx/devkit';
 import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { createNodes } from '../../../plugins/plugin';
 import {
   nxVersion,
@@ -31,8 +30,6 @@ export async function reactNativeInitGeneratorInternal(
   host: Tree,
   schema: Schema
 ) {
-  assertNotUsingTsSolutionSetup(host, 'react-native', 'init');
-
   addGitIgnoreEntry(host);
 
   const nxJson = readNxJson(host);
diff --git a/packages/react-native/src/generators/library/lib/normalize-options.ts b/packages/react-native/src/generators/library/lib/normalize-options.ts
index ec916e3aa2c708..b98a0c2a932ac1 100644
--- a/packages/react-native/src/generators/library/lib/normalize-options.ts
+++ b/packages/react-native/src/generators/library/lib/normalize-options.ts
@@ -4,6 +4,7 @@ import {
   ensureProjectName,
 } from '@nx/devkit/src/generators/project-name-and-root-utils';
 import { Schema } from '../schema';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export interface NormalizedSchema extends Schema {
   name: string;
@@ -13,6 +14,7 @@ export interface NormalizedSchema extends Schema {
   parsedTags: string[];
   appMain?: string;
   appSourceRoot?: string;
+  isUsingTsSolutionConfig: boolean;
 }
 
 export async function normalizeOptions(
@@ -50,6 +52,7 @@ export async function normalizeOptions(
     projectRoot,
     parsedTags,
     importPath,
+    isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
   };
 
   return normalized;
diff --git a/packages/react-native/src/generators/library/library.spec.ts b/packages/react-native/src/generators/library/library.spec.ts
index d9c0d403381e0a..31d182ce6ca6c3 100644
--- a/packages/react-native/src/generators/library/library.spec.ts
+++ b/packages/react-native/src/generators/library/library.spec.ts
@@ -227,6 +227,8 @@ describe('lib', () => {
           "compilerOptions": {
             "outDir": "../dist/out-tsc",
             "module": "commonjs",
+            "moduleResolution": "node10",
+            "jsx": "react-jsx",
             "types": ["jest", "node"]
           },
           "files": ["src/test-setup.ts"],
diff --git a/packages/react-native/src/generators/library/library.ts b/packages/react-native/src/generators/library/library.ts
index 7e5a8b3d4f3d7e..227cd2d302431d 100644
--- a/packages/react-native/src/generators/library/library.ts
+++ b/packages/react-native/src/generators/library/library.ts
@@ -4,6 +4,7 @@ import {
   formatFiles,
   generateFiles,
   GeneratorCallback,
+  installPackagesTask,
   joinPathFragments,
   names,
   offsetFromRoot,
@@ -13,6 +14,7 @@ import {
   Tree,
   updateJson,
   updateProjectConfiguration,
+  writeJson,
 } from '@nx/devkit';
 
 import {
@@ -32,7 +34,11 @@ import { NormalizedSchema, normalizeOptions } from './lib/normalize-options';
 import { Schema } from './schema';
 import { ensureDependencies } from '../../utils/ensure-dependencies';
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import {
+  isUsingTsSolutionSetup,
+  updateTsconfigFiles,
+} from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { getImportPath } from '@nx/js/src/utils/get-import-path';
 
 export async function reactNativeLibraryGenerator(
   host: Tree,
@@ -48,7 +54,13 @@ export async function reactNativeLibraryGeneratorInternal(
   host: Tree,
   schema: Schema
 ): Promise<GeneratorCallback> {
-  assertNotUsingTsSolutionSetup(host, 'react-native', 'library');
+  const tasks: GeneratorCallback[] = [];
+
+  const jsInitTask = await jsInitGenerator(host, {
+    ...schema,
+    skipFormat: true,
+  });
+  tasks.push(jsInitTask);
 
   const options = await normalizeOptions(host, schema);
   if (options.publishable === true && !schema.importPath) {
@@ -57,13 +69,6 @@ export async function reactNativeLibraryGeneratorInternal(
     );
   }
 
-  const tasks: GeneratorCallback[] = [];
-
-  const jsInitTask = await jsInitGenerator(host, {
-    ...schema,
-    skipFormat: true,
-  });
-  tasks.push(jsInitTask);
   const initTask = await init(host, { ...options, skipFormat: true });
   tasks.push(initTask);
 
@@ -111,11 +116,29 @@ export async function reactNativeLibraryGeneratorInternal(
       ),
     ]);
   }
+  updateTsconfigFiles(
+    host,
+    options.projectRoot,
+    'tsconfig.lib.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
 
   if (!options.skipFormat) {
     await formatFiles(host);
   }
 
+  // Always run install to link packages.
+  if (options.isUsingTsSolutionConfig) {
+    tasks.push(() => installPackagesTask(host));
+  }
+
   tasks.push(() => {
     logShowProjectCommand(options.name);
   });
@@ -135,7 +158,27 @@ async function addProject(
     targets: {},
   };
 
-  addProjectConfiguration(host, options.name, project);
+  if (options.isUsingTsSolutionConfig) {
+    const sourceEntry = !options.buildable
+      ? options.js
+        ? './src/index.js'
+        : './src/index.ts'
+      : undefined;
+    writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
+      name: getImportPath(host, options.name),
+      version: '0.0.1',
+      main: sourceEntry,
+      types: sourceEntry,
+      nx: {
+        name: options.name,
+        sourceRoot: joinPathFragments(options.projectRoot, 'src'),
+        projectType: 'library',
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  } else {
+    addProjectConfiguration(host, options.name, project);
+  }
 
   if (!options.publishable && !options.buildable) {
     return () => {};
diff --git a/packages/react-native/src/generators/library/schema.json b/packages/react-native/src/generators/library/schema.json
index 5ba6c572250403..41760ef45c23f2 100644
--- a/packages/react-native/src/generators/library/schema.json
+++ b/packages/react-native/src/generators/library/schema.json
@@ -32,13 +32,16 @@
       "description": "The tool to use for running lint checks.",
       "type": "string",
       "enum": ["eslint", "none"],
-      "default": "eslint"
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["jest", "none"],
       "description": "Test runner to use for unit tests.",
-      "default": "jest"
+      "default": "none",
+      "x-priority": "important"
     },
     "tags": {
       "type": "string",
diff --git a/packages/react-native/src/generators/web-configuration/web-configuration.ts b/packages/react-native/src/generators/web-configuration/web-configuration.ts
index 85204f46cf030b..4903940df5758c 100644
--- a/packages/react-native/src/generators/web-configuration/web-configuration.ts
+++ b/packages/react-native/src/generators/web-configuration/web-configuration.ts
@@ -12,7 +12,11 @@ import {
 } from '@nx/devkit';
 import { hasWebpackPlugin } from '@nx/react/src/utils/has-webpack-plugin';
 
-import { nxVersion, reactNativeWebVersion } from '../../utils/versions';
+import {
+  nxVersion,
+  reactNativeWebVersion,
+  typesReactDomVersion,
+} from '../../utils/versions';
 import { NormalizedSchema, normalizeSchema } from './lib/normalize-schema';
 import {
   createBuildTarget,
@@ -77,6 +81,18 @@ export async function webConfigurationGenerator(
     );
   }
 
+  if (!options.skipPackageJson) {
+    tasks.push(
+      addDependenciesToPackageJson(
+        tree,
+        {},
+        {
+          '@types/react-dom': typesReactDomVersion,
+        }
+      )
+    );
+  }
+
   if (!options.skipFormat) {
     await formatFiles(tree);
   }
@@ -103,6 +119,7 @@ async function addBundlerConfiguration(
       project: normalizedSchema.project,
       newProject: true,
       includeVitest: false,
+      projectType: 'application',
       compiler: 'babel',
       skipFormat: true,
     });
diff --git a/packages/react-native/src/utils/versions.ts b/packages/react-native/src/utils/versions.ts
index c209303b428659..aefe1624744ccf 100644
--- a/packages/react-native/src/utils/versions.ts
+++ b/packages/react-native/src/utils/versions.ts
@@ -14,6 +14,7 @@ export const reactVersion = '18.2.0';
 export const reactDomVersion = '18.2.0';
 export const reactTestRendererVersion = '18.2.0';
 export const typesReactVersion = '~18.2.45';
+export const typesReactDomVersion = '18.3.0';
 
 export const testingLibraryReactNativeVersion = '~12.5.0';
 export const testingLibraryJestNativeVersion = '~5.4.3';
diff --git a/packages/react/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/react/src/generators/application/__snapshots__/application.spec.ts.snap
index f971b87d9db336..0a05b6eb0842d3 100644
--- a/packages/react/src/generators/application/__snapshots__/application.spec.ts.snap
+++ b/packages/react/src/generators/application/__snapshots__/application.spec.ts.snap
@@ -1,8 +1,8 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`app --minimal should create default application without Nx welcome component 1`] = `
-"// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import styles from './app.module.css';
+"// Uncomment this line to use CSS modules
+// import styles from './app.module.css';
 
 export function App() {
   return (
@@ -239,8 +239,8 @@ export default defineConfig({
 `;
 
 exports[`app not nested should generate files 1`] = `
-"// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import styles from './app.module.css';
+"// Uncomment this line to use CSS modules
+// import styles from './app.module.css';
 import NxWelcome from './nx-welcome';
 
 export function App() {
@@ -343,8 +343,8 @@ module.exports = {
 `;
 
 exports[`app should create Nx specific template 1`] = `
-"// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import styles from './app.module.css';
+"// Uncomment this line to use CSS modules
+// import styles from './app.module.css';
 import NxWelcome from "./nx-welcome";
 
 export function App() {
diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts
index d94a8268388e71..874abcde483763 100644
--- a/packages/react/src/generators/application/application.spec.ts
+++ b/packages/react/src/generators/application/application.spec.ts
@@ -7,7 +7,9 @@ import {
   readJson,
   readNxJson,
   Tree,
+  updateJson,
   updateNxJson,
+  writeJson,
 } from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import { Linter } from '@nx/eslint';
@@ -276,7 +278,6 @@ describe('app', () => {
       expect(tsconfigApp.compilerOptions.outDir).toEqual('../dist/out-tsc');
       expect(tsconfigApp.extends).toEqual('./tsconfig.json');
       expect(tsconfigApp.exclude).toEqual([
-        'jest.config.ts',
         'src/**/*.spec.ts',
         'src/**/*.test.ts',
         'src/**/*.spec.tsx',
@@ -285,6 +286,7 @@ describe('app', () => {
         'src/**/*.test.js',
         'src/**/*.spec.jsx',
         'src/**/*.test.jsx',
+        'jest.config.ts',
       ]);
 
       const eslintJson = readJson(appTree, 'my-app/.eslintrc.json');
@@ -414,7 +416,6 @@ describe('app', () => {
           path: 'my-dir/my-app/tsconfig.app.json',
           lookupFn: (json) => json.exclude,
           expectedValue: [
-            'jest.config.ts',
             'src/**/*.spec.ts',
             'src/**/*.test.ts',
             'src/**/*.spec.tsx',
@@ -423,6 +424,7 @@ describe('app', () => {
             'src/**/*.test.js',
             'src/**/*.spec.jsx',
             'src/**/*.test.jsx',
+            'jest.config.ts',
           ],
         },
         {
@@ -1241,4 +1243,180 @@ describe('app', () => {
       }
     `);
   });
+
+  describe('TS solution setup', () => {
+    beforeEach(() => {
+      appTree = createTreeWithEmptyWorkspace();
+      updateJson(appTree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(appTree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(appTree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+    });
+
+    it('should add project references when using TS solution', async () => {
+      await applicationGenerator(appTree, {
+        directory: 'myapp',
+        addPlugin: true,
+        linter: Linter.EsLint,
+        style: 'none',
+        bundler: 'vite',
+        unitTestRunner: 'vitest',
+        e2eTestRunner: 'playwright',
+      });
+
+      expect(readJson(appTree, 'tsconfig.json').references)
+        .toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./myapp-e2e",
+          },
+          {
+            "path": "./myapp",
+          },
+        ]
+      `);
+      expect(readJson(appTree, 'myapp/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "extends": "../tsconfig.base.json",
+          "files": [],
+          "include": [],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+            {
+              "path": "./tsconfig.spec.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(appTree, 'myapp/tsconfig.app.json'))
+        .toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "lib": [
+              "dom",
+            ],
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "out-tsc/myapp",
+            "rootDir": "src",
+            "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
+            "types": [
+              "node",
+              "@nx/react/typings/cssmodule.d.ts",
+              "@nx/react/typings/image.d.ts",
+              "vite/client",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "src/**/*.spec.ts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.js",
+            "src/**/*.test.js",
+            "src/**/*.spec.jsx",
+            "src/**/*.test.jsx",
+            "vite.config.ts",
+            "vite.config.mts",
+            "vitest.config.ts",
+            "vitest.config.mts",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "src/**/*.js",
+            "src/**/*.jsx",
+            "src/**/*.ts",
+            "src/**/*.tsx",
+          ],
+        }
+      `);
+      expect(readJson(appTree, 'myapp/tsconfig.spec.json'))
+        .toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "./out-tsc/vitest",
+            "types": [
+              "vitest/globals",
+              "vitest/importMeta",
+              "vite/client",
+              "node",
+              "vitest",
+              "@nx/react/typings/cssmodule.d.ts",
+              "@nx/react/typings/image.d.ts",
+            ],
+          },
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "vite.config.ts",
+            "vite.config.mts",
+            "vitest.config.ts",
+            "vitest.config.mts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.js",
+            "src/**/*.spec.js",
+            "src/**/*.test.jsx",
+            "src/**/*.spec.jsx",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(appTree, 'myapp-e2e/tsconfig.json'))
+        .toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowJs": true,
+            "outDir": "dist",
+            "sourceMap": false,
+            "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
+          },
+          "exclude": [
+            "dist",
+            "eslint.config.js",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "**/*.ts",
+            "**/*.js",
+            "playwright.config.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.spec.js",
+            "src/**/*.test.ts",
+            "src/**/*.test.js",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "../myapp",
+            },
+          ],
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/react/src/generators/application/application.ts b/packages/react/src/generators/application/application.ts
index 283e72c7a19a3a..c9a421896e46a0 100644
--- a/packages/react/src/generators/application/application.ts
+++ b/packages/react/src/generators/application/application.ts
@@ -21,14 +21,9 @@ import {
   Tree,
   updateNxJson,
 } from '@nx/devkit';
-
 import reactInitGenerator from '../init/init';
 import { Linter, lintProjectGenerator } from '@nx/eslint';
-import {
-  babelLoaderVersion,
-  nxRspackVersion,
-  nxVersion,
-} from '../../utils/versions';
+import { babelLoaderVersion, nxVersion } from '../../utils/versions';
 import { maybeJs } from '../../utils/maybe-js';
 import { installCommonDependencies } from './lib/install-common-dependencies';
 import { extractTsConfigBase } from '../../utils/create-ts-config';
@@ -46,7 +41,7 @@ import { initGenerator as jsInitGenerator } from '@nx/js';
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
 import { setupTailwindGenerator } from '../setup-tailwind/setup-tailwind';
 import { useFlatConfig } from '@nx/eslint/src/utils/flat-config';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 async function addLinting(host: Tree, options: NormalizedSchema) {
   const tasks: GeneratorCallback[] = [];
@@ -114,20 +109,20 @@ export async function applicationGeneratorInternal(
   host: Tree,
   schema: Schema
 ): Promise<GeneratorCallback> {
-  assertNotUsingTsSolutionSetup(host, 'react', 'application');
-
   const tasks = [];
 
-  const options = await normalizeOptions(host, schema);
-  showPossibleWarnings(host, options);
-
   const jsInitTask = await jsInitGenerator(host, {
     ...schema,
     tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json',
     skipFormat: true,
+    addTsPlugin: schema.useTsSolution,
+    formatter: schema.formatter,
   });
   tasks.push(jsInitTask);
 
+  const options = await normalizeOptions(host, schema);
+  showPossibleWarnings(host, options);
+
   const initTask = await reactInitGenerator(host, {
     ...options,
     skipFormat: true,
@@ -165,10 +160,7 @@ export async function applicationGeneratorInternal(
       tasks.push(ensureDependencies(host, { uiFramework: 'react' }));
     }
   } else if (options.bundler === 'rspack') {
-    const { rspackInitGenerator } = ensurePackage(
-      '@nx/rspack',
-      nxRspackVersion
-    );
+    const { rspackInitGenerator } = ensurePackage('@nx/rspack', nxVersion);
     const rspackInitTask = await rspackInitGenerator(host, {
       ...options,
       addPlugin: false,
@@ -213,6 +205,7 @@ export async function applicationGeneratorInternal(
       compiler: options.compiler,
       skipFormat: true,
       addPlugin: options.addPlugin,
+      projectType: 'application',
     });
     tasks.push(viteTask);
     createOrEditViteConfig(
@@ -236,6 +229,26 @@ export async function applicationGeneratorInternal(
       },
       false
     );
+  } else if (options.bundler === 'rspack') {
+    const { configurationGenerator } = ensurePackage('@nx/rspack', nxVersion);
+    const rspackTask = await configurationGenerator(host, {
+      project: options.projectName,
+      main: joinPathFragments(
+        options.appProjectRoot,
+        maybeJs(
+          {
+            js: options.js,
+            useJsx: true,
+          },
+          `src/main.tsx`
+        )
+      ),
+      tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
+      target: 'web',
+      newProject: true,
+      framework: 'react',
+    });
+    tasks.push(rspackTask);
   }
 
   if (options.bundler !== 'vite' && options.unitTestRunner === 'vitest') {
@@ -348,6 +361,12 @@ export async function applicationGeneratorInternal(
     );
   }
 
+  updateTsconfigFiles(host, options.appProjectRoot, 'tsconfig.app.json', {
+    jsx: 'react-jsx',
+    module: 'esnext',
+    moduleResolution: 'bundler',
+  });
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
diff --git a/packages/react/src/generators/application/files/base-rspack/tsconfig.app.json__tmpl__ b/packages/react/src/generators/application/files/base-rspack/tsconfig.app.json__tmpl__
index 8bdce3f07d6ac3..8b1bc8bb50853f 100644
--- a/packages/react/src/generators/application/files/base-rspack/tsconfig.app.json__tmpl__
+++ b/packages/react/src/generators/application/files/base-rspack/tsconfig.app.json__tmpl__
@@ -1,14 +1,31 @@
-{
+<%_ if (isUsingTsSolutionSetup) { _%>{
+  "extends": "<%= offsetFromRoot%>tsconfig.base.json",
+  "compilerOptions": {
+    "outDir": "dist",
+    "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
+    "jsx": "react-jsx",
+    "lib": ["dom"],
+    "types": [
+      "node",
+      <%_ if (style === 'styled-jsx') { _%>"@nx/react/typings/styled-jsx.d.ts",<%_ } _%>
+      "@nx/react/typings/cssmodule.d.ts",
+      "@nx/react/typings/image.d.ts"
+    ]
+  },
+  "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
+  "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
+}<% } else { %>{
   "extends": "./tsconfig.json",
   "compilerOptions": {
     "outDir": "<%= offsetFromRoot %>dist/out-tsc",
     "types": [
       "node",
-      <%_ if (style === 'styled-jsx') { %>"@nx/react/typings/styled-jsx.d.ts",<% } _%>
+      <%_ if (style === 'styled-jsx') { _%>"@nx/react/typings/styled-jsx.d.ts",<%_ } _%>
       "@nx/react/typings/cssmodule.d.ts",
       "@nx/react/typings/image.d.ts"
-      ]
+    ]
   },
-  "exclude": ["jest.config.ts","src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
+  "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
   "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
 }
+<% } %>
diff --git a/packages/react/src/generators/application/files/base-vite/tsconfig.app.json__tmpl__ b/packages/react/src/generators/application/files/base-vite/tsconfig.app.json__tmpl__
index 80a1b8ebf4c4a2..8b1bc8bb50853f 100644
--- a/packages/react/src/generators/application/files/base-vite/tsconfig.app.json__tmpl__
+++ b/packages/react/src/generators/application/files/base-vite/tsconfig.app.json__tmpl__
@@ -1,4 +1,20 @@
-{
+<%_ if (isUsingTsSolutionSetup) { _%>{
+  "extends": "<%= offsetFromRoot%>tsconfig.base.json",
+  "compilerOptions": {
+    "outDir": "dist",
+    "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
+    "jsx": "react-jsx",
+    "lib": ["dom"],
+    "types": [
+      "node",
+      <%_ if (style === 'styled-jsx') { _%>"@nx/react/typings/styled-jsx.d.ts",<%_ } _%>
+      "@nx/react/typings/cssmodule.d.ts",
+      "@nx/react/typings/image.d.ts"
+    ]
+  },
+  "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
+  "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
+}<% } else { %>{
   "extends": "./tsconfig.json",
   "compilerOptions": {
     "outDir": "<%= offsetFromRoot %>dist/out-tsc",
@@ -7,8 +23,9 @@
       <%_ if (style === 'styled-jsx') { _%>"@nx/react/typings/styled-jsx.d.ts",<%_ } _%>
       "@nx/react/typings/cssmodule.d.ts",
       "@nx/react/typings/image.d.ts"
-      ]
+    ]
   },
   "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
   "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
 }
+<% } %>
diff --git a/packages/react/src/generators/application/files/base-webpack/tsconfig.app.json__tmpl__ b/packages/react/src/generators/application/files/base-webpack/tsconfig.app.json__tmpl__
index 03309c7d0f9264..8b1bc8bb50853f 100644
--- a/packages/react/src/generators/application/files/base-webpack/tsconfig.app.json__tmpl__
+++ b/packages/react/src/generators/application/files/base-webpack/tsconfig.app.json__tmpl__
@@ -1,4 +1,20 @@
-{
+<%_ if (isUsingTsSolutionSetup) { _%>{
+  "extends": "<%= offsetFromRoot%>tsconfig.base.json",
+  "compilerOptions": {
+    "outDir": "dist",
+    "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
+    "jsx": "react-jsx",
+    "lib": ["dom"],
+    "types": [
+      "node",
+      <%_ if (style === 'styled-jsx') { _%>"@nx/react/typings/styled-jsx.d.ts",<%_ } _%>
+      "@nx/react/typings/cssmodule.d.ts",
+      "@nx/react/typings/image.d.ts"
+    ]
+  },
+  "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
+  "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
+}<% } else { %>{
   "extends": "./tsconfig.json",
   "compilerOptions": {
     "outDir": "<%= offsetFromRoot %>dist/out-tsc",
@@ -7,8 +23,9 @@
       <%_ if (style === 'styled-jsx') { _%>"@nx/react/typings/styled-jsx.d.ts",<%_ } _%>
       "@nx/react/typings/cssmodule.d.ts",
       "@nx/react/typings/image.d.ts"
-      ]
+    ]
   },
-  "exclude": ["jest.config.ts","src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
+  "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "src/**/*.spec.tsx", "src/**/*.test.tsx", "src/**/*.spec.js", "src/**/*.test.js", "src/**/*.spec.jsx", "src/**/*.test.jsx"],
   "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
 }
+<% } %>
diff --git a/packages/react/src/generators/application/files/style-css-module/src/app/__fileName__.tsx__tmpl__ b/packages/react/src/generators/application/files/style-css-module/src/app/__fileName__.tsx__tmpl__
index 4f04c1a17dbca7..59f0f480112ee0 100644
--- a/packages/react/src/generators/application/files/style-css-module/src/app/__fileName__.tsx__tmpl__
+++ b/packages/react/src/generators/application/files/style-css-module/src/app/__fileName__.tsx__tmpl__
@@ -1,8 +1,8 @@
 <% if (classComponent) { %>
 import { Component } from 'react';
 <%_ } _%>
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import styles from './<%= fileName %>.module.<%= style %>';
+// Uncomment this line to use CSS modules
+// import styles from './<%= fileName %>.module.<%= style %>';
 <%_ if (!minimal) { _%>
 import NxWelcome from "./nx-welcome";
 <%_ } _%>
diff --git a/packages/react/src/generators/application/lib/add-e2e.ts b/packages/react/src/generators/application/lib/add-e2e.ts
index e84ecea5f57a57..2f43036fb69530 100644
--- a/packages/react/src/generators/application/lib/add-e2e.ts
+++ b/packages/react/src/generators/application/lib/add-e2e.ts
@@ -1,10 +1,12 @@
-import type { GeneratorCallback, Tree } from '@nx/devkit';
 import {
   addProjectConfiguration,
   ensurePackage,
+  GeneratorCallback,
   getPackageManagerCommand,
   joinPathFragments,
   readNxJson,
+  Tree,
+  writeJson,
 } from '@nx/devkit';
 import { webStaticServeGenerator } from '@nx/web';
 
@@ -81,14 +83,31 @@ export async function addE2e(
         typeof import('@nx/cypress')
       >('@nx/cypress', nxVersion);
 
-      addProjectConfiguration(tree, options.e2eProjectName, {
-        projectType: 'application',
-        root: options.e2eProjectRoot,
-        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-        targets: {},
-        implicitDependencies: [options.projectName],
-        tags: [],
-      });
+      if (options.isUsingTsSolutionConfig) {
+        writeJson(
+          tree,
+          joinPathFragments(options.e2eProjectRoot, 'package.json'),
+          {
+            name: options.e2eProjectName,
+            version: '0.0.1',
+            private: true,
+            nx: {
+              projectType: 'application',
+              sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+              implicitDependencies: [options.projectName],
+            },
+          }
+        );
+      } else {
+        addProjectConfiguration(tree, options.e2eProjectName, {
+          projectType: 'application',
+          root: options.e2eProjectRoot,
+          sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+          targets: {},
+          implicitDependencies: [options.projectName],
+          tags: [],
+        });
+      }
 
       const e2eTask = await configurationGenerator(tree, {
         ...options,
@@ -157,13 +176,31 @@ export async function addE2e(
       const { configurationGenerator } = ensurePackage<
         typeof import('@nx/playwright')
       >('@nx/playwright', nxVersion);
-      addProjectConfiguration(tree, options.e2eProjectName, {
-        projectType: 'application',
-        root: options.e2eProjectRoot,
-        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-        targets: {},
-        implicitDependencies: [options.projectName],
-      });
+      if (options.isUsingTsSolutionConfig) {
+        writeJson(
+          tree,
+          joinPathFragments(options.e2eProjectRoot, 'package.json'),
+          {
+            name: options.e2eProjectName,
+            version: '0.0.1',
+            private: true,
+            nx: {
+              projectType: 'application',
+              sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+              implicitDependencies: [options.projectName],
+            },
+          }
+        );
+      } else {
+        addProjectConfiguration(tree, options.e2eProjectName, {
+          projectType: 'application',
+          root: options.e2eProjectRoot,
+          sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+          targets: {},
+          implicitDependencies: [options.projectName],
+        });
+      }
+
       const e2eTask = await configurationGenerator(tree, {
         project: options.e2eProjectName,
         skipFormat: true,
diff --git a/packages/react/src/generators/application/lib/add-jest.ts b/packages/react/src/generators/application/lib/add-jest.ts
index aceef21632f081..23f3af529f6ef1 100644
--- a/packages/react/src/generators/application/lib/add-jest.ts
+++ b/packages/react/src/generators/application/lib/add-jest.ts
@@ -23,5 +23,6 @@ export async function addJest(
     setupFile: 'none',
     compiler: options.compiler,
     skipFormat: true,
+    runtimeTsconfigFileName: 'tsconfig.app.json',
   });
 }
diff --git a/packages/react/src/generators/application/lib/add-project.ts b/packages/react/src/generators/application/lib/add-project.ts
index fd494e64a1de0e..a4cee10a39ac8a 100644
--- a/packages/react/src/generators/application/lib/add-project.ts
+++ b/packages/react/src/generators/application/lib/add-project.ts
@@ -5,10 +5,12 @@ import {
   ProjectConfiguration,
   TargetConfiguration,
   Tree,
+  writeJson,
 } from '@nx/devkit';
 import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
 import { maybeJs } from '../../../utils/maybe-js';
 import { hasRspackPlugin } from '../../../utils/has-rspack-plugin';
+import { getImportPath } from '@nx/js/src/utils/get-import-path';
 
 export function addProject(host: Tree, options: NormalizedSchema) {
   const project: ProjectConfiguration = {
@@ -36,9 +38,25 @@ export function addProject(host: Tree, options: NormalizedSchema) {
     };
   }
 
-  addProjectConfiguration(host, options.projectName, {
-    ...project,
-  });
+  if (options.isUsingTsSolutionConfig) {
+    writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
+      name: getImportPath(host, options.name),
+      version: '0.0.1',
+      private: true,
+      nx: {
+        name: options.name,
+        projectType: 'application',
+        sourceRoot: `${options.appProjectRoot}/src`,
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  }
+
+  if (!options.isUsingTsSolutionConfig || options.alwaysGenerateProjectJson) {
+    addProjectConfiguration(host, options.projectName, {
+      ...project,
+    });
+  }
 }
 
 function createRspackBuildTarget(
diff --git a/packages/react/src/generators/application/lib/create-application-files.ts b/packages/react/src/generators/application/lib/create-application-files.ts
index dbc60719337030..d84b28be9aead3 100644
--- a/packages/react/src/generators/application/lib/create-application-files.ts
+++ b/packages/react/src/generators/application/lib/create-application-files.ts
@@ -18,10 +18,11 @@ import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
 import { NormalizedSchema } from '../schema';
 import { getAppTests } from './get-app-tests';
 import {
-  getNxCloudAppOnBoardingUrl,
   createNxCloudOnboardingURLForWelcomeApp,
+  getNxCloudAppOnBoardingUrl,
 } from 'nx/src/nx-cloud/utilities/onboarding';
 import { hasRspackPlugin } from '../../../utils/has-rspack-plugin';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function createApplicationFiles(
   host: Tree,
@@ -67,6 +68,7 @@ export async function createApplicationFiles(
     inSourceVitestTests: getInSourceVitestTestsTemplate(appTests),
     style: options.style === 'tailwind' ? 'css' : options.style,
     hasStyleFile,
+    isUsingTsSolutionSetup: isUsingTsSolutionSetup(host),
   };
 
   if (options.bundler === 'vite') {
diff --git a/packages/react/src/generators/application/lib/normalize-options.ts b/packages/react/src/generators/application/lib/normalize-options.ts
index 6cb6a6080ef67f..37768a6a0d36e4 100644
--- a/packages/react/src/generators/application/lib/normalize-options.ts
+++ b/packages/react/src/generators/application/lib/normalize-options.ts
@@ -6,6 +6,7 @@ import {
 import { assertValidStyle } from '../../../utils/assertion';
 import { NormalizedSchema, Schema } from '../schema';
 import { findFreePort } from './find-free-port';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function normalizeDirectory(options: Schema) {
   options.directory = options.directory?.replace(/\\{1,2}/g, '/');
@@ -67,6 +68,7 @@ export async function normalizeOptions<T extends Schema = Schema>(
     fileName,
     styledModule,
     hasStyles: options.style !== 'none',
+    isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
   } as NormalizedSchema;
 
   normalized.routing = normalized.routing ?? false;
diff --git a/packages/react/src/generators/application/lib/update-jest-config.ts b/packages/react/src/generators/application/lib/update-jest-config.ts
index 62e279dc87a4a0..84eb70612a07be 100644
--- a/packages/react/src/generators/application/lib/update-jest-config.ts
+++ b/packages/react/src/generators/application/lib/update-jest-config.ts
@@ -20,6 +20,11 @@ export function updateSpecConfig(host: Tree, options: NormalizedSchema) {
     );
     compilerOptions.types = types;
     json.compilerOptions = compilerOptions;
+    if (options.isUsingTsSolutionConfig) {
+      // add project reference to the runtime tsconfig.app.json file
+      json.references ??= [];
+      json.references.push({ path: './tsconfig.app.json' });
+    }
     return json;
   });
 
diff --git a/packages/react/src/generators/application/schema.d.ts b/packages/react/src/generators/application/schema.d.ts
index c0acac95870e0e..0dc79aaf1dfbb2 100644
--- a/packages/react/src/generators/application/schema.d.ts
+++ b/packages/react/src/generators/application/schema.d.ts
@@ -25,8 +25,12 @@ export interface Schema {
   rootProject?: boolean;
   bundler?: 'webpack' | 'vite' | 'rspack';
   minimal?: boolean;
+  // Internal options
   addPlugin?: boolean;
   nxCloudToken?: string;
+  useTsSolution?: boolean;
+  formatter?: 'prettier' | 'none';
+  alwaysGenerateProjectJson?: boolean; // this is needed for MF currently
 }
 
 export interface NormalizedSchema<T extends Schema = Schema> extends T {
@@ -40,4 +44,5 @@ export interface NormalizedSchema<T extends Schema = Schema> extends T {
   hasStyles: boolean;
   unitTestRunner: 'jest' | 'vitest' | 'none';
   addPlugin?: boolean;
+  isUsingTsSolutionConfig?: boolean;
 }
diff --git a/packages/react/src/generators/application/schema.json b/packages/react/src/generators/application/schema.json
index 0e331b3bccb9d0..48c0dffa5d9dad 100644
--- a/packages/react/src/generators/application/schema.json
+++ b/packages/react/src/generators/application/schema.json
@@ -80,12 +80,6 @@
         ]
       }
     },
-    "linter": {
-      "description": "The tool to use for running lint checks.",
-      "type": "string",
-      "enum": ["eslint", "none"],
-      "default": "eslint"
-    },
     "routing": {
       "type": "boolean",
       "description": "Generate application with routes.",
@@ -104,11 +98,29 @@
       "default": false,
       "x-priority": "internal"
     },
+    "bundler": {
+      "description": "The bundler to use.",
+      "type": "string",
+      "enum": ["vite", "webpack", "rspack"],
+      "x-prompt": "Which bundler do you want to use to build the application?",
+      "default": "vite",
+      "x-priority": "important"
+    },
+    "linter": {
+      "description": "The tool to use for running lint checks.",
+      "type": "string",
+      "enum": ["eslint", "none"],
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
+    },
     "unitTestRunner": {
       "type": "string",
       "enum": ["vitest", "jest", "none"],
       "description": "Test runner to use for unit tests.",
-      "default": "vitest"
+      "default": "none",
+      "x-prompt": "What unit test runner should be used?",
+      "x-priority": "important"
     },
     "inSourceTests": {
       "type": "boolean",
@@ -171,14 +183,6 @@
       "default": false,
       "hidden": true
     },
-    "bundler": {
-      "description": "The bundler to use.",
-      "type": "string",
-      "enum": ["vite", "webpack", "rspack"],
-      "x-prompt": "Which bundler do you want to use to build the application?",
-      "default": "vite",
-      "x-priority": "important"
-    },
     "minimal": {
       "description": "Generate a React app with a minimal setup, no separate test files.",
       "type": "boolean",
diff --git a/packages/react/src/generators/component/component.spec.ts b/packages/react/src/generators/component/component.spec.ts
index 534648b3b3e400..76555e45f042d8 100644
--- a/packages/react/src/generators/component/component.spec.ts
+++ b/packages/react/src/generators/component/component.spec.ts
@@ -162,7 +162,7 @@ describe('component', () => {
 
       const indexContent = appTree.read('my-lib/src/index.ts', 'utf-8');
 
-      expect(indexContent).not.toMatch(/lib\/hello/);
+      expect(indexContent).toMatch(/lib\/hello/);
     });
   });
 
diff --git a/packages/react/src/generators/component/component.ts b/packages/react/src/generators/component/component.ts
index 5c5473d8f301f8..d532e074062fb3 100644
--- a/packages/react/src/generators/component/component.ts
+++ b/packages/react/src/generators/component/component.ts
@@ -106,10 +106,17 @@ function addExportsToBarrel(host: Tree, options: NormalizedSchema) {
     workspace.get(options.projectName).projectType === 'application';
 
   if (options.export && !isApp) {
-    const indexFilePath = joinPathFragments(
-      options.projectSourceRoot,
-      options.js ? 'index.js' : 'index.ts'
-    );
+    const indexFilePath = options.projectSourceRoot
+      ? joinPathFragments(
+          options.projectSourceRoot,
+          options.js ? 'index.js' : 'index.ts'
+        )
+      : joinPathFragments(
+          options.projectRoot,
+          'src',
+          options.js ? 'index.js' : 'index.ts'
+        );
+
     const indexSource = host.read(indexFilePath, 'utf-8');
     if (indexSource !== null) {
       const indexSourceFile = tsModule.createSourceFile(
diff --git a/packages/react/src/generators/component/lib/normalize-options.ts b/packages/react/src/generators/component/lib/normalize-options.ts
index c61b1409525c6e..3ea86c7d1c4937 100644
--- a/packages/react/src/generators/component/lib/normalize-options.ts
+++ b/packages/react/src/generators/component/lib/normalize-options.ts
@@ -61,6 +61,7 @@ export async function normalizeOptions(
     className,
     fileName,
     filePath,
-    projectSourceRoot: projectSourceRoot ?? projectRoot,
+    projectRoot,
+    projectSourceRoot: projectSourceRoot,
   };
 }
diff --git a/packages/react/src/generators/component/schema.d.ts b/packages/react/src/generators/component/schema.d.ts
index f3860e29acadf9..f6558748bcd16e 100644
--- a/packages/react/src/generators/component/schema.d.ts
+++ b/packages/react/src/generators/component/schema.d.ts
@@ -19,6 +19,7 @@ export interface Schema {
 
 export interface NormalizedSchema extends Schema {
   directory: string;
+  projectRoot: string;
   projectSourceRoot: string;
   projectName: string;
   fileName: string;
diff --git a/packages/react/src/generators/host/host.rspack.spec.ts b/packages/react/src/generators/host/host.rspack.spec.ts
index 7aaec551dbf787..032ab68ce10d62 100644
--- a/packages/react/src/generators/host/host.rspack.spec.ts
+++ b/packages/react/src/generators/host/host.rspack.spec.ts
@@ -1,5 +1,5 @@
 import * as devkit from '@nx/devkit';
-import type { Tree } from '@nx/devkit';
+import { Tree, updateJson, writeJson } from '@nx/devkit';
 import { ProjectGraph, readJson } from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import hostGenerator from './host';
@@ -426,4 +426,126 @@ describe('hostGenerator', () => {
       `);
     });
   });
+
+  describe('TS solution setup', () => {
+    beforeEach(() => {
+      tree = createTreeWithEmptyWorkspace();
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+    });
+
+    it('should add project references when using TS solution', async () => {
+      await hostGenerator(tree, {
+        directory: 'myapp',
+        addPlugin: true,
+        remotes: ['remote1', 'remote2', 'remote3'],
+        e2eTestRunner: 'none',
+        linter: Linter.None,
+        style: 'css',
+        unitTestRunner: 'none',
+        typescriptConfiguration: false,
+        bundler: 'rspack',
+      });
+
+      expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./myapp",
+          },
+          {
+            "path": "./remote1",
+          },
+          {
+            "path": "./remote2",
+          },
+          {
+            "path": "./remote3",
+          },
+        ]
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "extends": "../tsconfig.base.json",
+          "files": [],
+          "include": [],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+            {
+              "path": "../remote1",
+            },
+            {
+              "path": "../remote2",
+            },
+            {
+              "path": "../remote3",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.app.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "lib": [
+              "dom",
+            ],
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "out-tsc/myapp",
+            "rootDir": "src",
+            "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
+            "types": [
+              "node",
+              "@nx/react/typings/cssmodule.d.ts",
+              "@nx/react/typings/image.d.ts",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "src/**/*.spec.ts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.js",
+            "src/**/*.test.js",
+            "src/**/*.spec.jsx",
+            "src/**/*.test.jsx",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "src/**/*.js",
+            "src/**/*.jsx",
+            "src/**/*.ts",
+            "src/**/*.tsx",
+          ],
+          "references": [
+            {
+              "path": "../remote1/tsconfig.app.json",
+            },
+            {
+              "path": "../remote2/tsconfig.app.json",
+            },
+            {
+              "path": "../remote3/tsconfig.app.json",
+            },
+          ],
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/react/src/generators/host/host.ts b/packages/react/src/generators/host/host.ts
index 84ae83e851e3b5..fcd302431dc268 100644
--- a/packages/react/src/generators/host/host.ts
+++ b/packages/react/src/generators/host/host.ts
@@ -28,14 +28,12 @@ import {
   nxVersion,
 } from '../../utils/versions';
 import { ensureProjectName } from '@nx/devkit/src/generators/project-name-and-root-utils';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { updateModuleFederationTsconfig } from './lib/update-module-federation-tsconfig';
 
 export async function hostGenerator(
   host: Tree,
   schema: Schema
 ): Promise<GeneratorCallback> {
-  assertNotUsingTsSolutionSetup(host, 'react', 'host');
-
   const tasks: GeneratorCallback[] = [];
   const options: NormalizedSchema = {
     ...(await normalizeOptions<Schema>(host, schema)),
@@ -70,6 +68,7 @@ export async function hostGenerator(
     // The target use-case is loading remotes as child routes, thus always enable routing.
     routing: true,
     skipFormat: true,
+    alwaysGenerateProjectJson: true,
   });
   tasks.push(initTask);
 
@@ -106,6 +105,7 @@ export async function hostGenerator(
   addModuleFederationFiles(host, options, remotesWithPorts);
   updateModuleFederationProject(host, options);
   updateModuleFederationE2eProject(host, options);
+  updateModuleFederationTsconfig(host, options);
 
   if (options.ssr) {
     const setupSsrTask = await setupSsrGenerator(host, {
diff --git a/packages/react/src/generators/host/lib/update-module-federation-tsconfig.ts b/packages/react/src/generators/host/lib/update-module-federation-tsconfig.ts
new file mode 100644
index 00000000000000..1cd0b4cf6168d4
--- /dev/null
+++ b/packages/react/src/generators/host/lib/update-module-federation-tsconfig.ts
@@ -0,0 +1,48 @@
+import { joinPathFragments, type Tree, updateJson } from '@nx/devkit';
+import { NormalizedSchema } from '../schema';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+
+export function updateModuleFederationTsconfig(
+  host: Tree,
+  options: NormalizedSchema
+) {
+  const tsconfigPath = joinPathFragments(
+    options.appProjectRoot,
+    'tsconfig.json'
+  );
+  const tsconfigRuntimePath = joinPathFragments(
+    options.appProjectRoot,
+    'tsconfig.app.json'
+  );
+  if (!host.exists(tsconfigPath) || !host.exists(tsconfigRuntimePath)) return;
+
+  // Not setting `baseUrl` does not work with MF.
+  if (isUsingTsSolutionSetup(host)) {
+    updateJson(host, 'tsconfig.base.json', (json) => {
+      json.compilerOptions.baseUrl = '.';
+      return json;
+    });
+
+    // Update references to match what `nx sync` does.
+    if (options.remotes?.length) {
+      updateJson(host, tsconfigPath, (json) => {
+        json.references ??= [];
+        for (const remote of options.remotes) {
+          const remotePath = `../${remote}`;
+          if (!json.references.some((ref) => ref.path === remotePath))
+            json.references.push({ path: remotePath });
+        }
+        return json;
+      });
+      updateJson(host, tsconfigRuntimePath, (json) => {
+        json.references ??= [];
+        for (const remote of options.remotes) {
+          const remotePath = `../${remote}/tsconfig.app.json`;
+          if (!json.references.some((ref) => ref.path === remotePath))
+            json.references.push({ path: remotePath });
+        }
+        return json;
+      });
+    }
+  }
+}
diff --git a/packages/react/src/generators/init/init.ts b/packages/react/src/generators/init/init.ts
index 2f63ee51df9596..105e863d62793d 100755
--- a/packages/react/src/generators/init/init.ts
+++ b/packages/react/src/generators/init/init.ts
@@ -6,13 +6,10 @@ import {
   type GeneratorCallback,
   type Tree,
 } from '@nx/devkit';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { nxVersion, reactDomVersion, reactVersion } from '../../utils/versions';
 import { InitSchema } from './schema';
 
 export async function reactInitGenerator(host: Tree, schema: InitSchema) {
-  assertNotUsingTsSolutionSetup(host, 'react', 'init');
-
   const tasks: GeneratorCallback[] = [];
 
   if (!schema.skipPackageJson) {
diff --git a/packages/react/src/generators/library/files/common/package.json__tmpl__ b/packages/react/src/generators/library/files/common/package.json__tmpl__
deleted file mode 100644
index fa518765a372fc..00000000000000
--- a/packages/react/src/generators/library/files/common/package.json__tmpl__
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "<%= name %>",
-  "version": "0.0.1"
-}
diff --git a/packages/react/src/generators/library/files/vite/package.json__tmpl__ b/packages/react/src/generators/library/files/vite/package.json__tmpl__
deleted file mode 100644
index 507420ee308347..00000000000000
--- a/packages/react/src/generators/library/files/vite/package.json__tmpl__
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name": "<%= name %>",
-  "version": "0.0.1",
-  "main": "./index.js",
-  "types": "./index.d.ts",
-  "exports": {
-    ".": {
-      "import": "./index.mjs",
-      "require": "./index.js"
-    }
-  }
-}
diff --git a/packages/react/src/generators/library/lib/create-files.ts b/packages/react/src/generators/library/lib/create-files.ts
index e5163ff7c6c2bb..e873b26d7ecc1c 100644
--- a/packages/react/src/generators/library/lib/create-files.ts
+++ b/packages/react/src/generators/library/lib/create-files.ts
@@ -1,10 +1,10 @@
-import type { Tree } from '@nx/devkit';
 import {
   generateFiles,
   joinPathFragments,
   names,
   offsetFromRoot,
   toJS,
+  Tree,
   writeJson,
 } from '@nx/devkit';
 import { getRelativePathToRootTsConfig } from '@nx/js';
@@ -68,8 +68,29 @@ export function createFiles(host: Tree, options: NormalizedSchema) {
     });
   }
 
-  if (!options.publishable && !options.buildable) {
-    host.delete(`${options.projectRoot}/package.json`);
+  if (
+    (options.publishable || options.buildable) &&
+    !options.isUsingTsSolutionConfig
+  ) {
+    if (options.bundler === 'vite') {
+      writeJson(host, `${options.projectRoot}/package.json`, {
+        name: options.importPath,
+        version: '0.0.1',
+        main: './index.js',
+        types: './index.d.ts',
+        exports: {
+          '.': {
+            import: './index.mjs',
+            require: './index.js',
+          },
+        },
+      });
+    } else {
+      writeJson(host, `${options.projectRoot}/package.json`, {
+        name: options.importPath,
+        version: '0.0.1',
+      });
+    }
   }
 
   if (options.js) {
diff --git a/packages/react/src/generators/library/lib/normalize-options.ts b/packages/react/src/generators/library/lib/normalize-options.ts
index 389c2b74cd93b1..76233f3dd833ba 100644
--- a/packages/react/src/generators/library/lib/normalize-options.ts
+++ b/packages/react/src/generators/library/lib/normalize-options.ts
@@ -12,11 +12,15 @@ import {
 } from '@nx/devkit/src/generators/project-name-and-root-utils';
 import { assertValidStyle } from '../../../utils/assertion';
 import { NormalizedSchema, Schema } from '../schema';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { promptWhenInteractive } from '@nx/devkit/src/generators/prompt';
 
 export async function normalizeOptions(
   host: Tree,
   options: Schema
 ): Promise<NormalizedSchema> {
+  const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
+
   await ensureProjectName(host, options, 'library');
   const {
     projectName,
@@ -104,6 +108,8 @@ export async function normalizeOptions(
 
   assertValidStyle(normalized.style);
 
+  normalized.isUsingTsSolutionConfig = isUsingTsSolutionConfig;
+
   return normalized;
 }
 
diff --git a/packages/react/src/generators/library/library.spec.ts b/packages/react/src/generators/library/library.spec.ts
index ae4617f35c4f50..60ad9f8216236b 100644
--- a/packages/react/src/generators/library/library.spec.ts
+++ b/packages/react/src/generators/library/library.spec.ts
@@ -7,6 +7,7 @@ import {
   readProjectConfiguration,
   Tree,
   updateJson,
+  writeJson,
 } from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import { Linter } from '@nx/eslint';
@@ -875,4 +876,190 @@ module.exports = withNx(
       });
     }
   );
+
+  describe('TS solution setup', () => {
+    beforeEach(() => {
+      tree = createTreeWithEmptyWorkspace();
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+    });
+
+    it('should add project references when using TS solution', async () => {
+      await libraryGenerator(tree, {
+        ...defaultSchema,
+        bundler: 'vite',
+        unitTestRunner: 'vitest',
+        directory: 'mylib',
+        name: 'mylib',
+      });
+
+      expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./mylib",
+          },
+        ]
+      `);
+      expect(readJson(tree, 'mylib/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "extends": "../tsconfig.base.json",
+          "files": [],
+          "include": [],
+          "references": [
+            {
+              "path": "./tsconfig.lib.json",
+            },
+            {
+              "path": "./tsconfig.spec.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'mylib/tsconfig.lib.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "out-tsc/mylib",
+            "rootDir": "src",
+            "types": [
+              "node",
+              "@nx/react/typings/cssmodule.d.ts",
+              "@nx/react/typings/image.d.ts",
+              "vite/client",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "**/*.spec.ts",
+            "**/*.test.ts",
+            "**/*.spec.tsx",
+            "**/*.test.tsx",
+            "**/*.spec.js",
+            "**/*.test.js",
+            "**/*.spec.jsx",
+            "**/*.test.jsx",
+            "vite.config.ts",
+            "vite.config.mts",
+            "vitest.config.ts",
+            "vitest.config.mts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.js",
+            "src/**/*.spec.js",
+            "src/**/*.test.jsx",
+            "src/**/*.spec.jsx",
+            "eslint.config.js",
+            "eslint.config.cjs",
+            "eslint.config.mjs",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "src/**/*.js",
+            "src/**/*.jsx",
+            "src/**/*.ts",
+            "src/**/*.tsx",
+          ],
+        }
+      `);
+      expect(readJson(tree, 'mylib/tsconfig.spec.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "./out-tsc/vitest",
+            "types": [
+              "vitest/globals",
+              "vitest/importMeta",
+              "vite/client",
+              "node",
+              "vitest",
+            ],
+          },
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "vite.config.ts",
+            "vite.config.mts",
+            "vitest.config.ts",
+            "vitest.config.mts",
+            "src/**/*.test.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.tsx",
+            "src/**/*.spec.tsx",
+            "src/**/*.test.js",
+            "src/**/*.spec.js",
+            "src/**/*.test.jsx",
+            "src/**/*.spec.jsx",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "./tsconfig.lib.json",
+            },
+          ],
+        }
+      `);
+    });
+
+    it('should map non-buildable libraries to source', async () => {
+      await libraryGenerator(tree, {
+        ...defaultSchema,
+        bundler: 'none',
+        unitTestRunner: 'none',
+        directory: 'mylib',
+        name: 'mylib',
+      });
+
+      await libraryGenerator(tree, {
+        ...defaultSchema,
+        bundler: 'none',
+        unitTestRunner: 'none',
+        directory: 'myjslib',
+        name: 'myjslib',
+        js: true,
+      });
+
+      expect(readJson(tree, 'mylib/package.json')).toMatchInlineSnapshot(`
+        {
+          "main": "./src/index.ts",
+          "name": "@proj/mylib",
+          "nx": {
+            "name": "mylib",
+            "projectType": "library",
+            "sourceRoot": "mylib/src",
+          },
+          "types": "./src/index.ts",
+        }
+      `);
+      expect(readJson(tree, 'myjslib/package.json')).toMatchInlineSnapshot(`
+        {
+          "main": "./src/index.js",
+          "name": "@proj/myjslib",
+          "nx": {
+            "name": "myjslib",
+            "projectType": "library",
+            "sourceRoot": "myjslib/src",
+          },
+          "types": "./src/index.js",
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts
index 337d90cb451b47..7a33143c2cf7ca 100644
--- a/packages/react/src/generators/library/library.ts
+++ b/packages/react/src/generators/library/library.ts
@@ -4,15 +4,16 @@ import {
   ensurePackage,
   formatFiles,
   GeneratorCallback,
+  installPackagesTask,
   joinPathFragments,
   runTasksInSerial,
   Tree,
   updateJson,
+  writeJson,
 } from '@nx/devkit';
 import { getRelativeCwd } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
 import { addTsConfigPath, initGenerator as jsInitGenerator } from '@nx/js';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 import { nxVersion } from '../../utils/versions';
 import { maybeJs } from '../../utils/maybe-js';
@@ -28,6 +29,7 @@ import { createFiles } from './lib/create-files';
 import { extractTsConfigBase } from '../../utils/create-ts-config';
 import { installCommonDependencies } from './lib/install-common-dependencies';
 import { setDefaults } from './lib/set-defaults';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function libraryGenerator(host: Tree, schema: Schema) {
   return await libraryGeneratorInternal(host, {
@@ -37,10 +39,14 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
 }
 
 export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
-  assertNotUsingTsSolutionSetup(host, 'react', 'library');
-
   const tasks: GeneratorCallback[] = [];
 
+  const jsInitTask = await jsInitGenerator(host, {
+    ...schema,
+    skipFormat: true,
+  });
+  tasks.push(jsInitTask);
+
   const options = await normalizeOptions(host, schema);
   if (options.publishable === true && !schema.importPath) {
     throw new Error(
@@ -51,31 +57,45 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
     options.style = 'none';
   }
 
-  const jsInitTask = await jsInitGenerator(host, {
-    ...schema,
-    skipFormat: true,
-  });
-  tasks.push(jsInitTask);
-
   const initTask = await initGenerator(host, {
     ...options,
     skipFormat: true,
   });
   tasks.push(initTask);
 
-  addProjectConfiguration(host, options.name, {
-    root: options.projectRoot,
-    sourceRoot: joinPathFragments(options.projectRoot, 'src'),
-    projectType: 'library',
-    tags: options.parsedTags,
-    targets: {},
-  });
+  if (options.isUsingTsSolutionConfig) {
+    const sourceEntry =
+      options.bundler === 'none'
+        ? options.js
+          ? './src/index.js'
+          : './src/index.ts'
+        : undefined;
+    writeJson(host, `${options.projectRoot}/package.json`, {
+      name: options.importPath,
+      main: sourceEntry,
+      types: sourceEntry,
+      nx: {
+        name: options.importPath === options.name ? undefined : options.name,
+        projectType: 'library',
+        sourceRoot: `${options.projectRoot}/src`,
+        tags: options.parsedTags?.length ? options.parsedTags : undefined,
+      },
+    });
+  } else {
+    addProjectConfiguration(host, options.name, {
+      root: options.projectRoot,
+      sourceRoot: joinPathFragments(options.projectRoot, 'src'),
+      projectType: 'library',
+      tags: options.parsedTags,
+      targets: {},
+    });
+  }
+
+  createFiles(host, options);
 
   const lintTask = await addLinting(host, options);
   tasks.push(lintTask);
 
-  createFiles(host, options);
-
   // Set up build target
   if (options.buildable && options.bundler === 'vite') {
     const { viteConfigurationGenerator, createOrEditViteConfig } =
@@ -228,7 +248,7 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
 
   extractTsConfigBase(host);
 
-  if (!options.skipTsConfig) {
+  if (!options.skipTsConfig && !options.isUsingTsSolutionConfig) {
     addTsConfigPath(host, options.importPath, [
       maybeJs(
         options,
@@ -237,10 +257,29 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
     ]);
   }
 
+  updateTsconfigFiles(
+    host,
+    options.projectRoot,
+    'tsconfig.lib.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
+
   if (!options.skipFormat) {
     await formatFiles(host);
   }
 
+  // Always run install to link packages.
+  if (options.isUsingTsSolutionConfig) {
+    tasks.push(() => installPackagesTask(host));
+  }
+
   tasks.push(() => {
     logShowProjectCommand(options.name);
   });
diff --git a/packages/react/src/generators/library/schema.d.ts b/packages/react/src/generators/library/schema.d.ts
index 8bcd42b369ea0d..0b23eb2f168be9 100644
--- a/packages/react/src/generators/library/schema.d.ts
+++ b/packages/react/src/generators/library/schema.d.ts
@@ -39,4 +39,5 @@ export interface NormalizedSchema extends Schema {
   appMain?: string;
   appSourceRoot?: string;
   unitTestRunner: 'jest' | 'vitest' | 'none';
+  isUsingTsSolutionConfig?: boolean;
 }
diff --git a/packages/react/src/generators/library/schema.json b/packages/react/src/generators/library/schema.json
index cdac0a30d5271f..dc4b31374b5283 100644
--- a/packages/react/src/generators/library/schema.json
+++ b/packages/react/src/generators/library/schema.json
@@ -71,18 +71,29 @@
         ]
       }
     },
+    "bundler": {
+      "type": "string",
+      "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
+      "enum": ["none", "vite", "rollup"],
+      "default": "none",
+      "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
+      "x-priority": "important"
+    },
     "linter": {
       "description": "The tool to use for running lint checks.",
       "type": "string",
       "enum": ["eslint", "none"],
-      "default": "eslint"
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["vitest", "jest", "none"],
-      "default": "vitest",
+      "default": "none",
       "description": "Test runner to use for unit tests.",
-      "x-prompt": "What unit test runner should be used?"
+      "x-prompt": "What unit test runner should be used?",
+      "x-priority": "important"
     },
     "inSourceTests": {
       "type": "boolean",
@@ -154,14 +165,6 @@
       "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
       "default": false
     },
-    "bundler": {
-      "type": "string",
-      "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
-      "enum": ["none", "vite", "rollup"],
-      "default": "none",
-      "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
-      "x-priority": "important"
-    },
     "compiler": {
       "type": "string",
       "enum": ["babel", "swc"],
diff --git a/packages/react/src/generators/remote/remote.ts b/packages/react/src/generators/remote/remote.ts
index 4d6549715c207b..88cde9458e4836 100644
--- a/packages/react/src/generators/remote/remote.ts
+++ b/packages/react/src/generators/remote/remote.ts
@@ -31,7 +31,6 @@ import {
   nxVersion,
 } from '../../utils/versions';
 import { ensureProjectName } from '@nx/devkit/src/generators/project-name-and-root-utils';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function addModuleFederationFiles(
   host: Tree,
@@ -95,8 +94,6 @@ export function addModuleFederationFiles(
 }
 
 export async function remoteGenerator(host: Tree, schema: Schema) {
-  assertNotUsingTsSolutionSetup(host, 'react', 'remote');
-
   const tasks: GeneratorCallback[] = [];
   const options: NormalizedSchema<Schema> = {
     ...(await normalizeOptions<Schema>(host, schema)),
@@ -137,6 +134,7 @@ export async function remoteGenerator(host: Tree, schema: Schema) {
     ...options,
     name: options.projectName,
     skipFormat: true,
+    alwaysGenerateProjectJson: true,
   });
   tasks.push(initAppTask);
 
diff --git a/packages/react/src/rules/update-module-federation-project.ts b/packages/react/src/rules/update-module-federation-project.ts
index 350d047506d03a..3a8455d16aade7 100644
--- a/packages/react/src/rules/update-module-federation-project.ts
+++ b/packages/react/src/rules/update-module-federation-project.ts
@@ -8,6 +8,7 @@ import {
 } from '@nx/devkit';
 import { nxVersion } from '../utils/versions';
 import { maybeJs } from '../utils/maybe-js';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function updateModuleFederationProject(
   host: Tree,
@@ -125,5 +126,11 @@ export function updateModuleFederationProject(
     },
   };
 
+  // Typechecks must be performed first before build and serve to generate remote d.ts files.
+  if (isUsingTsSolutionSetup(host)) {
+    projectConfig.targets.build.dependsOn = ['^build', 'typecheck'];
+    projectConfig.targets.serve.dependsOn = ['typecheck'];
+  }
+
   updateProjectConfiguration(host, options.projectName, projectConfig);
 }
diff --git a/packages/react/src/utils/create-ts-config.ts b/packages/react/src/utils/create-ts-config.ts
index a86d0ca52b53c0..921dccfbbbb013 100644
--- a/packages/react/src/utils/create-ts-config.ts
+++ b/packages/react/src/utils/create-ts-config.ts
@@ -1,6 +1,7 @@
 import { Tree } from 'nx/src/generators/tree';
 import * as shared from '@nx/js/src/utils/typescript/create-ts-config';
 import { updateJson, writeJson } from 'nx/src/generators/utils/json';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function createTsConfig(
   host: Tree,
@@ -14,6 +15,110 @@ export function createTsConfig(
     unitTestRunner?: string;
   },
   relativePathToRootTsConfig: string
+) {
+  if (isUsingTsSolutionSetup(host)) {
+    createTsConfigForTsSolution(
+      host,
+      projectRoot,
+      type,
+      options,
+      relativePathToRootTsConfig
+    );
+  } else {
+    createTsConfigForNonTsSolution(
+      host,
+      projectRoot,
+      type,
+      options,
+      relativePathToRootTsConfig
+    );
+  }
+}
+
+export function extractTsConfigBase(host: Tree) {
+  shared.extractTsConfigBase(host);
+
+  if (host.exists('vite.config.ts')) {
+    const vite = host.read('vite.config.ts').toString();
+    host.write(
+      'vite.config.ts',
+      vite.replace(`projects: []`, `projects: ['tsconfig.base.json']`)
+    );
+  }
+}
+
+function createTsConfigForTsSolution(
+  host: Tree,
+  projectRoot: string,
+  type: 'app' | 'lib',
+  options: {
+    strict?: boolean;
+    style?: string;
+    bundler?: string;
+    rootProject?: boolean;
+    unitTestRunner?: string;
+  },
+  relativePathToRootTsConfig: string
+) {
+  const json = {
+    files: [],
+    include: [],
+    references: [
+      {
+        path: type === 'app' ? './tsconfig.app.json' : './tsconfig.lib.json',
+      },
+    ],
+  } as any;
+
+  // inline tsconfig.base.json into the project
+  if (options.rootProject) {
+    json.compileOnSave = false;
+    json.compilerOptions = {
+      ...shared.tsConfigBaseOptions,
+      ...json.compilerOptions,
+    };
+    json.exclude = ['node_modules', 'tmp'];
+  } else {
+    json.extends = relativePathToRootTsConfig;
+  }
+
+  writeJson(host, `${projectRoot}/tsconfig.json`, json);
+
+  const tsconfigProjectPath = `${projectRoot}/tsconfig.${type}.json`;
+  if (host.exists(tsconfigProjectPath)) {
+    updateJson(host, tsconfigProjectPath, (json) => {
+      if (options.bundler === 'vite') {
+        json.compilerOptions ??= {};
+
+        const types = new Set(json.compilerOptions.types ?? []);
+        types.add('node');
+        types.add('vite/client');
+
+        json.compilerOptions.types = Array.from(types);
+      }
+
+      if (options.style === '@emotion/styled') {
+        json.compilerOptions ??= {};
+        json.compilerOptions.jsxImportSource = '@emotion/react';
+      }
+
+      return json;
+    });
+  }
+}
+
+function createTsConfigForNonTsSolution(
+  host: Tree,
+  projectRoot: string,
+  type: 'app' | 'lib',
+  options: {
+    strict?: boolean;
+    style?: string;
+    bundler?: string;
+    rootProject?: boolean;
+    unitTestRunner?: string;
+  },
+  relativePathToRootTsConfig: string
 ) {
   const json = {
     compilerOptions: {
@@ -72,15 +177,3 @@ export function createTsConfig(
     });
   }
 }
-
-export function extractTsConfigBase(host: Tree) {
-  shared.extractTsConfigBase(host);
-
-  if (host.exists('vite.config.ts')) {
-    const vite = host.read('vite.config.ts').toString();
-    host.write(
-      'vite.config.ts',
-      vite.replace(`projects: []`, `projects: ['tsconfig.base.json']`)
-    );
-  }
-}
diff --git a/packages/react/src/utils/versions.ts b/packages/react/src/utils/versions.ts
index 1e387e083a5692..782a8b62d69d44 100755
--- a/packages/react/src/utils/versions.ts
+++ b/packages/react/src/utils/versions.ts
@@ -1,8 +1,5 @@
 export const nxVersion = require('../../package.json').version;
 
-// Always pull the latest version until we merge rspack plugin into the repo.
-export const nxRspackVersion = '*';
-
 export const reactVersion = '18.3.1';
 export const reactDomVersion = '18.3.1';
 export const reactIsVersion = '18.3.1';
diff --git a/packages/remix/src/generators/application/application.impl.spec.ts b/packages/remix/src/generators/application/application.impl.spec.ts
index 7a41eefd1b4695..47feaf0a0b48af 100644
--- a/packages/remix/src/generators/application/application.impl.spec.ts
+++ b/packages/remix/src/generators/application/application.impl.spec.ts
@@ -1,6 +1,13 @@
 import 'nx/src/internal-testing-utils/mock-project-graph';
 
-import { joinPathFragments, readJson, readNxJson, type Tree } from '@nx/devkit';
+import {
+  joinPathFragments,
+  readJson,
+  readNxJson,
+  type Tree,
+  updateJson,
+  writeJson,
+} from '@nx/devkit';
 
 import * as devkitExports from 'nx/src/devkit-exports';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
@@ -307,6 +314,216 @@ describe('Remix Application', () => {
       });
     });
   });
+
+  describe('TS solution setup', () => {
+    it('should add project references when using TS solution', async () => {
+      const tree = createTreeWithEmptyWorkspace();
+      updateJson(tree, 'package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+
+      await applicationGenerator(tree, {
+        directory: 'myapp',
+        e2eTestRunner: 'playwright',
+        unitTestRunner: 'jest',
+        addPlugin: true,
+        tags: 'foo',
+      });
+
+      expect(readJson(tree, 'myapp/package.json')).toMatchInlineSnapshot(`
+        {
+          "dependencies": {
+            "@remix-run/node": "^2.14.0",
+            "@remix-run/react": "^2.14.0",
+            "@remix-run/serve": "^2.14.0",
+            "isbot": "^4.4.0",
+            "react": "^18.2.0",
+            "react-dom": "^18.2.0",
+          },
+          "devDependencies": {
+            "@remix-run/dev": "^2.14.0",
+            "@types/react": "^18.2.0",
+            "@types/react-dom": "^18.2.0",
+          },
+          "engines": {
+            "node": ">=20",
+          },
+          "name": "myapp",
+          "nx": {
+            "projectType": "application",
+            "sourceRoot": "myapp",
+            "tags": [
+              "foo",
+            ],
+          },
+          "private": true,
+          "scripts": {},
+          "sideEffects": false,
+          "type": "module",
+        }
+      `);
+
+      expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
+        [
+          {
+            "path": "./myapp-e2e",
+          },
+          {
+            "path": "./myapp",
+          },
+        ]
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "extends": "../tsconfig.base.json",
+          "files": [],
+          "include": [],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+            {
+              "path": "./tsconfig.spec.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.app.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowJs": true,
+            "esModuleInterop": true,
+            "forceConsistentCasingInFileNames": true,
+            "isolatedModules": true,
+            "jsx": "react-jsx",
+            "lib": [
+              "DOM",
+              "DOM.Iterable",
+              "ES2019",
+            ],
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "out-tsc/myapp",
+            "resolveJsonModule": true,
+            "rootDir": ".",
+            "skipLibCheck": true,
+            "strict": true,
+            "target": "ES2022",
+            "types": [
+              "@remix-run/node",
+              "vite/client",
+            ],
+          },
+          "exclude": [
+            "dist",
+            "tests/**/*.spec.ts",
+            "tests/**/*.test.ts",
+            "tests/**/*.spec.tsx",
+            "tests/**/*.test.tsx",
+            "tests/**/*.spec.js",
+            "tests/**/*.test.js",
+            "tests/**/*.spec.jsx",
+            "tests/**/*.test.jsx",
+            "jest.config.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.test.ts",
+            "eslint.config.js",
+            "eslint.config.cjs",
+            "eslint.config.mjs",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "app/**/*.ts",
+            "app/**/*.tsx",
+            "app/**/*.js",
+            "app/**/*.jsx",
+            "**/.server/**/*.ts",
+            "**/.server/**/*.tsx",
+            "**/.client/**/*.ts",
+            "**/.client/**/*.tsx",
+          ],
+        }
+      `);
+      expect(readJson(tree, 'myapp/tsconfig.spec.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "jsx": "react-jsx",
+            "module": "esnext",
+            "moduleResolution": "bundler",
+            "outDir": "./out-tsc/jest",
+            "types": [
+              "jest",
+              "node",
+            ],
+          },
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "vite.config.ts",
+            "vitest.config.ts",
+            "app/**/*.ts",
+            "app/**/*.tsx",
+            "app/**/*.js",
+            "app/**/*.jsx",
+            "tests/**/*.spec.ts",
+            "tests/**/*.test.ts",
+            "tests/**/*.spec.tsx",
+            "tests/**/*.test.tsx",
+            "tests/**/*.spec.js",
+            "tests/**/*.test.js",
+            "tests/**/*.spec.jsx",
+            "tests/**/*.test.jsx",
+          ],
+          "references": [
+            {
+              "path": "./tsconfig.app.json",
+            },
+          ],
+        }
+      `);
+      expect(readJson(tree, 'myapp-e2e/tsconfig.json')).toMatchInlineSnapshot(`
+        {
+          "compilerOptions": {
+            "allowJs": true,
+            "outDir": "dist",
+            "sourceMap": false,
+            "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
+          },
+          "exclude": [
+            "dist",
+            "eslint.config.js",
+          ],
+          "extends": "../tsconfig.base.json",
+          "include": [
+            "**/*.ts",
+            "**/*.js",
+            "playwright.config.ts",
+            "src/**/*.spec.ts",
+            "src/**/*.spec.js",
+            "src/**/*.test.ts",
+            "src/**/*.test.js",
+            "src/**/*.d.ts",
+          ],
+          "references": [
+            {
+              "path": "../myapp",
+            },
+          ],
+        }
+      `);
+    });
+  });
 });
 
 function expectTargetsToBeCorrect(tree: Tree, projectRoot: string) {
diff --git a/packages/remix/src/generators/application/application.impl.ts b/packages/remix/src/generators/application/application.impl.ts
index c56633bf635560..e66b13fd2885db 100644
--- a/packages/remix/src/generators/application/application.impl.ts
+++ b/packages/remix/src/generators/application/application.impl.ts
@@ -17,7 +17,6 @@ import {
 import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
 import { initGenerator as jsInitGenerator } from '@nx/js';
 import { extractTsConfigBase } from '@nx/js/src/utils/typescript/create-ts-config';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { dirname } from 'node:path';
 import {
   createNxCloudOnboardingURLForWelcomeApp,
@@ -45,6 +44,10 @@ import {
   addViteTempFilesToGitIgnore,
 } from './lib';
 import { NxRemixGeneratorSchema } from './schema';
+import {
+  isUsingTsSolutionSetup,
+  updateTsconfigFiles,
+} from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function remixApplicationGenerator(
   tree: Tree,
@@ -60,7 +63,17 @@ export async function remixApplicationGeneratorInternal(
   tree: Tree,
   _options: NxRemixGeneratorSchema
 ) {
-  assertNotUsingTsSolutionSetup(tree, 'remix', 'application');
+  const tasks: GeneratorCallback[] = [
+    await initGenerator(tree, {
+      skipFormat: true,
+      addPlugin: true,
+    }),
+    await jsInitGenerator(tree, {
+      skipFormat: true,
+      addTsPlugin: _options.useTsSolution,
+      formatter: _options.formatter,
+    }),
+  ];
 
   const options = await normalizeOptions(tree, _options);
   if (!options.addPlugin) {
@@ -69,21 +82,17 @@ export async function remixApplicationGeneratorInternal(
     );
   }
 
-  const tasks: GeneratorCallback[] = [
-    await initGenerator(tree, {
-      skipFormat: true,
-      addPlugin: true,
-    }),
-    await jsInitGenerator(tree, { skipFormat: true }),
-  ];
+  const isUsingTsSolution = isUsingTsSolutionSetup(tree);
 
-  addProjectConfiguration(tree, options.projectName, {
-    root: options.projectRoot,
-    sourceRoot: `${options.projectRoot}`,
-    projectType: 'application',
-    tags: options.parsedTags,
-    targets: {},
-  });
+  if (!isUsingTsSolution) {
+    addProjectConfiguration(tree, options.projectName, {
+      root: options.projectRoot,
+      sourceRoot: `${options.projectRoot}`,
+      projectType: 'application',
+      tags: options.parsedTags,
+      targets: {},
+    });
+  }
 
   const installTask = updateDependencies(tree);
   tasks.push(installTask);
@@ -110,6 +119,7 @@ export async function remixApplicationGeneratorInternal(
     eslintVersion,
     typescriptVersion,
     viteVersion,
+    isUsingTsSolution,
   };
 
   generateFiles(
@@ -135,7 +145,16 @@ export async function remixApplicationGeneratorInternal(
   } else {
     generateFiles(
       tree,
-      joinPathFragments(__dirname, 'files/integrated'),
+      joinPathFragments(__dirname, 'files/non-root'),
+      options.projectRoot,
+      vars
+    );
+  }
+
+  if (isUsingTsSolution) {
+    generateFiles(
+      tree,
+      joinPathFragments(__dirname, 'files/ts-solution'),
       options.projectRoot,
       vars
     );
@@ -187,7 +206,7 @@ export async function remixApplicationGeneratorInternal(
         addPlugin: true,
       });
       const projectConfig = readProjectConfiguration(tree, options.projectName);
-      if (projectConfig.targets['test']?.options) {
+      if (projectConfig.targets?.['test']?.options) {
         projectConfig.targets['test'].options.passWithNoTests = true;
         updateProjectConfiguration(tree, options.projectName, projectConfig);
       }
@@ -340,6 +359,21 @@ export default {...nxPreset};
     await formatFiles(tree);
   }
 
+  updateTsconfigFiles(
+    tree,
+    options.projectRoot,
+    'tsconfig.app.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined,
+    '.'
+  );
+
   tasks.push(() => {
     logShowProjectCommand(options.projectName);
   });
diff --git a/packages/remix/src/generators/application/files/integrated/.gitignore__tmpl__ b/packages/remix/src/generators/application/files/non-root/.gitignore__tmpl__
similarity index 100%
rename from packages/remix/src/generators/application/files/integrated/.gitignore__tmpl__
rename to packages/remix/src/generators/application/files/non-root/.gitignore__tmpl__
diff --git a/packages/remix/src/generators/application/files/integrated/package.json__tmpl__ b/packages/remix/src/generators/application/files/non-root/package.json__tmpl__
similarity index 100%
rename from packages/remix/src/generators/application/files/integrated/package.json__tmpl__
rename to packages/remix/src/generators/application/files/non-root/package.json__tmpl__
diff --git a/packages/remix/src/generators/application/files/ts-solution/package.json__tmpl__ b/packages/remix/src/generators/application/files/ts-solution/package.json__tmpl__
new file mode 100644
index 00000000000000..06b3362f5c0fb4
--- /dev/null
+++ b/packages/remix/src/generators/application/files/ts-solution/package.json__tmpl__
@@ -0,0 +1,32 @@
+{
+  "private": true,
+  "name": "<%= projectName %>",
+  "scripts": {},
+  "type": "module",
+  "dependencies": {
+    "@remix-run/node": "<%= remixVersion %>",
+    "@remix-run/react": "<%= remixVersion %>",
+    "@remix-run/serve": "<%= remixVersion %>",
+    "isbot": "<%= isbotVersion %>",
+    "react": "<%= reactVersion %>",
+    "react-dom": "<%= reactDomVersion %>"
+  },
+  "devDependencies": {
+    "@remix-run/dev": "<%= remixVersion %>",
+    "@types/react": "<%= typesReactVersion %>",
+    "@types/react-dom": "<%= typesReactDomVersion %>"
+  },
+  "engines": {
+    "node": ">=20"
+  },
+  "sideEffects": false<% if (isUsingTsSolution) { %>,
+  "nx": {
+  <%_ if (name !== projectName) { _%>
+    "name": "<%= name %>",<%_ } _%>
+    "projectType": "application",
+    "sourceRoot": "<%- projectRoot %>",
+    <%_ if (parsedTags?.length) { _%>
+    "tags": <%- JSON.stringify(parsedTags) %>
+    <%_ } _%>
+  }<% } %>
+}
diff --git a/packages/remix/src/generators/application/files/ts-solution/tsconfig.app.json__tmpl__ b/packages/remix/src/generators/application/files/ts-solution/tsconfig.app.json__tmpl__
new file mode 100644
index 00000000000000..7c24e92dadf983
--- /dev/null
+++ b/packages/remix/src/generators/application/files/ts-solution/tsconfig.app.json__tmpl__
@@ -0,0 +1,39 @@
+{
+  "extends": "<%= offsetFromRoot %>tsconfig.base.json",
+  "compilerOptions": {
+    "outDir": "dist",
+    "lib": ["DOM", "DOM.Iterable", "ES2019"],
+    "types": ["@remix-run/node", "vite/client"],
+    "isolatedModules": true,
+    "esModuleInterop": true,
+    "jsx": "react-jsx",
+    "module": "ESNext",
+    "moduleResolution": "Bundler",
+    "resolveJsonModule": true,
+    "target": "ES2022",
+    "strict": true,
+    "allowJs": true,
+    "skipLibCheck": true,
+    "forceConsistentCasingInFileNames": true
+  },
+  "include": [
+    "app/**/*.ts",
+    "app/**/*.tsx",
+    "app/**/*.js",
+    "app/**/*.jsx",
+    "**/.server/**/*.ts",
+    "**/.server/**/*.tsx",
+    "**/.client/**/*.ts",
+    "**/.client/**/*.tsx"
+  ],
+  "exclude": [
+    "tests/**/*.spec.ts",
+    "tests/**/*.test.ts",
+    "tests/**/*.spec.tsx",
+    "tests/**/*.test.tsx",
+    "tests/**/*.spec.js",
+    "tests/**/*.test.js",
+    "tests/**/*.spec.jsx",
+    "tests/**/*.test.jsx"
+  ]
+}
diff --git a/packages/remix/src/generators/application/files/ts-solution/tsconfig.json__tmpl__ b/packages/remix/src/generators/application/files/ts-solution/tsconfig.json__tmpl__
new file mode 100644
index 00000000000000..de288cd7a6d9d1
--- /dev/null
+++ b/packages/remix/src/generators/application/files/ts-solution/tsconfig.json__tmpl__
@@ -0,0 +1,10 @@
+{
+  "extends": "<%= offsetFromRoot %>tsconfig.base.json",
+    "include": [],
+    "files": [],
+    "references": [
+      {
+        "path": "./tsconfig.app.json"
+      }
+    ]
+}
diff --git a/packages/remix/src/generators/application/lib/add-e2e.ts b/packages/remix/src/generators/application/lib/add-e2e.ts
index f496b1fd940a75..ee46632d59ccb3 100644
--- a/packages/remix/src/generators/application/lib/add-e2e.ts
+++ b/packages/remix/src/generators/application/lib/add-e2e.ts
@@ -4,12 +4,14 @@ import {
   joinPathFragments,
   ensurePackage,
   readNxJson,
+  writeJson,
 } from '@nx/devkit';
 import { type NormalizedSchema } from './normalize-options';
 import { getPackageVersion } from '../../../utils/versions';
 import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
 import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
 import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function addE2E(tree: Tree, options: NormalizedSchema) {
   const hasRemixPlugin = readNxJson(tree).plugins?.find((p) =>
@@ -30,14 +32,31 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) {
       typeof import('@nx/cypress')
     >('@nx/cypress', getPackageVersion(tree, 'nx'));
 
-    addProjectConfiguration(tree, options.e2eProjectName, {
-      projectType: 'application',
-      root: options.e2eProjectRoot,
-      sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-      targets: {},
-      tags: [],
-      implicitDependencies: [options.projectName],
-    });
+    if (isUsingTsSolutionSetup(tree)) {
+      writeJson(
+        tree,
+        joinPathFragments(options.e2eProjectRoot, 'package.json'),
+        {
+          name: options.e2eProjectName,
+          version: '0.0.1',
+          private: true,
+          nx: {
+            projectType: 'application',
+            sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+            implicitDependencies: [options.projectName],
+          },
+        }
+      );
+    } else {
+      addProjectConfiguration(tree, options.e2eProjectName, {
+        projectType: 'application',
+        root: options.e2eProjectRoot,
+        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+        targets: {},
+        tags: [],
+        implicitDependencies: [options.projectName],
+      });
+    }
 
     const e2eTask = await configurationGenerator(tree, {
       project: options.e2eProjectName,
@@ -93,14 +112,31 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) {
       typeof import('@nx/playwright')
     >('@nx/playwright', getPackageVersion(tree, 'nx'));
 
-    addProjectConfiguration(tree, options.e2eProjectName, {
-      projectType: 'application',
-      root: options.e2eProjectRoot,
-      sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
-      targets: {},
-      tags: [],
-      implicitDependencies: [options.projectName],
-    });
+    if (isUsingTsSolutionSetup(tree)) {
+      writeJson(
+        tree,
+        joinPathFragments(options.e2eProjectRoot, 'package.json'),
+        {
+          name: options.e2eProjectName,
+          version: '0.0.1',
+          private: true,
+          nx: {
+            projectType: 'application',
+            sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+            implicitDependencies: [options.projectName],
+          },
+        }
+      );
+    } else {
+      addProjectConfiguration(tree, options.e2eProjectName, {
+        projectType: 'application',
+        root: options.e2eProjectRoot,
+        sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
+        targets: {},
+        tags: [],
+        implicitDependencies: [options.projectName],
+      });
+    }
 
     const e2eTask = await configurationGenerator(tree, {
       project: options.e2eProjectName,
diff --git a/packages/remix/src/generators/application/schema.d.ts b/packages/remix/src/generators/application/schema.d.ts
index ddecf258963eb2..580a3fc855437e 100644
--- a/packages/remix/src/generators/application/schema.d.ts
+++ b/packages/remix/src/generators/application/schema.d.ts
@@ -8,7 +8,10 @@ export interface NxRemixGeneratorSchema {
   unitTestRunner?: 'vitest' | 'jest' | 'none';
   e2eTestRunner?: 'cypress' | 'playwright' | 'none';
   skipFormat?: boolean;
+  // Internal options
   rootProject?: boolean;
   addPlugin?: boolean;
   nxCloudToken?: string;
+  useTsSolution?: boolean;
+  formatter?: 'prettier' | 'none';
 }
diff --git a/packages/remix/src/generators/application/schema.json b/packages/remix/src/generators/application/schema.json
index 0a133441750caa..5b4ee76eee1cce 100644
--- a/packages/remix/src/generators/application/schema.json
+++ b/packages/remix/src/generators/application/schema.json
@@ -24,19 +24,22 @@
       "description": "The tool to use for running lint checks.",
       "type": "string",
       "enum": ["eslint", "none"],
-      "default": "eslint"
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["vitest", "jest", "none"],
-      "default": "vitest",
+      "default": "none",
       "description": "Test runner to use for unit tests.",
-      "x-prompt": "What unit test runner should be used?"
+      "x-prompt": "What unit test runner should be used?",
+      "x-priority": "important"
     },
     "e2eTestRunner": {
       "type": "string",
       "enum": ["playwright", "cypress", "none"],
-      "default": "playwright",
+      "default": "none",
       "description": "Test runner to use for e2e tests",
       "x-prompt": "Which E2E test runner would you like to use?"
     },
diff --git a/packages/remix/src/generators/init/init.ts b/packages/remix/src/generators/init/init.ts
index 470d6e9d879f84..c8695771c57414 100644
--- a/packages/remix/src/generators/init/init.ts
+++ b/packages/remix/src/generators/init/init.ts
@@ -1,17 +1,13 @@
 import {
-  type Tree,
+  addDependenciesToPackageJson,
+  createProjectGraphAsync,
   formatFiles,
   GeneratorCallback,
   readNxJson,
-  addDependenciesToPackageJson,
   runTasksInSerial,
-  createProjectGraphAsync,
+  type Tree,
 } from '@nx/devkit';
-import {
-  addPlugin,
-  generateCombinations,
-} from '@nx/devkit/src/utils/add-plugin';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
 import { createNodesV2 } from '../../plugins/plugin';
 import { nxVersion, remixVersion } from '../../utils/versions';
 import { type Schema } from './schema';
@@ -21,8 +17,6 @@ export function remixInitGenerator(tree: Tree, options: Schema) {
 }
 
 export async function remixInitGeneratorInternal(tree: Tree, options: Schema) {
-  assertNotUsingTsSolutionSetup(tree, 'remix', 'init');
-
   const tasks: GeneratorCallback[] = [];
 
   if (!options.skipPackageJson) {
diff --git a/packages/remix/src/generators/library/library.impl.ts b/packages/remix/src/generators/library/library.impl.ts
index d08496214c424e..1f0553763b160e 100644
--- a/packages/remix/src/generators/library/library.impl.ts
+++ b/packages/remix/src/generators/library/library.impl.ts
@@ -1,7 +1,6 @@
 import type { Tree } from '@nx/devkit';
 import { formatFiles, GeneratorCallback, runTasksInSerial } from '@nx/devkit';
-import { Linter } from '@nx/eslint';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
+import { initGenerator as jsInitGenerator } from '@nx/js';
 import { libraryGenerator } from '@nx/react';
 import {
   addTsconfigEntryPoints,
@@ -10,6 +9,7 @@ import {
   updateBuildableConfig,
 } from './lib';
 import type { NxRemixGeneratorSchema } from './schema';
+import { updateTsconfigFiles } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export async function remixLibraryGenerator(
   tree: Tree,
@@ -22,11 +22,15 @@ export async function remixLibraryGeneratorInternal(
   tree: Tree,
   schema: NxRemixGeneratorSchema
 ) {
-  assertNotUsingTsSolutionSetup(tree, 'remix', 'library');
-
   const tasks: GeneratorCallback[] = [];
   const options = await normalizeOptions(tree, schema);
 
+  const jsInitTask = await jsInitGenerator(tree, {
+    js: options.js,
+    skipFormat: true,
+  });
+  tasks.push(jsInitTask);
+
   const libGenTask = await libraryGenerator(tree, {
     name: options.projectName,
     style: options.style,
@@ -36,9 +40,10 @@ export async function remixLibraryGeneratorInternal(
     directory: options.projectRoot,
     skipFormat: true,
     skipTsConfig: false,
-    linter: Linter.EsLint,
+    linter: options.linter,
     component: true,
     buildable: options.buildable,
+    bundler: options.bundler,
     addPlugin: options.addPlugin,
   });
   tasks.push(libGenTask);
@@ -50,10 +55,24 @@ export async function remixLibraryGeneratorInternal(
 
   addTsconfigEntryPoints(tree, options);
 
-  if (options.buildable) {
+  if (options.bundler === 'rollup' || options.buildable) {
     updateBuildableConfig(tree, options.projectName);
   }
 
+  updateTsconfigFiles(
+    tree,
+    options.projectRoot,
+    'tsconfig.lib.json',
+    {
+      jsx: 'react-jsx',
+      module: 'esnext',
+      moduleResolution: 'bundler',
+    },
+    options.linter === 'eslint'
+      ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
+      : undefined
+  );
+
   if (!options.skipFormat) {
     await formatFiles(tree);
   }
diff --git a/packages/remix/src/generators/library/schema.d.ts b/packages/remix/src/generators/library/schema.d.ts
index 41283df98c4629..a0c546e8fdc288 100644
--- a/packages/remix/src/generators/library/schema.d.ts
+++ b/packages/remix/src/generators/library/schema.d.ts
@@ -6,7 +6,10 @@ export interface NxRemixGeneratorSchema {
   style: SupportedStyles;
   tags?: string;
   importPath?: string;
+  /** @deprecated Use bundler instead. */
   buildable?: boolean;
+  bundler?: 'none' | 'vite' | 'rollup';
+  linter?: 'none' | 'eslint';
   unitTestRunner?: 'jest' | 'vitest' | 'none';
   js?: boolean;
   skipFormat?: boolean;
diff --git a/packages/remix/src/generators/library/schema.json b/packages/remix/src/generators/library/schema.json
index e2e9bae514ee0e..d5c71fcad402bb 100644
--- a/packages/remix/src/generators/library/schema.json
+++ b/packages/remix/src/generators/library/schema.json
@@ -37,17 +37,29 @@
       "enum": ["none", "css"],
       "default": "css"
     },
-    "buildable": {
-      "type": "boolean",
-      "description": "Should the library be buildable?",
-      "default": false
+    "bundler": {
+      "type": "string",
+      "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
+      "enum": ["none", "vite", "rollup"],
+      "default": "none",
+      "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
+      "x-priority": "important"
+    },
+    "linter": {
+      "description": "The tool to use for running lint checks.",
+      "type": "string",
+      "enum": ["eslint", "none"],
+      "default": "none",
+      "x-prompt": "Which linter would you like to use?",
+      "x-priority": "important"
     },
     "unitTestRunner": {
       "type": "string",
       "enum": ["vitest", "jest", "none"],
       "description": "Test Runner to use for Unit Tests",
       "x-prompt": "What test runner should be used?",
-      "default": "vitest"
+      "default": "none",
+      "x-priority": "important"
     },
     "importPath": {
       "type": "string",
@@ -63,6 +75,12 @@
       "description": "Skip formatting files after generator runs",
       "default": false,
       "x-priority": "internal"
+    },
+    "buildable": {
+      "type": "boolean",
+      "default": false,
+      "description": "Generate a buildable library that uses rollup to bundle.",
+      "x-deprecated": "Use the `bundler` option for greater control (none, vite, rollup)."
     }
   },
   "required": ["directory"]
diff --git a/packages/rspack/src/executors/rspack/schema.json b/packages/rspack/src/executors/rspack/schema.json
index 8a2ccb1ab5b53b..0594e0dafef4a0 100644
--- a/packages/rspack/src/executors/rspack/schema.json
+++ b/packages/rspack/src/executors/rspack/schema.json
@@ -97,7 +97,7 @@
     "extractLicenses": {
       "type": "boolean",
       "description": "Extract all licenses in a separate file.",
-      "default": true
+      "default": false
     },
     "fileReplacements": {
       "description": "Replace files with other files in the build.",
diff --git a/packages/rspack/src/generators/application/application.ts b/packages/rspack/src/generators/application/application.ts
index 60d01c7b85f149..77ae88c8680b60 100644
--- a/packages/rspack/src/generators/application/application.ts
+++ b/packages/rspack/src/generators/application/application.ts
@@ -1,5 +1,4 @@
 import { ensurePackage, formatFiles, runTasksInSerial, Tree } from '@nx/devkit';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { version as nxVersion } from 'nx/package.json';
 import configurationGenerator from '../configuration/configuration';
 import rspackInitGenerator from '../init/init';
@@ -10,8 +9,6 @@ export default async function (
   tree: Tree,
   _options: ApplicationGeneratorSchema
 ) {
-  assertNotUsingTsSolutionSetup(tree, 'rspack', 'application');
-
   const tasks = [];
   const initTask = await rspackInitGenerator(tree, {
     ..._options,
diff --git a/packages/rspack/src/generators/configuration/configuration.ts b/packages/rspack/src/generators/configuration/configuration.ts
index 53be9571c22724..4a977e450f3201 100644
--- a/packages/rspack/src/generators/configuration/configuration.ts
+++ b/packages/rspack/src/generators/configuration/configuration.ts
@@ -5,7 +5,6 @@ import {
   readProjectConfiguration,
   Tree,
 } from '@nx/devkit';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import {
   addOrChangeBuildTarget,
   addOrChangeServeTarget,
@@ -26,8 +25,6 @@ export async function configurationGenerator(
   tree: Tree,
   options: ConfigurationSchema
 ) {
-  assertNotUsingTsSolutionSetup(tree, 'rspack', 'configuration');
-
   const task = await rspackInitGenerator(tree, {
     ...options,
     // TODO: Crystalize the default rspack.config.js file.
diff --git a/packages/rspack/src/generators/init/init.ts b/packages/rspack/src/generators/init/init.ts
index 6e43253f46ef04..f32af80d9c6968 100644
--- a/packages/rspack/src/generators/init/init.ts
+++ b/packages/rspack/src/generators/init/init.ts
@@ -9,7 +9,6 @@ import {
 } from '@nx/devkit';
 import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
 import { initGenerator } from '@nx/js';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { createNodesV2 } from '../../../plugin';
 import {
   lessLoaderVersion,
@@ -25,8 +24,6 @@ export async function rspackInitGenerator(
   tree: Tree,
   schema: InitGeneratorSchema
 ) {
-  assertNotUsingTsSolutionSetup(tree, 'rspack', 'init');
-
   const tasks: GeneratorCallback[] = [];
 
   const nxJson = readNxJson(tree);
diff --git a/packages/vite/src/generators/configuration/configuration.spec.ts b/packages/vite/src/generators/configuration/configuration.spec.ts
index 7b3da15c89312b..8fce12d571e471 100644
--- a/packages/vite/src/generators/configuration/configuration.spec.ts
+++ b/packages/vite/src/generators/configuration/configuration.spec.ts
@@ -1,6 +1,13 @@
 import 'nx/src/internal-testing-utils/mock-project-graph';
 
-import { addDependenciesToPackageJson, readJson, Tree } from '@nx/devkit';
+import {
+  addDependenciesToPackageJson,
+  addProjectConfiguration,
+  readJson,
+  Tree,
+  updateJson,
+  writeJson,
+} from '@nx/devkit';
 import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
 import { nxVersion } from '../../utils/versions';
 
@@ -35,6 +42,7 @@ describe('@nx/vite:configuration', () => {
         addPlugin: true,
         uiFramework: 'react',
         project: 'my-test-react-app',
+        projectType: 'application',
       });
     });
 
@@ -321,4 +329,84 @@ describe('@nx/vite:configuration', () => {
       }
     );
   });
+
+  describe('TS solution setup', () => {
+    beforeAll(async () => {
+      tree = createTreeWithEmptyWorkspace();
+      updateJson(tree, '/package.json', (json) => {
+        json.workspaces = ['packages/*', 'apps/*'];
+        return json;
+      });
+      writeJson(tree, 'tsconfig.base.json', {
+        compilerOptions: {
+          composite: true,
+          declaration: true,
+        },
+      });
+      writeJson(tree, 'tsconfig.json', {
+        extends: './tsconfig.base.json',
+        files: [],
+        references: [],
+      });
+    });
+
+    it('should create package.json with exports field for libraries', async () => {
+      addProjectConfiguration(tree, 'my-lib', {
+        root: 'packages/my-lib',
+      });
+      writeJson(tree, 'packages/my-lib/tsconfig.lib.json', {});
+      writeJson(tree, 'packages/my-lib/tsconfig.json', {});
+
+      await viteConfigurationGenerator(tree, {
+        addPlugin: true,
+        uiFramework: 'none',
+        project: 'my-lib',
+        projectType: 'library',
+        newProject: true,
+      });
+
+      expect(readJson(tree, 'packages/my-lib/package.json'))
+        .toMatchInlineSnapshot(`
+        {
+          "exports": {
+            ".": {
+              "default": "./dist/index.js",
+              "import": "./dist/index.mjs",
+              "types": "./dist/index.d.ts",
+            },
+            "./package.json": "./package.json",
+          },
+          "main": "./dist/index.js",
+          "module": "./dist/index.mjs",
+          "name": "@proj/my-lib",
+          "types": "./dist/index.d.ts",
+          "version": "0.0.1",
+        }
+      `);
+    });
+
+    it('should create package.json without exports field for apps', async () => {
+      addProjectConfiguration(tree, 'my-app', {
+        root: 'apps/my-app',
+      });
+      writeJson(tree, 'apps/my-app/tsconfig.app.json', {});
+      writeJson(tree, 'apps/my-app/tsconfig.json', {});
+
+      await viteConfigurationGenerator(tree, {
+        addPlugin: true,
+        uiFramework: 'none',
+        project: 'my-app',
+        projectType: 'application',
+        newProject: true,
+      });
+
+      expect(readJson(tree, 'apps/my-app/package.json')).toMatchInlineSnapshot(`
+        {
+          "name": "@proj/my-app",
+          "private": true,
+          "version": "0.0.1",
+        }
+      `);
+    });
+  });
 });
diff --git a/packages/vite/src/generators/configuration/configuration.ts b/packages/vite/src/generators/configuration/configuration.ts
index 57e8c502577eee..427a5303e873b6 100644
--- a/packages/vite/src/generators/configuration/configuration.ts
+++ b/packages/vite/src/generators/configuration/configuration.ts
@@ -50,7 +50,8 @@ export async function viteConfigurationGeneratorInternal(
   const projectConfig = readProjectConfiguration(tree, schema.project);
   const { targets, root: projectRoot } = projectConfig;
 
-  const projectType = projectConfig.projectType ?? 'library';
+  const projectType =
+    schema.projectType ?? projectConfig.projectType ?? 'library';
 
   schema.includeLib ??= projectType === 'library';
 
@@ -161,12 +162,13 @@ export async function viteConfigurationGeneratorInternal(
       skipFormat: true,
       addPlugin: schema.addPlugin,
       compiler: schema.compiler,
+      projectType,
     });
     tasks.push(vitestTask);
   }
 
   if (isUsingTsSolutionSetup(tree)) {
-    updatePackageJson(tree, schema);
+    updatePackageJson(tree, schema, projectType);
   }
 
   if (!schema.skipFormat) {
@@ -180,7 +182,8 @@ export default viteConfigurationGenerator;
 
 function updatePackageJson(
   tree: Tree,
-  options: ViteConfigurationGeneratorSchema
+  options: ViteConfigurationGeneratorSchema,
+  projectType: 'application' | 'library'
 ) {
   const project = readProjectConfiguration(tree, options.project);
 
@@ -193,28 +196,33 @@ function updatePackageJson(
       name: getImportPath(tree, options.project),
       version: '0.0.1',
     };
+    if (projectType === 'application') {
+      packageJson.private = true;
+    }
   }
 
-  // we always write/override the vite and project config with some set values,
-  // so we can rely on them
-  const main = join(project.root, 'src/index.ts');
-  // we configure the dts plugin with the entryRoot set to `src`
-  const rootDir = join(project.root, 'src');
-  const outputPath = joinPathFragments(project.root, 'dist');
-
-  packageJson = getUpdatedPackageJsonContent(packageJson, {
-    main,
-    outputPath,
-    projectRoot: project.root,
-    rootDir,
-    generateExportsField: true,
-    packageJsonPath,
-    format: ['esm', 'cjs'],
-    // when building both formats, we don't set the package.json "type" field, so
-    // we need to set the esm extension to ".mjs" to match vite output
-    // see the "File Extensions" callout in https://vite.dev/guide/build.html#library-mode
-    outputFileExtensionForEsm: '.mjs',
-  });
+  if (projectType === 'library') {
+    // we always write/override the vite and project config with some set values,
+    // so we can rely on them
+    const main = join(project.root, 'src/index.ts');
+    // we configure the dts plugin with the entryRoot set to `src`
+    const rootDir = join(project.root, 'src');
+    const outputPath = joinPathFragments(project.root, 'dist');
+
+    packageJson = getUpdatedPackageJsonContent(packageJson, {
+      main,
+      outputPath,
+      projectRoot: project.root,
+      rootDir,
+      generateExportsField: true,
+      packageJsonPath,
+      format: ['esm', 'cjs'],
+      // when building both formats, we don't set the package.json "type" field, so
+      // we need to set the esm extension to ".mjs" to match vite output
+      // see the "File Extensions" callout in https://vite.dev/guide/build.html#library-mode
+      outputFileExtensionForEsm: '.mjs',
+    });
+  }
 
   writeJson(tree, packageJsonPath, packageJson);
 }
diff --git a/packages/vite/src/generators/configuration/schema.d.ts b/packages/vite/src/generators/configuration/schema.d.ts
index 907958eb2b28a2..3b9d843556e40b 100644
--- a/packages/vite/src/generators/configuration/schema.d.ts
+++ b/packages/vite/src/generators/configuration/schema.d.ts
@@ -8,5 +8,7 @@ export interface ViteConfigurationGeneratorSchema {
   includeLib?: boolean;
   skipFormat?: boolean;
   testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string;
+  // Internal options
   addPlugin?: boolean;
+  projectType?: 'application' | 'library';
 }
diff --git a/packages/vite/src/generators/vitest/schema.d.ts b/packages/vite/src/generators/vitest/schema.d.ts
index e876864ac4bac0..8625e15530be5c 100644
--- a/packages/vite/src/generators/vitest/schema.d.ts
+++ b/packages/vite/src/generators/vitest/schema.d.ts
@@ -10,4 +10,6 @@ export interface VitestGeneratorSchema {
   addPlugin?: boolean;
   runtimeTsconfigFileName?: string;
   compiler?: 'babel' | 'swc'; // default: babel
+  // internal options
+  projectType?: 'application' | 'library';
 }
diff --git a/packages/vite/src/generators/vitest/vitest-generator.ts b/packages/vite/src/generators/vitest/vitest-generator.ts
index 1b03dd1e737e93..7082c01749cdff 100644
--- a/packages/vite/src/generators/vitest/vitest-generator.ts
+++ b/packages/vite/src/generators/vitest/vitest-generator.ts
@@ -51,7 +51,11 @@ export async function vitestGeneratorInternal(
 
   const tasks: GeneratorCallback[] = [];
 
-  const { root, projectType } = readProjectConfiguration(tree, schema.project);
+  const { root, projectType: _projectType } = readProjectConfiguration(
+    tree,
+    schema.project
+  );
+  const projectType = schema.projectType ?? _projectType;
   const isRootProject = root === '.';
 
   tasks.push(await jsInitGenerator(tree, { ...schema, skipFormat: true }));
@@ -279,7 +283,9 @@ function createFiles(
     extendedConfig: isTsSolutionSetup
       ? `${rootOffset}tsconfig.base.json`
       : './tsconfig.json',
-    outDir: isTsSolutionSetup ? `./out-tsc/jest` : `${rootOffset}dist/out-tsc`,
+    outDir: isTsSolutionSetup
+      ? `./out-tsc/vitest`
+      : `${rootOffset}dist/out-tsc`,
   });
 }
 
diff --git a/packages/vite/src/plugins/plugin.spec.ts b/packages/vite/src/plugins/plugin.spec.ts
index 1b3a9334f74b7a..6eec64ff806a84 100644
--- a/packages/vite/src/plugins/plugin.spec.ts
+++ b/packages/vite/src/plugins/plugin.spec.ts
@@ -2,6 +2,7 @@ import { CreateNodesContext } from '@nx/devkit';
 import { createNodesV2 } from './plugin';
 import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
 import { loadViteDynamicImport } from '../utils/executor-utils';
+import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 jest.mock('../utils/executor-utils', () => ({
   loadViteDynamicImport: jest.fn().mockResolvedValue({
@@ -9,6 +10,11 @@ jest.mock('../utils/executor-utils', () => ({
   }),
 }));
 
+jest.mock('@nx/js/src/utils/typescript/ts-solution-setup', () => ({
+  ...jest.requireActual('@nx/js/src/utils/typescript/ts-solution-setup'),
+  isUsingTsSolutionSetup: jest.fn().mockReturnValue(false),
+}));
+
 describe('@nx/vite/plugin', () => {
   let createNodesFunction = createNodesV2[1];
   let context: CreateNodesContext;
@@ -87,6 +93,27 @@ describe('@nx/vite/plugin', () => {
       expect(targets?.['build-input']?.command).toMatch(/vite/);
       expect(targets?.['serve-input'].command).toMatch(/vite/);
     });
+
+    it('should infer typecheck with --build flag when using TS solution setup', async () => {
+      (isUsingTsSolutionSetup as jest.Mock).mockResolvedValue(true);
+      tempFs.createFileSync('tsconfig.json', '');
+
+      const nodes = await createNodesFunction(
+        ['vite.config.ts'],
+        {
+          buildTargetName: 'build',
+          serveTargetName: 'serve',
+          previewTargetName: 'preview',
+          testTargetName: 'test',
+          serveStaticTargetName: 'serve-static',
+        },
+        context
+      );
+
+      expect(nodes[0][1].projects['.'].targets.typecheck.command).toEqual(
+        `tsc --build --emitDeclarationOnly --pretty --verbose`
+      );
+    });
   });
 
   describe('not root project', () => {
diff --git a/packages/vite/src/plugins/plugin.ts b/packages/vite/src/plugins/plugin.ts
index 64868c07b2eb02..79eb7fed6ee9e1 100644
--- a/packages/vite/src/plugins/plugin.ts
+++ b/packages/vite/src/plugins/plugin.ts
@@ -22,6 +22,7 @@ import { getLockFileName } from '@nx/js';
 import { loadViteDynamicImport } from '../utils/executor-utils';
 import { hashObject } from 'nx/src/hasher/file-hasher';
 import { minimatch } from 'minimatch';
+import { isUsingTsSolutionSetup as _isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 const pmc = getPackageManagerCommand();
 
@@ -59,10 +60,17 @@ export const createNodesV2: CreateNodesV2<VitePluginOptions> = [
     const optionsHash = hashObject(options);
     const cachePath = join(workspaceDataDirectory, `vite-${optionsHash}.hash`);
     const targetsCache = readTargetsCache(cachePath);
+    const isUsingTsSolutionSetup = _isUsingTsSolutionSetup();
     try {
       return await createNodesFromFiles(
         (configFile, options, context) =>
-          createNodesInternal(configFile, options, context, targetsCache),
+          createNodesInternal(
+            configFile,
+            options,
+            context,
+            targetsCache,
+            isUsingTsSolutionSetup
+          ),
         configFilePaths,
         options,
         context
@@ -79,7 +87,13 @@ export const createNodes: CreateNodes<VitePluginOptions> = [
     logger.warn(
       '`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
     );
-    return createNodesInternal(configFilePath, options, context, {});
+    return createNodesInternal(
+      configFilePath,
+      options,
+      context,
+      {},
+      _isUsingTsSolutionSetup()
+    );
   },
 ];
 
@@ -87,7 +101,8 @@ async function createNodesInternal(
   configFilePath: string,
   options: VitePluginOptions,
   context: CreateNodesContext,
-  targetsCache: Record<string, ViteTargets>
+  targetsCache: Record<string, ViteTargets>,
+  isUsingTsSolutionSetup: boolean
 ) {
   const projectRoot = dirname(configFilePath);
   // Do not create a project if package.json and project.json isn't there.
@@ -119,6 +134,7 @@ async function createNodesInternal(
     projectRoot,
     normalizedOptions,
     tsConfigFiles,
+    isUsingTsSolutionSetup,
     context
   );
   targetsCache[hash] ??= viteTargets;
@@ -148,6 +164,7 @@ async function buildViteTargets(
   projectRoot: string,
   options: VitePluginOptions,
   tsConfigFiles: string[],
+  isUsingTsSolutionSetup: boolean,
   context: CreateNodesContext
 ): Promise<ViteTargets & { isLibrary: boolean }> {
   const absoluteConfigFilePath = joinPathFragments(
@@ -218,7 +235,9 @@ async function buildViteTargets(
           : ['default', '^default']),
         { externalDependencies: ['typescript'] },
       ],
-      command: `tsc --noEmit -p ${tsConfigToUse}`,
+      command: isUsingTsSolutionSetup
+        ? `tsc --build --emitDeclarationOnly --pretty --verbose`
+        : `tsc --noEmit -p ${tsConfigToUse}`,
       options: { cwd: joinPathFragments(projectRoot) },
       metadata: {
         description: `Run Typechecking`,
diff --git a/packages/webpack/src/generators/configuration/configuration.ts b/packages/webpack/src/generators/configuration/configuration.ts
index e4b9de0c972246..f4cd67321e3209 100644
--- a/packages/webpack/src/generators/configuration/configuration.ts
+++ b/packages/webpack/src/generators/configuration/configuration.ts
@@ -17,7 +17,6 @@ import { WebpackExecutorOptions } from '../../executors/webpack/schema';
 import { hasPlugin } from '../../utils/has-plugin';
 import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
 import { ensureDependencies } from '../../utils/ensure-dependencies';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 
 export function configurationGenerator(
   tree: Tree,
@@ -30,8 +29,6 @@ export async function configurationGeneratorInternal(
   tree: Tree,
   options: ConfigurationGeneratorSchema
 ) {
-  assertNotUsingTsSolutionSetup(tree, 'webpack', 'configuration');
-
   const tasks: GeneratorCallback[] = [];
   const nxJson = readNxJson(tree);
   const addPluginDefault =
diff --git a/packages/webpack/src/generators/init/init.ts b/packages/webpack/src/generators/init/init.ts
index ec19d0f2f1419e..24f10417e6036e 100644
--- a/packages/webpack/src/generators/init/init.ts
+++ b/packages/webpack/src/generators/init/init.ts
@@ -7,7 +7,6 @@ import {
   Tree,
 } from '@nx/devkit';
 import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin';
-import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
 import { createNodes } from '../../plugins/plugin';
 import { nxVersion, webpackCliVersion } from '../../utils/versions';
 import { Schema } from './schema';
@@ -17,8 +16,6 @@ export function webpackInitGenerator(tree: Tree, schema: Schema) {
 }
 
 export async function webpackInitGeneratorInternal(tree: Tree, schema: Schema) {
-  assertNotUsingTsSolutionSetup(tree, 'webpack', 'init');
-
   const nxJson = readNxJson(tree);
   const addPluginDefault =
     process.env.NX_ADD_PLUGINS !== 'false' &&
diff --git a/packages/workspace/src/generators/new/generate-preset.ts b/packages/workspace/src/generators/new/generate-preset.ts
index dba0c37028ac18..6824da637cc093 100644
--- a/packages/workspace/src/generators/new/generate-preset.ts
+++ b/packages/workspace/src/generators/new/generate-preset.ts
@@ -85,6 +85,7 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
       opts.prefix !== undefined ? `--prefix=${opts.prefix}` : null,
       opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
       opts.formatter ? `--formatter=${opts.formatter}` : null,
+      opts.workspaces ? `--workspaces` : null,
     ].filter((e) => !!e);
   }
 }
diff --git a/packages/workspace/src/generators/new/generate-workspace-files.spec.ts b/packages/workspace/src/generators/new/generate-workspace-files.spec.ts
index 2a84d1791c92ed..a53182eebf46f7 100644
--- a/packages/workspace/src/generators/new/generate-workspace-files.spec.ts
+++ b/packages/workspace/src/generators/new/generate-workspace-files.spec.ts
@@ -1,4 +1,12 @@
-import { createNxCloudOnboardingURL } from 'nx/src/nx-cloud/utilities/url-shorten';
+import type { NxJsonConfiguration, Tree } from '@nx/devkit';
+import { formatFiles, readJson } from '@nx/devkit';
+import Ajv from 'ajv';
+import { generateWorkspaceFiles } from './generate-workspace-files';
+import { createTree } from '@nx/devkit/testing';
+import { Preset } from '../utils/presets';
+import * as nxSchema from 'nx/schemas/nx-schema.json';
+import { mkdirSync, writeFileSync } from 'fs';
+import { join } from 'path';
 
 jest.mock(
   'nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud',
@@ -18,16 +26,6 @@ jest.mock('nx/src/nx-cloud/utilities/url-shorten', () => ({
   },
 }));
 
-import type { NxJsonConfiguration, Tree } from '@nx/devkit';
-import { formatFiles, readJson } from '@nx/devkit';
-import Ajv from 'ajv';
-import { generateWorkspaceFiles } from './generate-workspace-files';
-import { createTree } from '@nx/devkit/testing';
-import { Preset } from '../utils/presets';
-import * as nxSchema from 'nx/schemas/nx-schema.json';
-import { mkdirSync, writeFileSync } from 'fs';
-import { join } from 'path';
-
 describe('@nx/workspace:generateWorkspaceFiles', () => {
   let tree: Tree;
 
@@ -232,7 +230,7 @@ describe('@nx/workspace:generateWorkspaceFiles', () => {
         "scripts": {},
         "version": "0.0.0",
         "workspaces": [
-          "packages/*",
+          "packages/**",
         ],
       }
     `);
@@ -286,4 +284,57 @@ describe('@nx/workspace:generateWorkspaceFiles', () => {
 
     expect(readJson(tree, 'proj/package.json').scripts).toMatchSnapshot();
   });
+
+  it('should create workspaces from workspaceGlobs (npm)', async () => {
+    tree.write('/proj/package.json', JSON.stringify({}));
+    await generateWorkspaceFiles(tree, {
+      name: 'proj',
+      directory: 'proj',
+      preset: Preset.NPM,
+      defaultBase: 'main',
+      packageManager: 'npm',
+      isCustomPreset: false,
+      workspaceGlobs: ['apps/**', 'packages/**'],
+    });
+
+    const packageJson = readJson(tree, '/proj/package.json');
+    expect(packageJson).toMatchInlineSnapshot(`
+      {
+        "dependencies": {},
+        "devDependencies": {
+          "nx": "0.0.1",
+        },
+        "license": "MIT",
+        "name": "@proj/source",
+        "private": true,
+        "scripts": {},
+        "version": "0.0.0",
+        "workspaces": [
+          "apps/**",
+          "packages/**",
+        ],
+      }
+    `);
+  });
+
+  it('should create workspaces from workspaceGlobs (pnpm)', async () => {
+    tree.write('/proj/package.json', JSON.stringify({}));
+    await generateWorkspaceFiles(tree, {
+      name: 'proj',
+      directory: 'proj',
+      preset: Preset.NPM,
+      defaultBase: 'main',
+      packageManager: 'pnpm',
+      isCustomPreset: false,
+      workspaceGlobs: ['apps/**', 'packages/**'],
+    });
+
+    const packageJson = tree.read('/proj/pnpm-workspace.yaml', 'utf-8');
+    expect(packageJson).toMatchInlineSnapshot(`
+      "packages: 
+        - apps/**
+        - packages/**
+      "
+    `);
+  });
 });
diff --git a/packages/workspace/src/generators/new/generate-workspace-files.ts b/packages/workspace/src/generators/new/generate-workspace-files.ts
index 877ca6bcfcadcd..da8bb757206806 100644
--- a/packages/workspace/src/generators/new/generate-workspace-files.ts
+++ b/packages/workspace/src/generators/new/generate-workspace-files.ts
@@ -416,18 +416,25 @@ function setUpWorkspacesInPackageJson(tree: Tree, options: NormalizedSchema) {
     options.preset === Preset.NPM ||
     (options.preset === Preset.TS &&
       process.env.NX_ADD_PLUGINS !== 'false' &&
-      process.env.NX_ADD_TS_PLUGIN !== 'false')
+      process.env.NX_ADD_TS_PLUGIN !== 'false') ||
+    ((options.preset === Preset.Expo ||
+      options.preset === Preset.NextJs ||
+      options.preset === Preset.ReactMonorepo ||
+      options.preset === Preset.ReactNative ||
+      options.preset === Preset.RemixMonorepo) &&
+      options.workspaces)
   ) {
+    const workspaces = options.workspaceGlobs ?? ['packages/**'];
     if (options.packageManager === 'pnpm') {
       tree.write(
         join(options.directory, 'pnpm-workspace.yaml'),
-        `packages:
-  - 'packages/*'
+        `packages: 
+  - ${workspaces.join('\n  - ')}
 `
       );
     } else {
       updateJson(tree, join(options.directory, 'package.json'), (json) => {
-        json.workspaces = ['packages/*'];
+        json.workspaces = workspaces;
         return json;
       });
     }
diff --git a/packages/workspace/src/generators/new/new.ts b/packages/workspace/src/generators/new/new.ts
index b0ce463c6df18c..0167a358e11ed4 100644
--- a/packages/workspace/src/generators/new/new.ts
+++ b/packages/workspace/src/generators/new/new.ts
@@ -38,12 +38,15 @@ interface Schema {
   useGitHub?: boolean;
   nxCloud?: 'yes' | 'skip' | 'circleci' | 'github';
   formatter?: 'none' | 'prettier';
+  workspaces?: boolean;
+  workspaceGlobs?: string | string[];
 }
 
 export interface NormalizedSchema extends Schema {
   presetVersion?: string;
   isCustomPreset: boolean;
   nxCloudToken?: string;
+  workspaceGlobs?: string[];
 }
 
 export async function newGenerator(tree: Tree, opts: Schema) {
@@ -136,6 +139,11 @@ function parsePresetName(input: string): { package: string; version?: string } {
 function normalizeOptions(options: Schema): NormalizedSchema {
   const normalized: Partial<NormalizedSchema> = {
     ...options,
+    workspaceGlobs: Array.isArray(options.workspaceGlobs)
+      ? options.workspaceGlobs
+      : options.workspaceGlobs
+      ? [options.workspaceGlobs]
+      : undefined,
   };
 
   if (!options.directory) {
diff --git a/packages/workspace/src/generators/new/schema.json b/packages/workspace/src/generators/new/schema.json
index 4f895ab3a8fdad..65c62cc936c4ed 100644
--- a/packages/workspace/src/generators/new/schema.json
+++ b/packages/workspace/src/generators/new/schema.json
@@ -50,7 +50,7 @@
     "linter": {
       "description": "The tool to use for running lint checks.",
       "type": "string",
-      "enum": ["eslint"],
+      "enum": ["eslint", "none"],
       "default": "eslint"
     },
     "packageManager": {
@@ -92,6 +92,11 @@
       "type": "string",
       "enum": ["none", "prettier"],
       "default": "none"
+    },
+    "workspaces": {
+      "description": "Whether to use package manager workspaces.",
+      "type": "boolean",
+      "default": false
     }
   },
   "additionalProperties": true
diff --git a/packages/workspace/src/generators/preset/preset.ts b/packages/workspace/src/generators/preset/preset.ts
index ad115d754021b9..3b9a8ba5331fe9 100644
--- a/packages/workspace/src/generators/preset/preset.ts
+++ b/packages/workspace/src/generators/preset/preset.ts
@@ -71,6 +71,8 @@ async function createPreset(tree: Tree, options: Schema) {
       e2eTestRunner: options.e2eTestRunner ?? 'playwright',
       addPlugin,
       nxCloudToken: options.nxCloudToken,
+      useTsSolution: options.workspaces,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.ReactStandalone) {
     const { applicationGenerator: reactApplicationGenerator } = require('@nx' +
@@ -87,6 +89,7 @@ async function createPreset(tree: Tree, options: Schema) {
       unitTestRunner: options.bundler === 'vite' ? 'vitest' : 'jest',
       addPlugin,
       nxCloudToken: options.nxCloudToken,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.RemixMonorepo) {
     const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
@@ -100,6 +103,8 @@ async function createPreset(tree: Tree, options: Schema) {
       unitTestRunner: 'vitest',
       addPlugin,
       nxCloudToken: options.nxCloudToken,
+      useTsSolution: options.workspaces,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.RemixStandalone) {
     const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
@@ -114,6 +119,7 @@ async function createPreset(tree: Tree, options: Schema) {
       unitTestRunner: 'vitest',
       addPlugin,
       nxCloudToken: options.nxCloudToken,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.VueMonorepo) {
     const { applicationGenerator: vueApplicationGenerator } = require('@nx' +
@@ -184,6 +190,8 @@ async function createPreset(tree: Tree, options: Schema) {
       src: options.nextSrcDir,
       e2eTestRunner: options.e2eTestRunner ?? 'playwright',
       addPlugin,
+      useTsSolution: options.workspaces,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.NextJsStandalone) {
     const { applicationGenerator: nextApplicationGenerator } = require('@nx' +
@@ -198,6 +206,7 @@ async function createPreset(tree: Tree, options: Schema) {
       e2eTestRunner: options.e2eTestRunner ?? 'playwright',
       rootProject: true,
       addPlugin,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.WebComponents) {
     const { applicationGenerator: webApplicationGenerator } = require('@nx' +
@@ -246,6 +255,8 @@ async function createPreset(tree: Tree, options: Schema) {
       addPlugin,
       nxCloudToken: options.nxCloudToken,
       bundler: options.bundler ?? 'webpack',
+      useTsSolution: options.workspaces,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.Expo) {
     const { expoApplicationGenerator } = require('@nx' + '/expo');
@@ -256,6 +267,8 @@ async function createPreset(tree: Tree, options: Schema) {
       e2eTestRunner: options.e2eTestRunner ?? 'detox',
       addPlugin,
       nxCloudToken: options.nxCloudToken,
+      useTsSolution: options.workspaces,
+      formatter: options.formatter,
     });
   } else if (options.preset === Preset.TS) {
     const { initGenerator } = require('@nx' + '/js');
diff --git a/packages/workspace/src/generators/preset/schema.d.ts b/packages/workspace/src/generators/preset/schema.d.ts
index 8c9d19f54c1ed4..e25c2b9084b8e1 100644
--- a/packages/workspace/src/generators/preset/schema.d.ts
+++ b/packages/workspace/src/generators/preset/schema.d.ts
@@ -7,6 +7,7 @@ export interface Schema {
   style?: string;
   linter?: string;
   formatter?: 'none' | 'prettier';
+  workspaces?: boolean;
   standaloneConfig?: boolean;
   framework?: string;
   packageManager?: PackageManager;
diff --git a/packages/workspace/src/generators/preset/schema.json b/packages/workspace/src/generators/preset/schema.json
index 891e099699022a..53f305180dfb9f 100644
--- a/packages/workspace/src/generators/preset/schema.json
+++ b/packages/workspace/src/generators/preset/schema.json
@@ -17,7 +17,7 @@
     "linter": {
       "description": "The tool to use for running lint checks.",
       "type": "string",
-      "enum": ["eslint"],
+      "enum": ["eslint", "none"],
       "default": "eslint"
     },
     "routing": {
@@ -103,6 +103,17 @@
     "prefix": {
       "description": "The prefix to use for Angular component and directive selectors.",
       "type": "string"
+    },
+    "formatter": {
+      "description": "The tool to use for code formatting.",
+      "type": "string",
+      "enum": ["none", "prettier"],
+      "default": "none"
+    },
+    "workspaces": {
+      "description": "Whether to use package manager workspaces.",
+      "type": "boolean",
+      "default": false
     }
   },
   "required": ["preset", "name"]