From adabbf08e21e362e68a2bfcdd70e07c69a5b38a3 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 5 Jun 2026 16:39:57 -0600 Subject: [PATCH] Track generated route tree in scaffolds --- .changeset/track-route-tree.md | 5 +++ packages/create/src/create-app.ts | 33 ++++++++++++++- .../react/project/base/_dot_gitignore | 1 - .../react/project/base/package.json | 1 + .../react/project/base/tsr.config.json | 3 ++ .../frameworks/react/project/packages.json | 3 ++ .../solid/project/base/_dot_gitignore | 1 - .../solid/project/base/package.json | 1 + .../solid/project/base/tsr.config.json | 3 ++ .../frameworks/solid/project/packages.json | 3 ++ packages/create/tests/create-app.test.ts | 42 +++++++++++++++++-- .../create/tests/framework-template.test.ts | 23 +++++++++- 12 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 .changeset/track-route-tree.md create mode 100644 packages/create/src/frameworks/react/project/base/tsr.config.json create mode 100644 packages/create/src/frameworks/solid/project/base/tsr.config.json diff --git a/.changeset/track-route-tree.md b/.changeset/track-route-tree.md new file mode 100644 index 00000000..a39ffffa --- /dev/null +++ b/.changeset/track-route-tree.md @@ -0,0 +1,5 @@ +--- +"@tanstack/create": patch +--- + +Keep the generated route tree tracked in new React and Solid apps and run route generation once during scaffold. diff --git a/packages/create/src/create-app.ts b/packages/create/src/create-app.ts index f2371c9b..46add011 100644 --- a/packages/create/src/create-app.ts +++ b/packages/create/src/create-app.ts @@ -31,7 +31,7 @@ function stripExamplesFromOptions(options: Options): Options { !isDemoFilePath(route.path) && !(route.url && route.url.startsWith('/demo')), ) - + const filteredIntegrations = (addOn.integrations || []).filter( (integration) => !isDemoFilePath(integration.path) ) @@ -277,6 +277,37 @@ async function runCommandsAndInstallDependencies( await installShadcnComponents(environment, options.targetDir, options) await setupIntent(environment, options.targetDir, options) + + if (shouldGenerateRoutes(options)) { + s.start(`Generating route tree...`) + const command = getPackageManagerScriptCommand(options.packageManager, [ + 'generate-routes', + ]) + const cmd = formatCommand(command) + environment.startStep({ + id: 'generate-routes', + type: 'command', + message: cmd, + }) + await environment.execute( + command.command, + command.args, + options.targetDir, + { + inherit: true, + }, + ) + environment.finishStep('generate-routes', 'Route tree generated') + s.stop(`Route tree generated`) + } +} + +function shouldGenerateRoutes(options: Options) { + return ( + options.install !== false && + options.mode === 'file-router' && + (options.framework.id === 'react' || options.framework.id === 'solid') + ) } async function seedEnvValues(environment: Environment, options: Options) { diff --git a/packages/create/src/frameworks/react/project/base/_dot_gitignore b/packages/create/src/frameworks/react/project/base/_dot_gitignore index a0789a6e..8b25bb54 100644 --- a/packages/create/src/frameworks/react/project/base/_dot_gitignore +++ b/packages/create/src/frameworks/react/project/base/_dot_gitignore @@ -6,7 +6,6 @@ dist-ssr .env .nitro .tanstack -src/routeTree.gen.ts .wrangler .output .vinxi diff --git a/packages/create/src/frameworks/react/project/base/package.json b/packages/create/src/frameworks/react/project/base/package.json index 8ac24f46..139568dd 100644 --- a/packages/create/src/frameworks/react/project/base/package.json +++ b/packages/create/src/frameworks/react/project/base/package.json @@ -7,6 +7,7 @@ }, "scripts": { "dev": "vite dev --port 3000", + "generate-routes": "tsr generate", "build": "vite build", "preview": "vite preview", "test": "vitest run" diff --git a/packages/create/src/frameworks/react/project/base/tsr.config.json b/packages/create/src/frameworks/react/project/base/tsr.config.json new file mode 100644 index 00000000..8b6b6edd --- /dev/null +++ b/packages/create/src/frameworks/react/project/base/tsr.config.json @@ -0,0 +1,3 @@ +{ + "target": "react" +} diff --git a/packages/create/src/frameworks/react/project/packages.json b/packages/create/src/frameworks/react/project/packages.json index 5a870b90..2bc6816a 100644 --- a/packages/create/src/frameworks/react/project/packages.json +++ b/packages/create/src/frameworks/react/project/packages.json @@ -15,6 +15,9 @@ } }, "file-router": { + "devDependencies": { + "@tanstack/router-cli": "^1.132.0" + }, "dependencies": { "@tanstack/router-plugin": "^1.132.0" } diff --git a/packages/create/src/frameworks/solid/project/base/_dot_gitignore b/packages/create/src/frameworks/solid/project/base/_dot_gitignore index 65dfcdc1..e2395bd8 100644 --- a/packages/create/src/frameworks/solid/project/base/_dot_gitignore +++ b/packages/create/src/frameworks/solid/project/base/_dot_gitignore @@ -6,7 +6,6 @@ dist-ssr .env .nitro .tanstack -src/routeTree.gen.ts .wrangler .output .vinxi diff --git a/packages/create/src/frameworks/solid/project/base/package.json b/packages/create/src/frameworks/solid/project/base/package.json index ab417b37..5e653255 100644 --- a/packages/create/src/frameworks/solid/project/base/package.json +++ b/packages/create/src/frameworks/solid/project/base/package.json @@ -4,6 +4,7 @@ "type": "module", "scripts": { "dev": "vite dev --port 3000", + "generate-routes": "tsr generate", "build": "vite build", "start": "node .output/server/index.mjs", "preview": "vite preview", diff --git a/packages/create/src/frameworks/solid/project/base/tsr.config.json b/packages/create/src/frameworks/solid/project/base/tsr.config.json new file mode 100644 index 00000000..078264aa --- /dev/null +++ b/packages/create/src/frameworks/solid/project/base/tsr.config.json @@ -0,0 +1,3 @@ +{ + "target": "solid" +} diff --git a/packages/create/src/frameworks/solid/project/packages.json b/packages/create/src/frameworks/solid/project/packages.json index ddea17a7..603bd779 100644 --- a/packages/create/src/frameworks/solid/project/packages.json +++ b/packages/create/src/frameworks/solid/project/packages.json @@ -11,6 +11,9 @@ } }, "file-router": { + "devDependencies": { + "@tanstack/router-cli": "^1.133.21" + }, "dependencies": { "@tanstack/router-plugin": "^1.133.21" } diff --git a/packages/create/tests/create-app.test.ts b/packages/create/tests/create-app.test.ts index e0182183..fe2b481d 100644 --- a/packages/create/tests/create-app.test.ts +++ b/packages/create/tests/create-app.test.ts @@ -4,8 +4,7 @@ import { resolve } from 'node:path' import { createApp } from '../src/create-app.js' import { createMemoryEnvironment } from '../src/environment.js' -import { FILE_ROUTER } from '../src/constants.js' -import { AddOn, Options } from '../src/types.js' +import type { AddOn, Options } from '../src/types.js' const simpleOptions = { projectName: 'test', @@ -43,7 +42,7 @@ const simpleOptions = { packageManager: 'pnpm', typescript: true, tailwind: true, - mode: FILE_ROUTER, + mode: 'file-router', variableValues: {}, } as unknown as Options @@ -88,6 +87,43 @@ describe('createApp', () => { expect(output.commands.some(({ command }) => command === 'echo')).toBe(true) }) + it.each(['react', 'solid'])( + 'generates routes for %s file-router apps after install', + async (frameworkId) => { + const { environment, output } = createMemoryEnvironment() + await createApp(environment, { + ...simpleOptions, + framework: { + ...simpleOptions.framework, + id: frameworkId, + }, + install: true, + } as Options) + + expect(output.commands).toContainEqual({ + command: 'pnpm', + args: ['generate-routes'], + }) + }, + ) + + it('skips route generation when dependency install is skipped', async () => { + const { environment, output } = createMemoryEnvironment() + await createApp(environment, { + ...simpleOptions, + framework: { + ...simpleOptions.framework, + id: 'react', + }, + install: false, + }) + + expect(output.commands).not.toContainEqual({ + command: 'pnpm', + args: ['generate-routes'], + }) + }) + it('should create an app - with a add-on', async () => { const { environment, output } = createMemoryEnvironment() await createApp(environment, { diff --git a/packages/create/tests/framework-template.test.ts b/packages/create/tests/framework-template.test.ts index e09a9ca0..3f79f1e7 100644 --- a/packages/create/tests/framework-template.test.ts +++ b/packages/create/tests/framework-template.test.ts @@ -7,9 +7,28 @@ describe('framework templates', () => { it.each([ ['React', createReactFrameworkDefinition], ['Solid', createSolidFrameworkDefinition], - ])('%s gitignore excludes the generated route tree', (_, createDefinition) => { + ])( + '%s gitignore does not exclude the generated route tree', + (_, createDefinition) => { + const framework = createDefinition() + + expect(framework.base._dot_gitignore).not.toContain( + 'src/routeTree.gen.ts', + ) + }, + ) + + it.each([ + ['React', createReactFrameworkDefinition], + ['Solid', createSolidFrameworkDefinition], + ])('%s includes route generation tooling', (_, createDefinition) => { const framework = createDefinition() - expect(framework.base._dot_gitignore).toContain('src/routeTree.gen.ts') + expect(framework.base['package.json']).toContain( + '"generate-routes": "tsr generate"', + ) + expect( + framework.optionalPackages['file-router'].devDependencies, + ).toHaveProperty('@tanstack/router-cli') }) })