From af6b1689975d585d82eb09a32447273e43a01578 Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 16 Oct 2026 17:49:52 +0800 Subject: [PATCH 1/3] feat(create-rstack): add Nx template --- packages/create-rstack/README.md | 1 + packages/create-rstack/src/index.ts | 10 +++- packages/create-rstack/template-nx/README.md | 35 +++++++++++ .../template-nx/apps/web/package.json | 26 +++++++++ .../template-nx/apps/web/rstack.config.ts | 15 +++++ .../template-nx/apps/web/src/App.tsx | 17 ++++++ .../template-nx/apps/web/src/index.css | 27 +++++++++ .../template-nx/apps/web/src/index.tsx | 13 +++++ .../template-nx/apps/web/tests/app.test.tsx | 11 ++++ .../apps/web/tests/rstest.setup.ts | 4 ++ .../template-nx/apps/web/tests/tsconfig.json | 7 +++ .../template-nx/apps/web/tsconfig.json | 4 ++ packages/create-rstack/template-nx/gitignore | 17 ++++++ packages/create-rstack/template-nx/nx.json | 29 ++++++++++ .../create-rstack/template-nx/package.json | 20 +++++++ .../template-nx/packages/ui/package.json | 39 +++++++++++++ .../template-nx/packages/ui/rstack.config.ts | 20 +++++++ .../template-nx/packages/ui/src/button.tsx | 8 +++ .../packages/ui/tests/button.test.tsx | 18 ++++++ .../packages/ui/tests/rstest.setup.ts | 4 ++ .../packages/ui/tests/tsconfig.json | 8 +++ .../template-nx/packages/ui/tsconfig.json | 7 +++ .../template-nx/pnpm-workspace.yaml | 6 ++ .../template-nx/rstack.config.ts | 30 ++++++++++ .../template-nx/tsconfig.base.json | 22 +++++++ packages/create-rstack/tests/create.test.ts | 58 ++++++++++--------- website/docs/en/guide/quick-start.mdx | 4 +- website/docs/zh/guide/quick-start.mdx | 4 +- 28 files changed, 431 insertions(+), 33 deletions(-) create mode 100644 packages/create-rstack/template-nx/README.md create mode 100644 packages/create-rstack/template-nx/apps/web/package.json create mode 100644 packages/create-rstack/template-nx/apps/web/rstack.config.ts create mode 100644 packages/create-rstack/template-nx/apps/web/src/App.tsx create mode 100644 packages/create-rstack/template-nx/apps/web/src/index.css create mode 100644 packages/create-rstack/template-nx/apps/web/src/index.tsx create mode 100644 packages/create-rstack/template-nx/apps/web/tests/app.test.tsx create mode 100644 packages/create-rstack/template-nx/apps/web/tests/rstest.setup.ts create mode 100644 packages/create-rstack/template-nx/apps/web/tests/tsconfig.json create mode 100644 packages/create-rstack/template-nx/apps/web/tsconfig.json create mode 100644 packages/create-rstack/template-nx/gitignore create mode 100644 packages/create-rstack/template-nx/nx.json create mode 100644 packages/create-rstack/template-nx/package.json create mode 100644 packages/create-rstack/template-nx/packages/ui/package.json create mode 100644 packages/create-rstack/template-nx/packages/ui/rstack.config.ts create mode 100644 packages/create-rstack/template-nx/packages/ui/src/button.tsx create mode 100644 packages/create-rstack/template-nx/packages/ui/tests/button.test.tsx create mode 100644 packages/create-rstack/template-nx/packages/ui/tests/rstest.setup.ts create mode 100644 packages/create-rstack/template-nx/packages/ui/tests/tsconfig.json create mode 100644 packages/create-rstack/template-nx/packages/ui/tsconfig.json create mode 100644 packages/create-rstack/template-nx/pnpm-workspace.yaml create mode 100644 packages/create-rstack/template-nx/rstack.config.ts create mode 100644 packages/create-rstack/template-nx/tsconfig.base.json diff --git a/packages/create-rstack/README.md b/packages/create-rstack/README.md index e6c47e26..e41dc6d7 100644 --- a/packages/create-rstack/README.md +++ b/packages/create-rstack/README.md @@ -51,6 +51,7 @@ npx create-rstack --dir my-project --template app-vanilla-ts --no-git - `doc` - Basic documentation site - `doc-i18n` - Multilingual documentation site - `turborepo` - Turborepo +- `nx` - Nx ## Documentation diff --git a/packages/create-rstack/src/index.ts b/packages/create-rstack/src/index.ts index 762aac45..a925e197 100644 --- a/packages/create-rstack/src/index.ts +++ b/packages/create-rstack/src/index.ts @@ -44,6 +44,7 @@ const templateNames = [ 'doc', 'doc-i18n', 'turborepo', + 'nx', ]; const resolveTemplateName = (template: string): string => { @@ -56,7 +57,7 @@ const resolveTemplateName = (template: string): string => { const getTemplateName = async ({ template }: Argv): Promise => { if (typeof template === 'string') { - if (/^(?:app|lib|doc|turborepo)(?:-|$)/u.test(template)) { + if (/^(?:app|lib|doc|turborepo|nx)(?:-|$)/u.test(template)) { return resolveTemplateName(template); } @@ -79,7 +80,10 @@ const getTemplateName = async ({ template }: Argv): Promise => { const monorepoType = checkCancel( await select({ message: 'Select monorepo tool', - options: [{ value: 'turborepo', label: 'Turborepo', hint: 'pnpm' }], + options: [ + { value: 'turborepo', label: 'Turborepo', hint: 'pnpm' }, + { value: 'nx', label: 'Nx', hint: 'pnpm' }, + ], }), ); @@ -235,6 +239,6 @@ await create({ builtinTools: [], getTemplateName, getPackageManager: ({ templateName }) => - templateName === 'turborepo' ? 'pnpm' : undefined, + ['turborepo', 'nx'].includes(templateName) ? 'pnpm' : undefined, onGitResolved: injectStagedSetup, }); diff --git a/packages/create-rstack/template-nx/README.md b/packages/create-rstack/template-nx/README.md new file mode 100644 index 00000000..d27364a1 --- /dev/null +++ b/packages/create-rstack/template-nx/README.md @@ -0,0 +1,35 @@ +# Nx + Rstack + +## Setup + +```bash +pnpm install +``` + +## Structure + +- `apps/web`: React application. +- `packages/ui`: Shared UI components. +- `tsconfig.base.json`: Shared TypeScript configuration. + +## Scripts + +Run from the repository root: + +- `pnpm run build`: Build all packages. +- `pnpm run dev`: Start the web app and watch the shared UI package. +- `pnpm run test`: Run tests. +- `pnpm run check`: Run lint, formatting, and TypeScript checks. +- `pnpm run lint`: Lint the workspace. +- `pnpm run format`: Format the workspace. + +Nx discovers projects and tasks from workspace package manifests. Build and test tasks are cached, and dependencies are built first. + +Run `pnpm run build` before `pnpm run check`. + +Use `pnpm exec nx graph` to explore the project graph. + +## Learn more + +- [Rstack CLI monorepo guide](https://rstack.rs/guide/monorepo) +- [Nx documentation](https://nx.dev/docs/getting-started/intro) diff --git a/packages/create-rstack/template-nx/apps/web/package.json b/packages/create-rstack/template-nx/apps/web/package.json new file mode 100644 index 00000000..b322570c --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/package.json @@ -0,0 +1,26 @@ +{ + "name": "web", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "rs build", + "dev": "rs dev", + "preview": "rs preview", + "test": "rs test" + }, + "dependencies": { + "@repo/ui": "workspace:^", + "react": "^19.3.0", + "react-dom": "^19.3.0" + }, + "devDependencies": { + "@rsbuild/plugin-react": "^2.1.1", + "@testing-library/dom": "^10.4.2", + "@testing-library/jest-dom": "^7.0.1", + "@testing-library/react": "^16.3.3", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "happy-dom": "^21.0.1" + } +} diff --git a/packages/create-rstack/template-nx/apps/web/rstack.config.ts b/packages/create-rstack/template-nx/apps/web/rstack.config.ts new file mode 100644 index 00000000..778e61cf --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/rstack.config.ts @@ -0,0 +1,15 @@ +// Configuration guide: https://rstack.rs/config +import { define } from 'rstack'; + +define.app(async () => { + const { pluginReact } = await import('@rsbuild/plugin-react'); + return { + plugins: [pluginReact()], + html: { title: 'Web | Rstack' }, + server: { port: 3000 }, + }; +}); + +define.test({ + setupFiles: ['./tests/rstest.setup.ts'], +}); diff --git a/packages/create-rstack/template-nx/apps/web/src/App.tsx b/packages/create-rstack/template-nx/apps/web/src/App.tsx new file mode 100644 index 00000000..e0a78c18 --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/src/App.tsx @@ -0,0 +1,17 @@ +import { Button } from '@repo/ui/button'; + +export function App() { + return ( +
+

Web

+

Nx + Rstack CLI

+

Edit apps/web/src/App.tsx to get started.

+ + +
+ ); +} diff --git a/packages/create-rstack/template-nx/apps/web/src/index.css b/packages/create-rstack/template-nx/apps/web/src/index.css new file mode 100644 index 00000000..6da54671 --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/src/index.css @@ -0,0 +1,27 @@ +body { + margin: 0; + font-family: system-ui, sans-serif; + color: #202124; + background: #f8f9fa; +} + +main { + max-width: 640px; + margin: 15vh auto; + padding: 24px; +} + +button { + padding: 10px 16px; + border: 0; + border-radius: 8px; + color: white; + background: #5755d9; + cursor: pointer; +} + +nav { + display: flex; + gap: 20px; + margin-top: 24px; +} diff --git a/packages/create-rstack/template-nx/apps/web/src/index.tsx b/packages/create-rstack/template-nx/apps/web/src/index.tsx new file mode 100644 index 00000000..89109467 --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/src/index.tsx @@ -0,0 +1,13 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { App } from './App'; +import './index.css'; + +const root = document.getElementById('root'); +if (root) { + createRoot(root).render( + + + , + ); +} diff --git a/packages/create-rstack/template-nx/apps/web/tests/app.test.tsx b/packages/create-rstack/template-nx/apps/web/tests/app.test.tsx new file mode 100644 index 00000000..7268227b --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/tests/app.test.tsx @@ -0,0 +1,11 @@ +import { expect, test } from 'rstack/test'; +import { render, screen } from '@testing-library/react'; +import { App } from '../src/App'; + +test('renders the web app with the shared UI package', () => { + render(); + expect(screen.getByRole('heading', { name: 'Web' })).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'Shared button' }), + ).toBeInTheDocument(); +}); diff --git a/packages/create-rstack/template-nx/apps/web/tests/rstest.setup.ts b/packages/create-rstack/template-nx/apps/web/tests/rstest.setup.ts new file mode 100644 index 00000000..93951b15 --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/tests/rstest.setup.ts @@ -0,0 +1,4 @@ +import { expect } from 'rstack/test'; +import * as jestDomMatchers from '@testing-library/jest-dom/matchers'; + +expect.extend(jestDomMatchers); diff --git a/packages/create-rstack/template-nx/apps/web/tests/tsconfig.json b/packages/create-rstack/template-nx/apps/web/tests/tsconfig.json new file mode 100644 index 00000000..3eb5dc12 --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/tests/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "types": ["rstack/types", "node", "@testing-library/jest-dom"] + }, + "include": ["./"] +} diff --git a/packages/create-rstack/template-nx/apps/web/tsconfig.json b/packages/create-rstack/template-nx/apps/web/tsconfig.json new file mode 100644 index 00000000..1ccf2b9a --- /dev/null +++ b/packages/create-rstack/template-nx/apps/web/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src", "rstack.config.ts"] +} diff --git a/packages/create-rstack/template-nx/gitignore b/packages/create-rstack/template-nx/gitignore new file mode 100644 index 00000000..224c6c96 --- /dev/null +++ b/packages/create-rstack/template-nx/gitignore @@ -0,0 +1,17 @@ +# Local +.DS_Store +*.local +*.log* + +# Dist +node_modules +dist/ + +# IDE +.vscode/* +!.vscode/extensions.json +.idea + +# Nx +.nx/cache/ +.nx/workspace-data/ diff --git a/packages/create-rstack/template-nx/nx.json b/packages/create-rstack/template-nx/nx.json new file mode 100644 index 00000000..968be05b --- /dev/null +++ b/packages/create-rstack/template-nx/nx.json @@ -0,0 +1,29 @@ +{ + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "sharedGlobals": [ + "{workspaceRoot}/tsconfig.base.json", + "{workspaceRoot}/rstack.config.ts", + "{workspaceRoot}/pnpm-workspace.yaml" + ] + }, + "targetDefaults": { + "build": { + "dependsOn": ["^build"], + "cache": true, + "inputs": ["default", "^default"], + "outputs": ["{projectRoot}/dist"] + }, + "dev": { + "dependsOn": ["^build"], + "cache": false, + "continuous": true + }, + "test": { + "dependsOn": ["^build"], + "cache": true, + "inputs": ["default", "^default"] + } + } +} diff --git a/packages/create-rstack/template-nx/package.json b/packages/create-rstack/template-nx/package.json new file mode 100644 index 00000000..4604f473 --- /dev/null +++ b/packages/create-rstack/template-nx/package.json @@ -0,0 +1,20 @@ +{ + "name": "rstack-nx", + "private": true, + "type": "module", + "scripts": { + "build": "nx run-many -t build", + "check": "rs check --type-check", + "dev": "nx run-many -t dev", + "format": "rs fmt", + "lint": "rs lint", + "test": "nx run-many -t test" + }, + "devDependencies": { + "@types/node": "^26.6.5", + "nx": "^23.3.0", + "rstack": "^0.8.4", + "typescript": "^7.0.2" + }, + "packageManager": "pnpm@12.11.2" +} diff --git a/packages/create-rstack/template-nx/packages/ui/package.json b/packages/create-rstack/template-nx/packages/ui/package.json new file mode 100644 index 00000000..836f321f --- /dev/null +++ b/packages/create-rstack/template-nx/packages/ui/package.json @@ -0,0 +1,39 @@ +{ + "name": "@repo/ui", + "version": "0.0.0", + "private": true, + "type": "module", + "exports": { + "./button": { + "types": "./dist/button.d.ts", + "default": "./dist/button.js" + } + }, + "scripts": { + "build": "rs lib", + "dev": "rs lib --watch --no-clean", + "test": "rs test" + }, + "dependencies": { + "react": "^19.3.0" + }, + "devDependencies": { + "@rsbuild/plugin-react": "^2.1.1", + "@testing-library/dom": "^10.4.2", + "@testing-library/jest-dom": "^7.0.1", + "@testing-library/react": "^16.3.3", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "happy-dom": "^21.0.1", + "react-dom": "^19.3.0" + }, + "nx": { + "targets": { + "dev": { + "dependsOn": [ + "build" + ] + } + } + } +} diff --git a/packages/create-rstack/template-nx/packages/ui/rstack.config.ts b/packages/create-rstack/template-nx/packages/ui/rstack.config.ts new file mode 100644 index 00000000..70438041 --- /dev/null +++ b/packages/create-rstack/template-nx/packages/ui/rstack.config.ts @@ -0,0 +1,20 @@ +// Configuration guide: https://rstack.rs/config +import { define } from 'rstack'; + +define.lib(async () => { + const { pluginReact } = await import('@rsbuild/plugin-react'); + return { + dts: true, + source: { + entry: { button: './src/button.tsx' }, + }, + output: { + target: 'web', + }, + plugins: [pluginReact()], + }; +}); + +define.test({ + setupFiles: ['./tests/rstest.setup.ts'], +}); diff --git a/packages/create-rstack/template-nx/packages/ui/src/button.tsx b/packages/create-rstack/template-nx/packages/ui/src/button.tsx new file mode 100644 index 00000000..19db4f2a --- /dev/null +++ b/packages/create-rstack/template-nx/packages/ui/src/button.tsx @@ -0,0 +1,8 @@ +import type { ComponentProps } from 'react'; + +export function Button({ + type = 'button', + ...props +}: ComponentProps<'button'>) { + return ); + const button = screen.getByRole('button', { name: 'Save' }); + expect(button).toHaveAttribute('type', 'button'); + expect(button).toBeDisabled(); +}); + +test('allows a submit button', () => { + render(); + expect(screen.getByRole('button', { name: 'Submit' })).toHaveAttribute( + 'type', + 'submit', + ); +}); diff --git a/packages/create-rstack/template-nx/packages/ui/tests/rstest.setup.ts b/packages/create-rstack/template-nx/packages/ui/tests/rstest.setup.ts new file mode 100644 index 00000000..93951b15 --- /dev/null +++ b/packages/create-rstack/template-nx/packages/ui/tests/rstest.setup.ts @@ -0,0 +1,4 @@ +import { expect } from 'rstack/test'; +import * as jestDomMatchers from '@testing-library/jest-dom/matchers'; + +expect.extend(jestDomMatchers); diff --git a/packages/create-rstack/template-nx/packages/ui/tests/tsconfig.json b/packages/create-rstack/template-nx/packages/ui/tests/tsconfig.json new file mode 100644 index 00000000..1f0e1fcb --- /dev/null +++ b/packages/create-rstack/template-nx/packages/ui/tests/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": "..", + "types": ["rstack/types", "node", "@testing-library/jest-dom"] + }, + "include": ["./", "../rstack.config.ts"] +} diff --git a/packages/create-rstack/template-nx/packages/ui/tsconfig.json b/packages/create-rstack/template-nx/packages/ui/tsconfig.json new file mode 100644 index 00000000..da8829fe --- /dev/null +++ b/packages/create-rstack/template-nx/packages/ui/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/packages/create-rstack/template-nx/pnpm-workspace.yaml b/packages/create-rstack/template-nx/pnpm-workspace.yaml new file mode 100644 index 00000000..84de81f0 --- /dev/null +++ b/packages/create-rstack/template-nx/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +packages: + - apps/* + - packages/* + +allowBuilds: + nx: true diff --git a/packages/create-rstack/template-nx/rstack.config.ts b/packages/create-rstack/template-nx/rstack.config.ts new file mode 100644 index 00000000..919d271d --- /dev/null +++ b/packages/create-rstack/template-nx/rstack.config.ts @@ -0,0 +1,30 @@ +// Configuration guide: https://rstack.rs/config +import { define } from 'rstack'; + +define.lint(({ js, ts, reactPlugin, reactHooksPlugin, rstestPlugin }) => [ + js.configs.recommended, + ts.configs.recommendedTypeChecked, + reactPlugin.configs.recommended, + reactHooksPlugin.configs.recommended, + { + files: ['**/*.{test,spec}.?(c|m)[jt]s?(x)'], + ...rstestPlugin.configs.recommended, + }, + { + languageOptions: { + parserOptions: { + project: [ + './apps/*/tsconfig.json', + './apps/*/tests/tsconfig.json', + './packages/*/tsconfig.json', + './packages/*/tests/tsconfig.json', + ], + }, + }, + }, +]); + +define.fmt({ + singleQuote: true, + ignorePatterns: ['**/dist/**', '**/.nx/**'], +}); diff --git a/packages/create-rstack/template-nx/tsconfig.base.json b/packages/create-rstack/template-nx/tsconfig.base.json new file mode 100644 index 00000000..d57fde3b --- /dev/null +++ b/packages/create-rstack/template-nx/tsconfig.base.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "jsx": "react-jsx", + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "types": ["rstack/types", "node"] + } +} diff --git a/packages/create-rstack/tests/create.test.ts b/packages/create-rstack/tests/create.test.ts index 0c11b067..9200a995 100644 --- a/packages/create-rstack/tests/create.test.ts +++ b/packages/create-rstack/tests/create.test.ts @@ -298,32 +298,38 @@ test.each(docTemplates)( }, ); -test('creates the Turborepo template with pnpm when invoked using npm', async () => { - const projectDirectory = await createProject('turborepo', { - userAgent: 'npm/11.0.0', - }); - const packageJson = await readProjectPackage(projectDirectory); - const appPackage = await readProjectPackage( - path.join(projectDirectory, 'apps/web'), - ); +test.each(['turborepo', 'nx'])( + 'creates the %s template with pnpm when invoked using npm', + async (template) => { + const projectDirectory = await createProject(template, { + userAgent: 'npm/11.0.0', + }); + const packageJson = await readProjectPackage(projectDirectory); + const appPackage = await readProjectPackage( + path.join(projectDirectory, 'apps/web'), + ); - await expectStagedSetup(projectDirectory, 'ts', packageJson.scripts); - expect(packageJson.packageManager).toMatch(/^pnpm@/u); - expect(appPackage.dependencies?.['@repo/ui']).toBe('workspace:^'); - await expectFiles(projectDirectory, [ - 'pnpm-workspace.yaml', - 'turbo.json', - 'apps/web/src/index.tsx', - 'packages/ui/src/button.tsx', - ]); -}); + await expectStagedSetup(projectDirectory, 'ts', packageJson.scripts); + expect(packageJson.packageManager).toMatch(/^pnpm@/u); + expect(appPackage.dependencies?.['@repo/ui']).toBe('workspace:^'); + await expectFiles(projectDirectory, [ + 'pnpm-workspace.yaml', + template === 'nx' ? 'nx.json' : 'turbo.json', + 'apps/web/src/index.tsx', + 'packages/ui/src/button.tsx', + ]); + }, +); -test('configures Turborepo when Git initialization is disabled', async () => { - const projectDirectory = await createProject('turborepo', { - args: ['--no-git'], - }); - const packageJson = await readProjectPackage(projectDirectory); +test.each(['turborepo', 'nx'])( + 'configures %s when Git initialization is disabled', + async (template) => { + const projectDirectory = await createProject(template, { + args: ['--no-git'], + }); + const packageJson = await readProjectPackage(projectDirectory); - expect(packageJson.packageManager).toMatch(/^pnpm@/u); - await expectNoStagedSetup(projectDirectory, 'ts', packageJson.scripts); -}); + expect(packageJson.packageManager).toMatch(/^pnpm@/u); + await expectNoStagedSetup(projectDirectory, 'ts', packageJson.scripts); + }, +); diff --git a/website/docs/en/guide/quick-start.mdx b/website/docs/en/guide/quick-start.mdx index 0d5b02e1..197e1b3a 100644 --- a/website/docs/en/guide/quick-start.mdx +++ b/website/docs/en/guide/quick-start.mdx @@ -54,7 +54,7 @@ When creating a project, choose from the following templates provided by `create | Web application | Vanilla JavaScript, React, Preact, Vue, Lit, Svelte, Solid | | Library | Node.js, React, Vue, Svelte, Solid | | Documentation site | Single language, multilingual | -| Monorepo | Turborepo | +| Monorepo | Turborepo, Nx | All application and library templates are available in both JavaScript and TypeScript. @@ -102,7 +102,7 @@ Options: --package-name specify the package name --template-version specify the npm template version -Available templates: app-vanilla, app-vanilla-ts, app-react, app-react-ts, app-preact, app-preact-ts, app-vue, app-vue-ts, app-lit, app-lit-ts, app-svelte, app-svelte-ts, app-solid, app-solid-ts, lib-node, lib-node-ts, lib-react, lib-react-ts, lib-vue, lib-vue-ts, lib-svelte, lib-svelte-ts, lib-solid, lib-solid-ts, doc, doc-i18n, turborepo +Available templates: app-vanilla, app-vanilla-ts, app-react, app-react-ts, app-preact, app-preact-ts, app-vue, app-vue-ts, app-lit, app-lit-ts, app-svelte, app-svelte-ts, app-solid, app-solid-ts, lib-node, lib-node-ts, lib-react, lib-react-ts, lib-vue, lib-vue-ts, lib-svelte, lib-svelte-ts, lib-solid, lib-solid-ts, doc, doc-i18n, turborepo, nx ``` ## Migrate an existing project diff --git a/website/docs/zh/guide/quick-start.mdx b/website/docs/zh/guide/quick-start.mdx index 9e6eb8be..65053493 100644 --- a/website/docs/zh/guide/quick-start.mdx +++ b/website/docs/zh/guide/quick-start.mdx @@ -54,7 +54,7 @@ Rstack CLI 要求 Node.js 20.19.0+ 或 22.12.0+。 | Web 应用 | 原生 JavaScript、React、Preact、Vue、Lit、Svelte、Solid | | 库 | Node.js、React、Vue、Svelte、Solid | | 文档站点 | 单语言、多语言 | -| Monorepo | Turborepo | +| Monorepo | Turborepo, Nx | 所有应用和库模板均提供 JavaScript 和 TypeScript 版本。 @@ -102,7 +102,7 @@ Options: --package-name specify the package name --template-version specify the npm template version -Available templates: app-vanilla, app-vanilla-ts, app-react, app-react-ts, app-preact, app-preact-ts, app-vue, app-vue-ts, app-lit, app-lit-ts, app-svelte, app-svelte-ts, app-solid, app-solid-ts, lib-node, lib-node-ts, lib-react, lib-react-ts, lib-vue, lib-vue-ts, lib-svelte, lib-svelte-ts, lib-solid, lib-solid-ts, doc, doc-i18n, turborepo +Available templates: app-vanilla, app-vanilla-ts, app-react, app-react-ts, app-preact, app-preact-ts, app-vue, app-vue-ts, app-lit, app-lit-ts, app-svelte, app-svelte-ts, app-solid, app-solid-ts, lib-node, lib-node-ts, lib-react, lib-react-ts, lib-vue, lib-vue-ts, lib-svelte, lib-svelte-ts, lib-solid, lib-solid-ts, doc, doc-i18n, turborepo, nx ``` ## 迁移现有项目 \{#migrate-an-existing-project} From 37f8d8f4af07be69837ac96d5704df9a1f63998f Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 16 Oct 2026 17:51:42 +0800 Subject: [PATCH 2/3] refactor(create-rstack): simplify Nx app configuration --- packages/create-rstack/template-nx/apps/web/rstack.config.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/create-rstack/template-nx/apps/web/rstack.config.ts b/packages/create-rstack/template-nx/apps/web/rstack.config.ts index 778e61cf..972b7f4c 100644 --- a/packages/create-rstack/template-nx/apps/web/rstack.config.ts +++ b/packages/create-rstack/template-nx/apps/web/rstack.config.ts @@ -5,8 +5,6 @@ define.app(async () => { const { pluginReact } = await import('@rsbuild/plugin-react'); return { plugins: [pluginReact()], - html: { title: 'Web | Rstack' }, - server: { port: 3000 }, }; }); From a0b886bc47f2d8ae8010228c40d67e711ffb6f20 Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 16 Oct 2026 17:54:51 +0800 Subject: [PATCH 3/3] refactor(create-rstack): remove redundant Nx template settings --- packages/create-rstack/template-nx/nx.json | 5 +---- packages/create-rstack/template-nx/rstack.config.ts | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/create-rstack/template-nx/nx.json b/packages/create-rstack/template-nx/nx.json index 968be05b..3ccb7eda 100644 --- a/packages/create-rstack/template-nx/nx.json +++ b/packages/create-rstack/template-nx/nx.json @@ -12,18 +12,15 @@ "build": { "dependsOn": ["^build"], "cache": true, - "inputs": ["default", "^default"], "outputs": ["{projectRoot}/dist"] }, "dev": { "dependsOn": ["^build"], - "cache": false, "continuous": true }, "test": { "dependsOn": ["^build"], - "cache": true, - "inputs": ["default", "^default"] + "cache": true } } } diff --git a/packages/create-rstack/template-nx/rstack.config.ts b/packages/create-rstack/template-nx/rstack.config.ts index 919d271d..930096fa 100644 --- a/packages/create-rstack/template-nx/rstack.config.ts +++ b/packages/create-rstack/template-nx/rstack.config.ts @@ -26,5 +26,4 @@ define.lint(({ js, ts, reactPlugin, reactHooksPlugin, rstestPlugin }) => [ define.fmt({ singleQuote: true, - ignorePatterns: ['**/dist/**', '**/.nx/**'], });