For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /guide/migration/tanstack-start.md.
close

TanStack Start

TanStack Start supports Rsbuild for React and Solid applications. This guide replaces the Vite integration while preserving TanStack Start's managed client and server entries.

Do not apply the generic build entry migration steps to a TanStack Start application.

Before you start

Keep your existing tanstackStart options, routes, server functions, and application code. This migration changes the build tool; it does not change the TanStack Start application model.

Review your Vite configuration and deployment integration before editing dependencies. Vite plugins cannot run in rsbuild.config.ts; migrate each one to an Rsbuild or Rspack equivalent, or remove it only after confirming that it is no longer needed.

Replace the Vite configuration

React

Remove Vite and its React plugin, then install the Rsbuild equivalents:

npm
yarn
pnpm
bun
deno
npm remove vite @vitejs/plugin-react
npm
yarn
pnpm
bun
deno
npm add @rsbuild/core @rsbuild/plugin-react -D

If you use @vitejs/plugin-react-swc, remove that package instead. Keep @tanstack/react-start and @tanstack/react-router installed.

Replace vite.config.ts with rsbuild.config.ts:

rsbuild.config.ts
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { tanstackStart } from '@tanstack/react-start/plugin/rsbuild';

export default defineConfig({
  plugins: [pluginReact(), tanstackStart()],
});

This is the minimal configuration used by the Rsbuild React example, excluding its optional Tailwind CSS plugin.

Solid

Remove Vite and its Solid plugin, then install the Rsbuild equivalents:

npm
yarn
pnpm
bun
deno
npm remove vite vite-plugin-solid
npm
yarn
pnpm
bun
deno
npm add @rsbuild/core @rsbuild/plugin-babel @rsbuild/plugin-solid -D

Keep @tanstack/solid-start and @tanstack/solid-router installed.

Replace vite.config.ts with rsbuild.config.ts:

rsbuild.config.ts
import { defineConfig } from '@rsbuild/core';
import { pluginBabel } from '@rsbuild/plugin-babel';
import { pluginSolid } from '@rsbuild/plugin-solid';
import { tanstackStart } from '@tanstack/solid-start/plugin/rsbuild';

export default defineConfig({
  plugins: [
    pluginBabel({
      include: /\.(?:jsx|tsx)$/,
    }),
    pluginSolid(),
    tanstackStart(),
  ],
});

This is the minimal configuration used by the Rsbuild Solid example, excluding its optional Tailwind CSS plugin.

Update scripts

Retain "type": "module" in package.json, then replace the Vite scripts:

package.json
{
  "type": "module",
  "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "preview": "vite preview",
    "dev": "rsbuild",
    "build": "rsbuild build",
    "preview": "rsbuild preview"
  }
}

rsbuild without a subcommand starts the dev server. rsbuild dev is equivalent.

Route generation

If the project has a generate-routes script that runs tsr generate, replace it with rsbuild build:

package.json
{
  "scripts": {
    "generate-routes": "tsr generate",
    "generate-routes": "rsbuild build"
  }
}

The TanStack Start Rsbuild plugin generates the route tree during the build and adds its required registration to routeTree.gen.ts. Running tsr generate directly can overwrite that registration.

Migrate project-specific settings

The configuration above replaces only the TanStack Start and Vite integration. Migrate all other Vite configuration deliberately:

  • Use the Vite config migration reference for aliases, CSS, dev server settings, static assets, and other Vite options.
  • Replace each Vite plugin with an Rsbuild or Rspack equivalent. Integrations that expose only a Vite plugin need a separately supported replacement.
  • Delete vite.config.ts after its settings have been migrated.

React Compiler

For React applications that use React Compiler through a Babel plugin, configure the built-in Rspack implementation instead:

rsbuild.config.ts
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';

export default defineConfig({
  plugins: [
    pluginReact({
      reactCompiler: true,
    }),
  ],
});

If a Babel or Rolldown Babel plugin was used only for React Compiler, remove that plugin and babel-plugin-react-compiler. For React 17 or 18 applications, install react-compiler-runtime and set the compiler target as described in the React plugin documentation.

TypeScript

Replace Vite's preset types in tsconfig.json with Rsbuild's preset types. If your project already defines a types array, replace only the Vite entries and retain the other required types:

tsconfig.json
{
  "compilerOptions": {
    "types": ["vite/client", "vite-plugin-svgr/client"],
    "types": ["@rsbuild/core/types"] 
  }
}

@rsbuild/plugin-svgr does not provide a TypeScript declaration for *.svg?react imports. If your application uses that query, add a declaration file such as src/types/svg.d.ts:

src/types/svg.d.ts
declare module '*.svg?react' {
  import type React from 'react';

  const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
  export default ReactComponent;
}

Environment variables

Rsbuild exposes client environment variables with the PUBLIC_ prefix. Rename every client variable from VITE_* to PUBLIC_*, including its definition in .env files, CI variables, Docker build arguments, and application code:

- VITE_API_URL
+ PUBLIC_API_URL

Update application code to use direct property access, such as import.meta.env.PUBLIC_API_URL. If an environment validator receives the entire import.meta.env object, pass it an explicit object containing the required PUBLIC_ properties.

Static prerendering and CDN URLs

Keep options passed to tanstackStart. For example, static prerendering remains configured through the plugin:

tanstackStart({
  prerender: {
    enabled: true,
    crawlLinks: true,
  },
});

