Routing Structure Generation and Conventions in OpenCut

OpenCut leverages TanStack Router's file-based routing system to automatically generate type-safe route trees from the src/routes directory, eliminating manual route configuration while ensuring compile-time path validation through the auto-generated routeTree.gen.ts file.

The OpenCut web application employs a modern, zero-configuration routing architecture powered by TanStack Router. This approach treats the filesystem as the source of truth for URL structure, automatically mapping TypeScript files in src/routes to application paths. Understanding these routing conventions is essential for extending the application's navigation structure while maintaining strict type safety.

Core Routing Files and Architecture

OpenCut's routing layer centers around three critical files that orchestrate navigation:

  • src/router.tsx – Instantiates the TanStack router with the generated route tree and global configuration options like scroll restoration and preloading.
  • src/routeTree.gen.ts – Auto-generated TypeScript file containing the compile-time route map. Never edit this file manually; it regenerates automatically during the build process.
  • src/routes/__root.tsx – The root route defining global HTML head elements, CSS imports, and shared layout providers.

These files work together to provide a type-safe navigation experience where route IDs, paths, and parameters are validated at compile time.

How the Route Tree Is Generated

The generation process follows a file-based discovery pattern. When you run npm run dev or bun run dev, TanStack Router scans the src/routes/**/*.tsx pattern and performs the following steps:

  1. File Discovery – Every file exporting a Route constant created via createFileRoute (or createRootRoute for the root) becomes a route entry.
  2. Type Generation – The plugin writes src/routeTree.gen.ts, containing concrete route objects (IndexRoute) and TypeScript interfaces (FileRoutesByFullPath, FileRoutesById).
  3. Router Initialization – src/router.tsx imports the generated routeTree and passes it to createTanStackRouter:
// src/router.tsx
import { createRouter as createTanStackRouter } from '@tanstack/react-router';
import { routeTree } from './routeTree.gen';

export function getRouter() {
  return createTanStackRouter({
    routeTree,
    scrollRestoration: true,
    defaultPreload: 'intent',
    defaultPreloadStaleTime: 0,
  });
}

The resulting router instance provides module augmentation that enables type-safe usage of useRouter() and <Link> components throughout the application.

File-Based Routing Conventions

OpenCut follows strict conventions to ensure predictable URL mapping:

  • File Location – Place route files under src/routes/; subdirectories create nested paths.
  • Index Routes – Use index.tsx for directory roots (maps to /).
  • Export Requirement – Must export a Route constant using createFileRoute.
  • Path Inference – URL path derived from file location unless overridden via options.

Creating a New Route

To add a Settings page at /settings, create src/routes/settings.tsx with the following structure:

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

export const Route = createFileRoute('/settings')({
  component: SettingsPage,
});

function SettingsPage() {
  return (
    <div className="p-4">
      <h1 className="text-2xl font-bold">Settings</h1>
      {/* Settings UI implementation */}
    </div>
  );
}

After saving the file, the development server automatically regenerates routeTree.gen.ts, making the route immediately available without restarting the dev server.

The Root Route and Global Layout

The src/routes/__root.tsx file serves as the application shell, utilizing createRootRoute instead of createFileRoute. This route wraps all page content and provides:

  • Global Head Management – Meta tags, viewport settings, and font preloading via the head property.
  • CSS Injection – Global stylesheet imports (e.g., appCss).
  • Provider Wrapping – TooltipProvider for UI components.
  • Development Tools – TanStack Router devtools panel for debugging navigation.
// src/routes/__root.tsx
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router';
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools';
import { TooltipProvider } from '../components/ui/tooltip';
import appCss from '../styles.css?url';

export const Route = createRootRoute({
  head: () => ({
    meta: [
      { charSet: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { title: 'OpenCut rewrite — beta.opencut.app' }
    ],
    links: [
      { rel: 'icon', href: '/favicon.ico' },
      { rel: 'stylesheet', href: appCss },
    ],
  }),
  shellComponent: RootDocument,
});

function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head><HeadContent /></head>
      <body>
        <TooltipProvider>{children}</TooltipProvider>
        <TanStackRouterDevtoolsPanel />
        <Scripts />
      </body>
    </html>
  );
}

All child routes render inside the RootDocument component, ensuring consistent styling and behavior across the application.

Type Safety and the Generated Route Tree

The routeTree.gen.ts file exports TypeScript interfaces that map file paths to route types:

export interface FileRoutesByFullPath {
  '/': typeof IndexRoute;
  '/settings': typeof SettingsRoute;
}

export interface FileRoutesById {
  __root__: typeof rootRouteImport;
  '/': typeof IndexRoute;
  '/settings': typeof SettingsRoute;
}

These definitions enable IDE autocomplete for route IDs and compile-time validation of navigation calls. For example, router.navigate({ to: '/settings' }) will type-check against valid paths, preventing runtime 404 errors due to typos in route strings.

When you need to add loaders or search parameter validation, modify the route file (e.g., src/routes/settings.tsx) rather than the generated file. The build process will incorporate your changes into the type definitions automatically.

Summary

  • File-based routing in OpenCut uses TanStack Router to map src/routes/**/*.tsx files directly to URLs without manual configuration.
  • Auto-generation creates routeTree.gen.ts during the build process, providing compile-time type safety for all navigation operations.
  • Root route (__root.tsx) defines global layout, meta tags, and development tools using createRootRoute.
  • New routes require only a file in src/routes/ exporting a Route constant via createFileRoute, with paths inferred from the file location.
  • Never edit routeTree.gen.ts manually; modify source route files and let the generator update type definitions.

Frequently Asked Questions

How do I add a nested route like /projects/:id in OpenCut?

Create a directory structure under src/routes/ that mirrors the URL path. For /projects/:id, create src/routes/projects/$id.tsx (using the $ prefix for parameters). Export a Route using createFileRoute('/projects/$id') and access the parameter via the useParams hook. The file-based system automatically registers the dynamic segment.

What happens if I edit routeTree.gen.ts manually?

Manual edits to routeTree.gen.ts will be overwritten the next time the development server starts or the build runs. This file is purely generated output. To modify route behavior, edit the source route files in src/routes/ or adjust the router configuration in src/router.tsx.

Can I customize the route path to differ from the file path?

Yes. While TanStack Router infers the path from the file location by default, you can override it in the createFileRoute options. Pass a path property in the configuration object to specify a custom URL pattern that differs from the filesystem structure.

How does OpenCut handle 404 pages and error boundaries?

Define a notFoundComponent in your route configuration or utilize the root route's error handling. TanStack Router supports error boundaries through the errorComponent property on route definitions. For catch-all 404 routes, create a $.tsx file in src/routes/ to match unmatched paths.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →