Skip to content

TanStack Start

Next release

A TanStack Start or TanStack Router app is edited like any Vite + React project, and midcode reads its file routes as pages.

View as Markdown

This ships with the next release of midcode. The version you can download today (1.1.2) doesn’t have it yet.

midcode treats a TanStack Start app as what it is: a Vite project written in React. It’s started, marked and edited exactly as described in React with Vite. What this page adds is the one thing specific to TanStack: its routes are files, so midcode can list them as pages.

The same goes for a plain Vite app that uses TanStack Router with file routes.

At a glance

TanStack Start
Detected byvite and react in package.json. The routes are found by the folder that holds __root.tsx
Runs withvite dev, with a config of midcode’s that loads yours and adds one plugin
Elements are marked byThat plugin, as Vite transforms each .tsx and .jsx file
EditingFull, in .tsx and .jsx files
ComponentsYes: instances, props, variants and states, variables
PagesThe route files of src/routes. New pages and removing them
StylesTailwind 4 classes, or mid: classes with midcode.css

How midcode runs it

There is no check for TanStack itself. midcode sees vite in package.json, with react, and starts Vite with its own config in front of yours:

Terminal
vite dev /Users/you/apps/start-app \
  --config "/Users/you/Library/Application Support/midcode/injected/vite.config.mjs" \
  --port 4310 --strictPort --host localhost

That config loads your vite.config, with its tanstackStart() plugin and everything else, and adds the plugin that marks each JSX element with its file, line and column. Nothing is written in your project. Options in your dev script, such as --mode, are kept. The port in it isn’t: midcode picks its own. The details, and what happens when Vite doesn’t start this way, are in React with Vite.

A route file is marked like any other component:

src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/')({ component: Home })

function Home() {
  return (
    <main className="p-8">
      <h1 className="text-4xl font-bold">Welcome</h1>
    </main>
  )
}
HTML
<h1 data-mc="src/routes/index.tsx:8:7" class="text-4xl font-bold">Welcome</h1>

Pages

midcode looks for __root.tsx (or .jsx, .ts, .js) in src/routes, app/routes and src/app/routes. The folder that has it is the routes folder, and each .tsx or .jsx file in it or in its subfolders is a page. The address comes from the file’s name, read the way TanStack Router reads it:

FilePage
index.tsx/
about.tsx/about
posts.index.tsx or posts/index.tsx/posts
posts.$postId.tsx/posts/[postId], a dynamic route
posts_.$postId.edit.tsx/posts/[postId]/edit
_app.settings.tsx/settings
(marketing)/pricing.tsx/pricing
files.$.tsx/files/[...]

Dots nest like folders. Parts that only group or wrap add nothing to the address: a name that starts with _, a (group) folder, route.tsx, .lazy. Not listed: __root, anything whose name starts with -, and an api folder at the top.

A dynamic route is one entry. midcode finds its pages in the running site, from its sitemap and the links on its pages. See Pages and navigation.

“New page” in the page menu writes a route file with its createFileRoute, and “Remove” moves a route’s file to the Trash:

src/routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/about')({ component: About })

function About() {
  return (
    <main className="mx-auto max-w-3xl px-6 py-24">
      <h1 className="text-4xl font-semibold">About</h1>
      <p className="mt-4">A new page, made in midcode.</p>
    </main>
  )
}

A deeper path uses dots: /posts/first is posts.first.tsx. The class names are written when Tailwind is in your package.json. Both are offered when __root.tsx (or .jsx) is in src/routes, or __root.tsx in app/routes.

Styles

With Tailwind 4, midcode writes Tailwind’s classes: see Tailwind CSS.

Without it, midcode writes mid: utilities and compiles them to midcode.css. It imports that file in the module index.html loads, or in src/main.*, src/index.* or src/entry-client.*. A TanStack Start app usually has none of those. In that case midcode writes src/midcode.css and tells you it couldn’t tell where to import it: load it in src/routes/__root.tsx, the way your app loads its other stylesheet. See Without Tailwind.

Limits

  • Only the file names are read. Routes built in code, virtual file routes and a custom routes folder set in the plugin’s options aren’t followed. Any page can still be opened by typing its path in the page menu.

  • An older TanStack Start project that has no vite in its package.json isn’t recognised as a Vite project: it runs with its own dev script and shows without marks.

  • No free canvas: it’s for Next.js projects on the App Router.

  • Site settings writes the <head> of an index.html at the project’s root. A Vite app that uses TanStack Router has one. A TanStack Start app usually doesn’t (its <head> is built in its root route), and then the globe isn’t in the top bar: set the title and the rest in code.

  • No TanStack Start version is on record as tried end to end. The route reader follows TanStack Router’s file naming, and everything else is the Vite + React path, which is tried.

  • The other limits of React with Vite apply.