From c10d8fb11d112a93b7a6200bc2446e9fba2f8200 Mon Sep 17 00:00:00 2001 From: Eduardo Kegler Date: Fri, 30 Oct 2026 20:04:49 -0300 Subject: [PATCH 1/3] fix(create): generate Start route trees with vite build --- .changeset/start-generate-routes-vite-build.md | 5 +++++ packages/cli/tests-e2e/blank-smoke.spec.ts | 3 +-- packages/create/src/edge-package-json.ts | 5 +++++ packages/create/src/package-json.ts | 5 +++++ packages/create/tests/blank-preset.test.ts | 2 -- packages/create/tests/bundlers.test.ts | 14 +++++++++++++- 6 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 .changeset/start-generate-routes-vite-build.md diff --git a/.changeset/start-generate-routes-vite-build.md b/.changeset/start-generate-routes-vite-build.md new file mode 100644 index 00000000..36f7f19b --- /dev/null +++ b/.changeset/start-generate-routes-vite-build.md @@ -0,0 +1,5 @@ +--- +"@tanstack/create": patch +--- + +Generate the route tree of new Start apps on Vite with `vite build` instead of `tsr generate`, which leaves out the Start `Register` block. diff --git a/packages/cli/tests-e2e/blank-smoke.spec.ts b/packages/cli/tests-e2e/blank-smoke.spec.ts index e3f5635a..01fad0d8 100644 --- a/packages/cli/tests-e2e/blank-smoke.spec.ts +++ b/packages/cli/tests-e2e/blank-smoke.spec.ts @@ -32,7 +32,6 @@ const expectedDependencies = [ const expectedDevDependencies = [ '@cloudflare/vite-plugin', - '@tanstack/router-cli', '@types/node', '@types/react', '@types/react-dom', @@ -208,7 +207,7 @@ test('@blocking creates a production-valid blank React app', async ({ ) expect(packageJSON.scripts).toEqual({ dev: 'vite dev --port 3000', - 'generate-routes': 'tsr generate', + 'generate-routes': 'vite build', build: 'vite build', preview: 'vite preview', deploy: 'npm run build && wrangler deploy', diff --git a/packages/create/src/edge-package-json.ts b/packages/create/src/edge-package-json.ts index 5d4585c8..42f85076 100644 --- a/packages/create/src/edge-package-json.ts +++ b/packages/create/src/edge-package-json.ts @@ -230,6 +230,11 @@ export function createPackageJSON(options: Options) { devDependencies?.['@tanstack/router-plugin'] ?? 'latest', } } + } else if (scripts?.['generate-routes'] === 'tsr generate') { + // `tsr generate` drops the Register block that the Start Vite plugin + // writes into routeTree.gen.ts, so Start apps generate routes with a build. + packageJSON.scripts = { ...scripts, 'generate-routes': 'vite build' } + delete devDependencies?.['@tanstack/router-cli'] } packageJSON.dependencies = sortObject( diff --git a/packages/create/src/package-json.ts b/packages/create/src/package-json.ts index 8a0e0d25..bd46681b 100644 --- a/packages/create/src/package-json.ts +++ b/packages/create/src/package-json.ts @@ -179,6 +179,11 @@ export function createPackageJSON(options: Options) { packageJSON.devDependencies?.['@tanstack/router-plugin'] ?? 'latest', } } + } else if (packageJSON.scripts?.['generate-routes'] === 'tsr generate') { + // `tsr generate` drops the Register block that the Start Vite plugin + // writes into routeTree.gen.ts, so Start apps generate routes with a build. + packageJSON.scripts['generate-routes'] = 'vite build' + delete packageJSON.devDependencies?.['@tanstack/router-cli'] } packageJSON.dependencies = sortObject( diff --git a/packages/create/tests/blank-preset.test.ts b/packages/create/tests/blank-preset.test.ts index 22909adf..c6ca05f9 100644 --- a/packages/create/tests/blank-preset.test.ts +++ b/packages/create/tests/blank-preset.test.ts @@ -36,7 +36,6 @@ const BLANK_DEPENDENCY_ALLOWLIST = [ ] const BLANK_DEV_DEPENDENCY_ALLOWLIST = [ - '@tanstack/router-cli', '@types/node', '@types/react', '@types/react-dom', @@ -169,7 +168,6 @@ describe('blank project preset', () => { 'solid-js', ]) expect(Object.keys(packageJSON.devDependencies).sort()).toEqual([ - '@tanstack/router-cli', 'typescript', 'vite', 'vite-plugin-solid', diff --git a/packages/create/tests/bundlers.test.ts b/packages/create/tests/bundlers.test.ts index fbcf2aee..94191661 100644 --- a/packages/create/tests/bundlers.test.ts +++ b/packages/create/tests/bundlers.test.ts @@ -206,7 +206,11 @@ describe('bundler project generation', () => { expect(packageJSON.scripts.build).toBe(`${bundler} build`) expect(packageJSON.scripts.preview).toBe(`${bundler} preview`) expect(packageJSON.scripts['generate-routes']).toBe( - bundler === 'vite' ? 'tsr generate' : 'rsbuild build', + bundler === 'rsbuild' + ? 'rsbuild build' + : routerOnly + ? 'tsr generate' + : 'vite build', ) if (bundler === 'vite') { @@ -251,8 +255,16 @@ describe('bundler project generation', () => { expect(packageJSON.scripts).not.toHaveProperty('start') expect(packageJSON.dependencies).not.toHaveProperty('srvx') expect(files[configFile]).toContain('@tanstack/router-plugin') + if (bundler === 'vite') { + expect(packageJSON.devDependencies).toHaveProperty( + '@tanstack/router-cli', + ) + } } else { expect(packageJSON.dependencies).toHaveProperty(startPackage) + expect(packageJSON.devDependencies).not.toHaveProperty( + '@tanstack/router-cli', + ) if (bundler === 'rsbuild') { expect(packageJSON.scripts.start).toContain('srvx') expect(packageJSON.dependencies).toHaveProperty('srvx') From 4aef65676aa0e29750f2fdb9beaf1c2e81953da0 Mon Sep 17 00:00:00 2001 From: Eduardo Kegler Date: Fri, 30 Oct 2026 20:26:17 -0300 Subject: [PATCH 2/3] refactor(create): pick the route generator from the framework packages --- packages/create/src/edge-package-json.ts | 11 ++++------- .../create/src/frameworks/react/project/packages.json | 7 +++++-- .../create/src/frameworks/solid/project/packages.json | 7 +++++-- packages/create/src/package-json.ts | 11 ++++------- packages/create/tests/framework-template.test.ts | 11 +---------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/packages/create/src/edge-package-json.ts b/packages/create/src/edge-package-json.ts index 42f85076..a0f2f6f8 100644 --- a/packages/create/src/edge-package-json.ts +++ b/packages/create/src/edge-package-json.ts @@ -137,8 +137,10 @@ export function createPackageJSON(options: Options) { ? options.framework.optionalPackages.bundlerTailwindcss?.[bundler] : undefined, options.mode ? options.framework.optionalPackages[options.mode] : undefined, - options.mode === 'file-router' - ? options.framework.optionalPackages.bundlerFileRouter?.[bundler] + options.mode === 'file-router' && options.routerOnly + ? options.framework.optionalPackages.bundlerRouterOnlyFileRouter?.[ + bundler + ] : undefined, ] for (const addition of additions.filter( @@ -230,11 +232,6 @@ export function createPackageJSON(options: Options) { devDependencies?.['@tanstack/router-plugin'] ?? 'latest', } } - } else if (scripts?.['generate-routes'] === 'tsr generate') { - // `tsr generate` drops the Register block that the Start Vite plugin - // writes into routeTree.gen.ts, so Start apps generate routes with a build. - packageJSON.scripts = { ...scripts, 'generate-routes': 'vite build' } - delete devDependencies?.['@tanstack/router-cli'] } packageJSON.dependencies = sortObject( diff --git a/packages/create/src/frameworks/react/project/packages.json b/packages/create/src/frameworks/react/project/packages.json index 1675fbb1..6680ccf8 100644 --- a/packages/create/src/frameworks/react/project/packages.json +++ b/packages/create/src/frameworks/react/project/packages.json @@ -27,7 +27,7 @@ "vite": { "scripts": { "dev": "vite dev --port 3000", - "generate-routes": "tsr generate", + "generate-routes": "vite build", "build": "vite build", "preview": "vite preview" }, @@ -75,8 +75,11 @@ } } }, - "bundlerFileRouter": { + "bundlerRouterOnlyFileRouter": { "vite": { + "scripts": { + "generate-routes": "tsr generate" + }, "devDependencies": { "@tanstack/router-cli": "^1.132.0" } diff --git a/packages/create/src/frameworks/solid/project/packages.json b/packages/create/src/frameworks/solid/project/packages.json index 85bf6018..f1fe3a0e 100644 --- a/packages/create/src/frameworks/solid/project/packages.json +++ b/packages/create/src/frameworks/solid/project/packages.json @@ -18,7 +18,7 @@ "vite": { "scripts": { "dev": "vite dev --port 3000", - "generate-routes": "tsr generate", + "generate-routes": "vite build", "build": "vite build", "start": "node .output/server/index.mjs", "preview": "vite preview" @@ -68,8 +68,11 @@ } } }, - "bundlerFileRouter": { + "bundlerRouterOnlyFileRouter": { "vite": { + "scripts": { + "generate-routes": "tsr generate" + }, "devDependencies": { "@tanstack/router-cli": "^1.133.21" } diff --git a/packages/create/src/package-json.ts b/packages/create/src/package-json.ts index bd46681b..20bc571c 100644 --- a/packages/create/src/package-json.ts +++ b/packages/create/src/package-json.ts @@ -97,8 +97,10 @@ export function createPackageJSON(options: Options) { ? options.framework.optionalPackages.bundlerTailwindcss?.[bundler] : undefined, options.mode ? options.framework.optionalPackages[options.mode] : undefined, - options.mode === 'file-router' - ? options.framework.optionalPackages.bundlerFileRouter?.[bundler] + options.mode === 'file-router' && options.routerOnly + ? options.framework.optionalPackages.bundlerRouterOnlyFileRouter?.[ + bundler + ] : undefined, ] for (const addition of additions.filter(Boolean)) { @@ -179,11 +181,6 @@ export function createPackageJSON(options: Options) { packageJSON.devDependencies?.['@tanstack/router-plugin'] ?? 'latest', } } - } else if (packageJSON.scripts?.['generate-routes'] === 'tsr generate') { - // `tsr generate` drops the Register block that the Start Vite plugin - // writes into routeTree.gen.ts, so Start apps generate routes with a build. - packageJSON.scripts['generate-routes'] = 'vite build' - delete packageJSON.devDependencies?.['@tanstack/router-cli'] } packageJSON.dependencies = sortObject( diff --git a/packages/create/tests/framework-template.test.ts b/packages/create/tests/framework-template.test.ts index 97432925..505df2c8 100644 --- a/packages/create/tests/framework-template.test.ts +++ b/packages/create/tests/framework-template.test.ts @@ -21,18 +21,9 @@ describe('framework templates', () => { it.each([ ['React', createReactFrameworkDefinition], ['Solid', createSolidFrameworkDefinition], - ])('%s includes route generation tooling', (_, createDefinition) => { + ])('%s defaults to Vite and offers Rsbuild', (_, createDefinition) => { const framework = createDefinition() - expect( - framework.optionalPackages.bundlers.vite.scripts['generate-routes'], - ).toBe('tsr generate') - expect( - framework.optionalPackages.bundlers.rsbuild.scripts['generate-routes'], - ).toBe('rsbuild build') - expect( - framework.optionalPackages.bundlerFileRouter.vite.devDependencies, - ).toHaveProperty('@tanstack/router-cli') expect(framework.defaultBundler).toBe('vite') expect(framework.bundlers?.map((bundler) => bundler.id)).toEqual([ 'vite', From bb2a9f5225ad1966a226dfe95ef4c2f7fa229e9d Mon Sep 17 00:00:00 2001 From: Eduardo Kegler Date: Fri, 30 Oct 2026 20:37:22 -0300 Subject: [PATCH 3/3] fix(create): keep applying bundlerFileRouter to file-router apps --- packages/create/src/edge-package-json.ts | 3 ++ packages/create/src/package-json.ts | 3 ++ packages/create/tests/package-json.test.ts | 38 ++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/packages/create/src/edge-package-json.ts b/packages/create/src/edge-package-json.ts index a0f2f6f8..6929cc2d 100644 --- a/packages/create/src/edge-package-json.ts +++ b/packages/create/src/edge-package-json.ts @@ -137,6 +137,9 @@ export function createPackageJSON(options: Options) { ? options.framework.optionalPackages.bundlerTailwindcss?.[bundler] : undefined, options.mode ? options.framework.optionalPackages[options.mode] : undefined, + options.mode === 'file-router' + ? options.framework.optionalPackages.bundlerFileRouter?.[bundler] + : undefined, options.mode === 'file-router' && options.routerOnly ? options.framework.optionalPackages.bundlerRouterOnlyFileRouter?.[ bundler diff --git a/packages/create/src/package-json.ts b/packages/create/src/package-json.ts index 20bc571c..fde5f7fd 100644 --- a/packages/create/src/package-json.ts +++ b/packages/create/src/package-json.ts @@ -97,6 +97,9 @@ export function createPackageJSON(options: Options) { ? options.framework.optionalPackages.bundlerTailwindcss?.[bundler] : undefined, options.mode ? options.framework.optionalPackages[options.mode] : undefined, + options.mode === 'file-router' + ? options.framework.optionalPackages.bundlerFileRouter?.[bundler] + : undefined, options.mode === 'file-router' && options.routerOnly ? options.framework.optionalPackages.bundlerRouterOnlyFileRouter?.[ bundler diff --git a/packages/create/tests/package-json.test.ts b/packages/create/tests/package-json.test.ts index e2d96a06..941cdbed 100644 --- a/packages/create/tests/package-json.test.ts +++ b/packages/create/tests/package-json.test.ts @@ -65,6 +65,44 @@ describe('createPackageJSON', () => { }, ) + it.each([false, true])( + 'applies a custom framework bundlerFileRouter to file-router apps (routerOnly=%s)', + (routerOnly) => { + const framework = { + id: 'custom', + basePackageJSON: {}, + optionalPackages: { + bundlerFileRouter: { + vite: { + scripts: { routes: 'custom-routes' }, + devDependencies: { 'custom-routes': '^1.0.0' }, + }, + }, + }, + } as unknown as Framework + const options = { + chosenAddOns: [], + addOnOptions: {}, + mode: 'file-router', + routerOnly, + typescript: true, + tailwind: false, + projectName: 'test', + packageManager: 'pnpm', + framework, + } as unknown as Options + + const packageJSON = createPackageJSON(options) + + expect(packageJSON.scripts).toHaveProperty('routes', 'custom-routes') + expect(packageJSON.devDependencies).toHaveProperty( + 'custom-routes', + '^1.0.0', + ) + expect(createEdgePackageJSON(options)).toEqual(packageJSON) + }, + ) + it('should create a package.json', () => { const packageJSON = createPackageJSON({ chosenAddOns: [