Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .agents/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ node ../cli/packages/cli/dist/index.js create my-app
| Add-on | Plugin that extends apps (auth, DB, etc) | `--add-ons` |
| Template | Reusable project template | `--template` |
| Framework | React or Solid | `--framework` |
| Bundler | Vite (default) or Rsbuild | `--bundler` |

## CLI Commands

Expand All @@ -70,6 +71,7 @@ node ../cli/packages/cli/dist/index.js create my-app
| -------------------- | ------------------------------------------------------- |
| `--add-ons <ids>` | Comma-separated add-on IDs |
| `--framework <name>` | React or Solid |
| `--bundler <name>` | Vite (default) or Rsbuild |
| `--toolchain <id>` | Toolchain (use `--list-add-ons` to see options) |
| `--deployment <id>` | Deployment target (use `--list-add-ons` to see options) |
| `--template <url-or-id>` | Use template URL/path or built-in ID |
Expand All @@ -86,6 +88,7 @@ node ../cli/packages/cli/dist/index.js create my-app
| `projectName` | string | Project name |
| `typescript` | boolean | Always true (TanStack Start requires TS) |
| `tailwind` | boolean | False for blank unless an add-on requires it |
| `bundler` | string | Resolved bundler (`vite` or `rsbuild`) |
| `blank` | boolean | True when using the blank project preset |
| `fileRouter` | boolean | Always true |
| `addOnEnabled` | object | `{ [id]: boolean }` |
Expand Down Expand Up @@ -131,7 +134,7 @@ This project uses [TanStack Intent](https://github.com/TanStack/intent). Run `np
<!-- intent-skills:start -->
# Skill mappings — when working in these areas, load the linked skill file into context.
skills:
- task: "scaffold a new TanStack app with create command, framework, template, toolchain, deployment, or add-on flags"
- task: "scaffold a new TanStack app with create command, framework, bundler, template, toolchain, deployment, or add-on flags"
load: "packages/cli/skills/create-app-scaffold/SKILL.md"
- task: "add add-ons to an existing project using tanstack add"
load: "packages/cli/skills/add-addons-existing-app/SKILL.md"
Expand Down
7 changes: 7 additions & 0 deletions .changeset/green-builders-rise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@tanstack/create': minor
'@tanstack/cli': minor
---

Add first-class Rsbuild bundler support for React and Solid TanStack Start and
router-only scaffolds, including Tailwind and ESLint/Biome toolchains.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ npx @tanstack/cli create my-app

- **TanStack Start** - Full-stack SSR framework (default)
- **TanStack Router** - Type-safe routing (`--router-only` for SPA)
- **Vite or Rsbuild** - Choose the bundler for React and Solid projects
- **Add-ons** - Auth, database, deployment, monitoring, and more
- **CLI Introspection** - Agent-friendly discovery via JSON CLI output

Expand All @@ -59,6 +60,9 @@ npx @tanstack/cli create my-app --blank -y
# Create Router-only SPA (no SSR)
npx @tanstack/cli create my-app --router-only

# Create with Rsbuild
npx @tanstack/cli create my-app --bundler rsbuild -y

# With add-ons
npx @tanstack/cli create my-app --add-ons clerk,drizzle,tanstack-query

Expand All @@ -84,7 +88,7 @@ npx @tanstack/cli search-docs "loaders" --library router --framework react --jso

TanStack CLI sends anonymous usage telemetry by default.

- Sent: command usage, durations, selected framework/package manager/add-on ids, and coarse result metadata
- Sent: command usage, durations, selected framework/bundler/package manager/add-on ids, and coarse result metadata
- Never sent: project names, file paths, target directories, raw search queries, raw template URLs/paths, add-on config values, env vars, or raw error messages
- Disabled automatically in `CI`, or when `DO_NOT_TRACK=1` or `TANSTACK_CLI_TELEMETRY_DISABLED=1`

Expand Down
4 changes: 4 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tanstack create [project-name] [options]
| `--blank` | Create a minimal one-route Start project without default starter UI, examples, Tailwind, devtools, or a test stack |
| `--package-manager <pm>` | `npm`, `pnpm`, `yarn`, `bun`, `deno` |
| `--framework <name>` | `React`, `Solid` |
| `--bundler <name>` | `vite` (default), `rsbuild` |
| `--router-only` | Create file-based Router-only app without TanStack Start (add-ons/deployment/template disabled) |
| `--toolchain <id>` | Toolchain add-on (use `--list-add-ons` to see options) |
| `--deployment <id>` | Deployment add-on (use `--list-add-ons` to see options) |
Expand All @@ -41,6 +42,8 @@ tanstack create my-app --blank -y
tanstack create my-app --blank --deployment cloudflare -y
tanstack create my-app --add-ons clerk,drizzle,tanstack-query
tanstack create my-app --router-only --toolchain eslint --no-examples
tanstack create my-app --bundler rsbuild -y
tanstack create my-app --framework Solid --bundler rsbuild --router-only --blank --toolchain biome -y
tanstack create my-app --template https://example.com/template.json
tanstack create my-app --template ecommerce
tanstack create --list-add-ons --framework React --json
Expand Down Expand Up @@ -126,6 +129,7 @@ await create.createApp(environment, {
targetDir: '/app',
framework: framework!,
mode: 'file-router',
bundler: 'vite',
typescript: true,
tailwind: true,
packageManager: 'pnpm',
Expand Down
6 changes: 6 additions & 0 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ npx @tanstack/cli create my-app --add-ons tanstack-query,clerk,drizzle -y

# Router-only SPA (no SSR)
npx @tanstack/cli create my-app --router-only -y

# Rsbuild instead of the default Vite bundler
npx @tanstack/cli create my-app --bundler rsbuild -y

# Minimal router-only Rsbuild app
npx @tanstack/cli create my-app --bundler rsbuild --router-only --blank -y
```

Blank projects omit the default starter interface, examples, Tailwind,
Expand Down
18 changes: 16 additions & 2 deletions packages/cli/skills/create-app-scaffold/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
name: create-app-scaffold
description: >
Scaffold a TanStack app with tanstack create using --framework, --template,
Scaffold a TanStack app with tanstack create using --framework, --bundler, --template,
--toolchain, --deployment, --add-ons, --blank, and --router-only. Covers flag
compatibility, non-interactive defaults, and intent-preserving command
construction.
metadata:
type: core
library: tanstack-cli
library_version: "0.70.0"
library_version: "0.71.0"
---

# Create App Scaffold
Expand All @@ -28,6 +28,19 @@ npx @tanstack/cli create acme-web \

## Core Patterns

### Choose Vite or Rsbuild explicitly

Vite is the default. Use Rsbuild for React or Solid when the requested project
fits its initial compatibility surface.

```bash
npx @tanstack/cli create acme-web \
--framework react \
--bundler rsbuild \
--toolchain biome \
-y
```

### Build a deterministic non-interactive scaffold

```bash
Expand Down Expand Up @@ -162,5 +175,6 @@ See also: query-docs-library-metadata/SKILL.md § Common Mistakes

- [Create flag compatibility matrix](references/create-flag-compatibility-matrix.md)
- [Framework adapter options](references/framework-adapters.md)
- [Bundler options](references/bundlers.md)
- [Deployment provider options](references/deployment-providers.md)
- [Toolchain options](references/toolchains.md)
27 changes: 27 additions & 0 deletions packages/cli/skills/create-app-scaffold/references/bundlers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Bundler Options

Targets `@tanstack/cli` v0.71.0.

## Supported values

- `vite` (default)
- `rsbuild`

## Usage

```bash
npx @tanstack/cli create app --framework react --bundler vite -y
npx @tanstack/cli create app --framework solid --bundler rsbuild -y
```

Rsbuild supports full TanStack Start and router-only projects, including the
standard and `--blank` presets, built-in example pages, Tailwind, ESLint, and
Biome. It does not currently support templates, deployment adapters, or
catalog business/example add-ons. `tanstack add` is limited to ESLint/Biome in
Rsbuild projects.

Use the bundler-aware catalog view before constructing an Rsbuild command:

```bash
npx @tanstack/cli create --list-add-ons --bundler rsbuild --json
```
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Create Flag Compatibility Matrix

Targets `@tanstack/cli` v0.70.0.
Targets `@tanstack/cli` v0.71.0.

## Compatibility

| Flag | Works with normal create | Works with `--router-only` | Notes |
|---|---|---|---|
| `--framework` | yes | yes | Framework is still honored in both modes. |
| `--bundler` | yes | yes | `vite` is the default; `rsbuild` supports React and Solid. |
| `--toolchain` | yes | yes | Toolchain selection remains available. |
| `--add-ons` | yes | no | Ignored in router-only mode. |
| `--deployment` | yes | no | Ignored in router-only mode. |
Expand All @@ -15,14 +16,18 @@ Targets `@tanstack/cli` v0.70.0.
| `--blank` | yes | yes | Omits starter UI, examples, Tailwind, devtools, and test tooling unless an explicit integration requires them. Cannot be combined with a template, `--examples`, or `--tailwind`. |
| `--tailwind` / `--no-tailwind` | deprecated/ignored | deprecated/ignored | Standard scaffolds enable Tailwind; use `--blank` for the supported minimal preset. |

With `--bundler rsbuild`, only toolchain catalog entries are compatible.
Templates, deployments, and business/example add-ons are rejected. Built-in
demo pages controlled by `--examples` remain available.

Source: `packages/cli/src/command-line.ts:337`

## Recommended command construction order

1. Choose mode (`--router-only` or full scaffold).
2. If full scaffold, resolve add-ons and deployment first.
3. Add framework and toolchain.
4. Pass explicit add-on ids and use `-y` only after flags are final.
1. Choose framework and bundler.
2. Choose mode (`--router-only` or full scaffold).
3. If using Vite full scaffold, resolve add-ons, template, and deployment.
4. Add the toolchain and use `-y` only after flags are final.

## Safe presets

Expand All @@ -35,4 +40,7 @@ npx @tanstack/cli create app --blank --framework react --deployment cloudflare -

# Router-only preset
npx @tanstack/cli create app --router-only --framework react --toolchain biome -y

# Rsbuild preset
npx @tanstack/cli create app --framework solid --bundler rsbuild --toolchain biome -y
```
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Framework Adapter Options

Targets `@tanstack/cli` v0.70.0.
Targets `@tanstack/cli` v0.71.0.

## Supported values

Expand Down
37 changes: 35 additions & 2 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import {
createApp,
devAddOn,
getAllAddOns,
getBundlers,
getFrameworkByName,
getFrameworks,
initAddOn,
initStarter,
isDemoFilePath,
resolveBundler,
} from '@tanstack/create'
import {
LIBRARY_GROUPS,
Expand Down Expand Up @@ -167,7 +169,7 @@ function getCreateCommandVariant(options: CliOptions) {
return 'scaffold'
}

function getCreateTelemetryProperties(projectName: string, options: CliOptions) {
export function getCreateTelemetryProperties(projectName: string, options: CliOptions) {
const addOnIds = Array.isArray(options.addOns)
? sanitizeIdList(options.addOns)
: undefined
Expand All @@ -181,6 +183,7 @@ function getCreateTelemetryProperties(projectName: string, options: CliOptions)
: undefined,
command_variant: getCreateCommandVariant(options),
deployment: options.deployment ? sanitizeId(options.deployment) : undefined,
bundler: options.bundler ? sanitizeId(options.bundler) : undefined,
examples: options.examples,
blank: !!options.blank,
framework: options.framework ? sanitizeId(options.framework) : undefined,
Expand All @@ -200,7 +203,7 @@ function getCreateTelemetryProperties(projectName: string, options: CliOptions)
}
}

function getResolvedCreateTelemetryProperties(
export function getResolvedCreateTelemetryProperties(
finalOptions: Options,
cliOptions: CliOptions,
) {
Expand All @@ -221,6 +224,7 @@ function getResolvedCreateTelemetryProperties(
add_on_count: addOnIds.length,
add_on_ids: addOnIds,
deployment: deployment ? sanitizeId(deployment.id) : undefined,
bundler: sanitizeId(finalOptions.bundler ?? 'vite'),
examples: includeExamples,
blank: finalOptions.projectPreset === 'blank',
framework: sanitizeId(finalOptions.framework.id),
Expand Down Expand Up @@ -306,6 +310,9 @@ export function cli({
lines.push(` Project: ${finalOptions.projectName}`)
lines.push(` Location: ${finalOptions.targetDir}`)
lines.push(` Framework: ${finalOptions.framework.name}`)
lines.push(
` Bundler: ${resolveBundler(finalOptions.framework, finalOptions.bundler).name}`,
)
lines.push(` Mode: ${finalOptions.mode}`)
if (finalOptions.projectPreset === 'blank') {
lines.push(` Preset: blank`)
Expand Down Expand Up @@ -565,6 +572,13 @@ export function cli({
}
}

const bundlers = new Set<string>()
for (const framework of getFrameworks()) {
for (const bundler of getBundlers(framework)) {
bundlers.add(bundler.id)
}
}

// Mode is always file-router (TanStack Start)
const defaultMode = 'file-router'
const categoryAliases: Record<string, string> = {
Expand Down Expand Up @@ -660,6 +674,7 @@ export function cli({
const addOns = await getAllAddOns(
getFrameworkByName(options.framework || defaultFramework || 'React')!,
defaultMode,
options.bundler,
)
const visibleAddOns = addOns.filter((a) => !forcedAddOns.includes(a.id))
telemetry.mergeProperties({
Expand Down Expand Up @@ -705,6 +720,7 @@ export function cli({
const addOns = await getAllAddOns(
getFrameworkByName(options.framework || defaultFramework || 'React')!,
defaultMode,
options.bundler,
)
const addOn =
addOns.find((a) => a.id === options.addonDetails) ??
Expand Down Expand Up @@ -958,6 +974,23 @@ export function cli({
}

cmd
.option<string>(
`--bundler <${Array.from(bundlers).join('|')}>`,
'select the project bundler',
(value) => {
const bundler = Array.from(bundlers).find(
(item) => item.toLowerCase() === value.toLowerCase(),
)
if (!bundler) {
throw new InvalidArgumentError(
`Invalid bundler: ${value}. The following are allowed: ${Array.from(
bundlers,
).join(', ')}`,
)
}
return bundler
},
)
.option(
'--starter [url-or-id]',
'DEPRECATED: use --template. Initializes from a template URL or built-in id',
Expand Down
Loading