See the React and Solid static prerendering guides for all available options.

For React applications that use CDN asset URLs, configure transformAssets in the TanStack Start server entry. This is different from setting an Rsbuild assetPrefix:

const handler = createStartHandler({
  handler: defaultStreamHandler,
  transformAssets: process.env.CDN_ORIGIN || '',
});

Use the React server APIs when creating the handler. See CDN asset URLs for a complete example.

Paraglide

If you use Paraglide, replace paraglideVitePlugin with paraglideRspackPlugin and register it in tools.rspack.plugins. Keep the existing plugin options and generated output directory.

Sentry

Replace the Vite adapter's build-time integration with @sentry/webpack-plugin. Register it in tools.rspack.plugins, enable hidden-source-map when uploading source maps, and set SENTRY_AUTH_TOKEN and SENTRY_RELEASE in CI.

If you use a Sentry tunnel, define a TanStack Start route and limit it to your public DSN:

src/routes/monitoring.ts
import * as Sentry from '@sentry/tanstackstart-react';
import { createFileRoute } from '@tanstack/react-router';

const sentryDsn = import.meta.env.PUBLIC_SENTRY_DSN;

export const Route = createFileRoute('/monitoring')({
  server: Sentry.createSentryTunnelRoute({
    allowedDsns: sentryDsn ? [sentryDsn] : [],
  }),
});

Configure the same path with the client SDK's tunnel option.

Migrate tests from Vitest to Rstest

Vitest runs tests through Vite. If you want to remove Vite from the test toolchain, migrate the Vitest configuration and test imports to Rstest before removing vitest, @vitest/coverage-v8, and Vite-only test plugins.

Install Rstest and its Rsbuild adapter. Add the V8 coverage package when the Vitest configuration uses V8 coverage:

npm
yarn
pnpm
bun
deno
npm add @rstest/core @rstest/adapter-rsbuild @rstest/coverage-v8 jsdom -D

Create rstest.config.ts and reuse the application configuration:

rstest.config.ts
import { withRsbuildConfig } from '@rstest/adapter-rsbuild';
import { defineConfig } from '@rstest/core';

export default defineConfig({
  extends: withRsbuildConfig(),
  testEnvironment: 'jsdom',
  setupFiles: ['./src/test/setup.ts'],
  coverage: {
    provider: 'v8',
    reporters: ['text', 'html', 'lcov', 'cobertura'],
  },
});

Rstest options are top-level fields: for example, move test.environment to testEnvironment, test.setupFiles to setupFiles, and test.coverage to coverage. Rename Vitest's coverage.reporter option to coverage.reporters.

Replace test API imports:

import { describe, expect, it } from 'vitest'; 
import { describe, expect, it } from '@rstest/core'; 

For Testing Library and @testing-library/jest-dom, register matchers with Rstest's expect in the setup file. Use the Testing Library package for your framework:

src/test/setup.ts (React)
import { cleanup } from '@testing-library/react';
import * as jestDomMatchers from '@testing-library/jest-dom/matchers';
import { afterEach, expect } from '@rstest/core';

expect.extend(jestDomMatchers);
afterEach(cleanup);
src/test/setup.ts (Solid)
import * as jestDomMatchers from '@testing-library/jest-dom/matchers';
import { cleanup } from '@testing-library/solid';
import { afterEach, expect } from '@rstest/core';

expect.extend(jestDomMatchers);
afterEach(cleanup);

Update scripts to use rstest, rstest --watch, and rstest --coverage. For more configuration mappings, see the Rstest migration guide and the Rsbuild Testing guide.

Deploy to Node.js or docker

If nitro/vite is used only for Node.js or Docker deployment, remove nitro. A TanStack Start Rsbuild build emits its own server entry. Install srvx as a production dependency:

npm
yarn
pnpm
bun
deno
npm remove nitro
npm
yarn
pnpm
bun
deno
npm add srvx
package.json
{
  "scripts": {
    "start": "srvx --prod -s ../client dist/server/index.js"
  }
}

The production build emits client assets in dist/client and the fetch-style server entry in dist/server/index.js. If your build emits dist/server/server.js, use that path instead.

For Docker, install production dependencies again in the final stage. The runner stage starts from a fresh base image: the builder's node_modules includes development dependencies and should not be copied to the runtime image.

Use the following runner stage in your Dockerfile. It detects the package manager from the project's lockfile and supports npm, Yarn, and pnpm:

Dockerfile (runner stage)
FROM node:24-alpine AS runner
WORKDIR /app
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* .npmrc* ./
RUN corepack enable && \
  if [ -f package-lock.json ]; then \
    npm ci --omit=dev --ignore-scripts; \
  elif [ -f yarn.lock ]; then \
    yarn install --frozen-lockfile --production=true --ignore-scripts; \
  elif [ -f pnpm-lock.yaml ]; then \
    pnpm install --prod --frozen-lockfile --ignore-scripts; \
  else \
    echo "No lockfile found." && exit 1; \
  fi
COPY --from=builder /app/dist ./dist
CMD ["./node_modules/.bin/srvx", "--prod", "-s", "../client", "dist/server/index.js"]

Configure the preceding build stages according to the TanStack Start React or Solid deployment guide.

For deployment targets other than Node.js or Docker, Vite-specific deployment integrations cannot be used with Rsbuild. Use a supported non-Vite adapter, or retain the Vite integration. See the React hosting guide and Solid hosting guide.