npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tanstack-router-scoped-trees

v0.1.1

Published

Generate per-section TanStack Router route trees for faster tests. A community package, not an official TanStack package.

Readme

tanstack-router-scoped-trees

Generate one TanStack Router route tree per section of your app, so a route test loads only the routes it needs.

This is a community package. It is not affiliated with TanStack and not an official TanStack package.

Why

TanStack Router builds one route tree for the whole app. A test for a single billing screen still imports every route in the app before it can render. On a large app that cost is paid in every test file.

This package generates a smaller tree for each section you define (billing, settings, and so on). A billing test imports the billing tree and nothing else.

In a local measurement (one machine, not CI) on a generated app with 1,000 routes, a test file ran 0.8 to 1.6 s faster per process, 25% to 46% less wall time. Details and caveats are in examples/benchmark/RESULTS.md. Your numbers depend on your app.

Install

npm i -D tanstack-router-scoped-trees

Also add @tanstack/router-generator as a devDependency, at the exact version your @tanstack/router-plugin uses. Without it, npm can install a second, newer copy for this package, and the trees would come from a different generator than the dev server's. Find the version and pin it:

npm ls @tanstack/router-generator
npm i -D @tanstack/router-generator@<version under @tanstack/router-plugin>
npm ls @tanstack/router-generator

The last command must show one version. If it does not, the CLI stops and the Vite plugin and the parity test say which versions differ. See versions.

Set up in five minutes

The code below comes from examples/basic.

  1. Add the plugin after tanstackRouter() in vite.config.ts:

    import { tanstackRouter } from "@tanstack/router-plugin/vite";
    import react from "@vitejs/plugin-react";
    import { scopedRouteTrees } from "tanstack-router-scoped-trees/vite";
    import { defineConfig } from "vite";
    
    export default defineConfig({
      plugins: [tanstackRouter(), scopedRouteTrees(), react()],
    });
  2. Start the dev server once. The plugin detects your sections, writes scoped-route-trees.config.ts and generates the trees. Review the config:

    import { defineConfig } from "tanstack-router-scoped-trees";
    
    export default defineConfig({
      sections: {
        billing: ["/billing"],
        about: ["/about"],
        settings: ["/settings"],
      },
    });
  3. Commit the config and the generated trees (by default in src/test/route-trees). Add that folder to .prettierignore, next to routeTree.gen.ts, and to any other formatter or linter that rewrites files. A reformatted tree no longer matches a fresh generation, so generate --check would fail:

    src/routeTree.gen.ts
    src/test/route-trees
  4. In one test, swap the full tree for a scoped one:

    import { createMemoryHistory, createRouter, RouterProvider } from "@tanstack/react-router";
    import { render, screen } from "@testing-library/react";
    import { expect, it } from "vitest";
    import { routeTree as billingRouteTree } from "./route-trees/billing.gen.js";
    
    it("renders the invoices page", async () => {
      const router = createRouter({
        routeTree: billingRouteTree,
        history: createMemoryHistory({ initialEntries: ["/billing/invoices"] }),
      });
    
      render(<RouterProvider router={router} />);
    
      expect(await screen.findByRole("heading", { name: "Invoices" })).toBeDefined();
    });

Generated files export TanStack's plain routeTree, so rename it on import.

Each section tree also contains the parent routes it needs (the root, and layouts above your routes), so nested routes keep working.

One tree per test file

Import only one route tree in each test file. TanStack's generated trees change the shared root route, so a second import breaks the first. This includes mixing a scoped tree with the full tree.

To assert a redirect out of your section, write that test in its own file and import the full tree there. See pitfalls.

CLI

npx tanstack-router-scoped-trees init
npx tanstack-router-scoped-trees generate
npx tanstack-router-scoped-trees generate --check
  1. init writes scoped-route-trees.config.ts from the sections it detects.
  2. generate refreshes the full tree and every scoped tree. It also creates the config if it is missing.
  3. generate --check writes nothing and exits 1 if a tree is stale, a route is in no section, or parity fails. It is the check that compares committed trees with a fresh generation. Use it in CI. See CI.

All commands take --root <dir>, and --version prints the package version.

The CLI reads routing options from tsr.config.json only. Keep every option that changes the generated output there too (quoteStyle, semicolons, routeFileIgnorePattern and so on). If such an option is only set inline in tanstackRouter(), the CLI and the dev server write different full trees and generate --check fails.

Parity test

Add one test that builds every section tree in memory and checks it against what TanStack itself generates from the same files. It does not read your committed trees:

import { checkScopedRouteTrees, formatParityDifferences } from "tanstack-router-scoped-trees";
import { expect, it } from "vitest";

it("keeps every scoped tree in parity with the full route tree", async () => {
  expect(formatParityDifferences(await checkScopedRouteTrees())).toBe("");
}, 60_000);

It runs one TanStack crawl per section, so give it a longer timeout than the default.

Not supported in v1

  1. Apps that set virtualRouteConfig (the tool stops with a message).
  2. Code-based routing. Only file-based routes.

Guides

  1. Options: every config field and its default.
  2. Sections: how prefixes, parents and common routes work.
  3. CI: keep trees fresh and checked.
  4. Pitfalls: redirects out of a section, and tests that now fail.
  5. Troubleshooting
  6. Versions
  7. Contributing

License

MIT