Routing

404 Not Found

Configure root and per-route 404 error boundaries and throw notFound() from TanStack Start loaders.

In TanStack Start, 404 handling is configured as a route option via notFoundComponent rather than a static file. VitNode provides localized 404 layouts with history-aware navigation buttons out of the box.

Root 404 Handler

Your apps/web/src/routes/__root.tsx defines the fallback boundary for all unmatched URLs:

apps/web/src/routes/__root.tsx
import { createRootRouteWithContext } from "@tanstack/react-router"
import { ErrorActions, NotFound } from "@vitnode/core/tanstack/layout"

export const Route = createRootRouteWithContext<RootRouterContext>()({
  notFoundComponent: () => (
    <NotFound actions={<ErrorActions />} />
  ),
  component: RootComponent,
})

NotFound automatically renders translated text from core.global.errors.404. ErrorActions renders Go Back (history.back()) and Back to Home (/) buttons.


Triggering 404 in Loaders

When a requested resource (like an article slug or user ID) is not found in the database, throw notFound() inside the loader:

apps/web/src/routes/_main/blog/$slug.tsx
import { createFileRoute, notFound } from "@tanstack/react-router"

export const Route = createFileRoute("/_main/blog/$slug")({
  loader: async ({ params }) => {
    const post = await fetchPost(params.slug)
    if (!post) {
      throw notFound()
    }
    return post
  },
  component: PostPage,
})

Custom Route-Level 404 Components

You can assign a customized notFoundComponent to specific routes or layout shells:

apps/web/src/routes/_main/blog/$slug.tsx
export const Route = createFileRoute("/_main/blog/$slug")({
  loader: async ({ params }) => { /* ... */ },
  notFoundComponent: () => (
    <div className="p-8 text-center">
      <h2>Article Not Found</h2>
      <p>The post you are looking for may have been removed.</p>
    </div>
  ),
})

Learn More