From 391f6535ad109409705185255ad74310706a0ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Curley?= Date: Mon, 21 Sep 2026 12:37:18 +0100 Subject: [PATCH 1/2] feat(cli): add interactive router-only prompt Prompt 'Use Tanstack Router without Start?' in interactive mode when router-only intent is not already explicit via --router-only, a legacy template, or --template/--starter. Answering yes sets cliOptions.routerOnly so template, deployment, add-on, and example prompts are skipped. --- packages/cli/src/options.ts | 11 ++++++++++- packages/cli/src/ui-prompts.ts | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index f09b55a2..5b12ed2b 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -21,6 +21,7 @@ import { selectGit, selectInstall, selectPackageManager, + selectRouterOnly, selectTemplate, selectToolchain, } from './ui-prompts.js' @@ -95,9 +96,17 @@ export async function promptForCreateOptions( ['file-router', 'typescript', 'tsx', 'javascript', 'js', 'jsx'].includes( template, ) + const hasTemplateIntent = !!cliOptions.template || !!cliOptions.starter const routerOnly = !!cliOptions.routerOnly || - (isLegacyTemplate ? template !== 'file-router' : false) + (isLegacyTemplate ? template !== 'file-router' : false) || + (cliOptions.routerOnly === undefined && + !isLegacyTemplate && + !hasTemplateIntent && + (await selectRouterOnly())) + if (routerOnly) { + cliOptions.routerOnly = true + } if (!cliOptions.starter) { if (cliOptions.template && !isLegacyTemplate) { diff --git a/packages/cli/src/ui-prompts.ts b/packages/cli/src/ui-prompts.ts index 396adba8..27130069 100644 --- a/packages/cli/src/ui-prompts.ts +++ b/packages/cli/src/ui-prompts.ts @@ -53,6 +53,18 @@ export async function selectFramework( return framework } +export async function selectRouterOnly(): Promise { + const routerOnly = await confirm({ + message: 'Use Tanstack Router without Start?', + initialValue: false, + }) + if (isCancel(routerOnly)) { + cancel('Operation cancelled.') + process.exit(0) + } + return routerOnly +} + export async function selectInstall(): Promise { const install = await confirm({ message: 'Would you like to install dependencies now?', From 18b1dd1eb9971836e56e20d0040bc5e9c19d8911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Curley?= Date: Mon, 21 Sep 2026 12:45:46 +0100 Subject: [PATCH 2/2] feat(cli): add --router-and-start flag Strict inverse of --router-only: explicitly opts into TanStack Start and suppresses the interactive router-only prompt. Errors when combined with --router-only and ignores legacy router-only templates in favor of Start. --- docs/cli-reference.md | 1 + packages/cli/src/cli.ts | 28 ++++++++++++++++++++++++++++ packages/cli/src/types.ts | 1 + 3 files changed, 30 insertions(+) diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 259ae629..4d9988cb 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -19,6 +19,7 @@ tanstack create [project-name] [options] | `--package-manager ` | `npm`, `pnpm`, `yarn`, `bun`, `deno` | | `--framework ` | `React`, `Solid` | | `--router-only` | Create file-based Router-only app without TanStack Start (add-ons/deployment/template disabled) | +| `--router-and-start` | Use TanStack Start explicitly (skips the interactive router-only prompt) | | `--toolchain ` | Toolchain add-on (use `--list-add-ons` to see options) | | `--deployment ` | Deployment add-on (use `--list-add-ons` to see options) | | `--examples` / `--no-examples` | Include or exclude demo/example pages | diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index ecd8bb4e..8559a2f4 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -193,6 +193,7 @@ function getCreateTelemetryProperties(projectName: string, options: CliOptions) package_manager: options.packageManager, project_name_provided: Boolean(projectName), router_only: !!options.routerOnly, + router_and_start: !!options.routerAndStart, target_dir_flag: Boolean(options.targetDir), toolchain: typeof options.toolchain === 'string' ? sanitizeId(options.toolchain) : undefined, @@ -229,6 +230,7 @@ function getResolvedCreateTelemetryProperties( intent: finalOptions.intent, package_manager: finalOptions.packageManager, router_only: !!cliOptions.routerOnly, + router_and_start: !!cliOptions.routerAndStart, toolchain: toolchain ? sanitizeId(toolchain.id) : undefined, } } @@ -810,6 +812,28 @@ export function cli({ ...options, } as CliOptions + if (cliOptions.routerAndStart) { + if (cliOptions.routerOnly) { + throw new Error( + 'Cannot combine --router-only with --router-and-start.', + ) + } + if ( + cliOptions.template && + ['typescript', 'tsx', 'javascript', 'js', 'jsx'].includes( + cliOptions.template.toLowerCase(), + ) + ) { + console.warn( + chalk.yellow( + 'Ignoring --template in favor of --router-and-start (TanStack Start).', + ), + ) + cliOptions.template = undefined + } + cliOptions.routerOnly = false + } + if (defaultRouterOnly && cliOptions.routerOnly === undefined) { cliOptions.routerOnly = true } @@ -992,6 +1016,10 @@ export function cli({ '--router-only', 'Use router-only compatibility mode (file-based routing without TanStack Start)', ) + .option( + '--router-and-start', + 'Use TanStack Start explicitly (skips the interactive router-only prompt)', + ) .option( '--blank', 'Create a minimal one-route app without default starter UI, Tailwind, devtools, or tests', diff --git a/packages/cli/src/types.ts b/packages/cli/src/types.ts index 235746ae..cdf821fa 100644 --- a/packages/cli/src/types.ts +++ b/packages/cli/src/types.ts @@ -24,6 +24,7 @@ export interface CliOptions { addOnConfig?: string force?: boolean routerOnly?: boolean + routerAndStart?: boolean blank?: boolean template?: string tailwind?: boolean