oakoss/open-saas-kit · Archived

tanstack-router

TanStack Router file-based routing. Use for routes, params, search params, navigation, loaders, auth guards, layouts, nested routes, redirect

First seen Jun 20, 2026

Installation

$ npx skills add oakoss/open-saas-kit --skill tanstack-router

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from oakoss/open-saas-kit · top by installs.

npx skills add oakoss/open-saas-kit

Browse all from oakoss/open-saas-kit

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 1
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,626 B
  • docs SUMMARY.md 164 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

TanStack Router

File-Based Routing

routes/
├── __root.tsx        # Root layout (meta, providers)
├── index.tsx         # / (homepage)
├── _app.tsx          # Layout for /_app/* routes
├── _app/
│   ├── index.tsx     # /app
│   └── settings.tsx  # /app/settings
├── posts.tsx         # /posts (list)
├── posts/
│   └── $id.tsx       # /posts/:id (detail)
└── api/
    └── auth/$.tsx    # /api/auth/* (catch-all)

Route Definition

import { createFileRoute } from '@tanstack/react-router';

export const Route = createFileRoute('/posts/$id')({
  component: PostPage,
  loader: async ({ params }) => fetchPost(params.id),
  validateSearch: z.object({ tab: z.string().optional() }),
  errorComponent: PostError,
  pendingComponent: PostSkeleton,
});

function PostPage() {
  const post = Route.useLoaderData();
  const { tab } = Route.useSearch();
  const { id } = Route.useParams();
  return <Post data={post} />;
}

Route Context Pattern

// __root.tsx
import { createRootRouteWithContext } from '@tanstack/react-router';

type RouterContext = {
  queryClient: QueryClient;
};

export const Route = createRootRouteWithContext<RouterContext>()({
  component: RootLayout,
});

// router.tsx
export const getRouter = () =>
  createRouter({
    routeTree,
    context: { queryClient },
  });

Auth Guard (beforeLoad)

export const Route = createFileRoute('/_app')({
  beforeLoad: async ({ context }) => {
    const session = await auth.api.getSession({
      headers: context.request.headers,
    });

    if (!session) {
      throw redirect({ to: '/login' });
    }

    return { user: session.user };
  },
  component: AppLayout,
});

Navigation

import { Link, useNavigate } from '@tanstack/react-router';

// Link component
<Link to="/posts/$id" params={{ id: '123' }} search={{ tab: 'comments' }}>
  View Post
</Link>;

// Programmatic navigation
const navigate = useNavigate();
navigate({ to: '/posts', search: { page: 2 } });
navigate({ to: '..', search: (prev) => ({ ...prev }) }); // Relative

Search Params with Zod

import { zodValidator } from '@tanstack/zod-adapter';
import { stripSearchParams } from '@tanstack/react-router';

const defaults = { page: 1, sort: 'newest' as const };

const searchSchema = z.object({
  page: z.number().default(defaults.page),
  sort: z.enum(['newest', 'oldest']).default(defaults.sort),
  filter: z.string().optional(),
});

export const Route = createFileRoute('/posts')({
  validateSearch: zodValidator(searchSchema),
  search: { middlewares: [stripSearchParams(defaults)] },
  component: PostsPage,
});

function PostsPage() {
  const { page, sort, filter } = Route.useSearch();
  const navigate = useNavigate();

  const setPage = (newPage: number) => {
    navigate({ search: (prev) => ({ ...prev, page: newPage }) });
  };
}

Layout Routes

// _app.tsx - Pathless layout
export const Route = createFileRoute('/_app')({
  component: AppLayout,
});

function AppLayout() {
  return (
    <div className="flex">
      <Sidebar />
      <main>
        <Outlet /> {/* Child routes render here */}
      </main>
    </div>
  );
}

Loader with TanStack Query

export const Route = createFileRoute('/posts')({
  loader: async ({ context }) => {
    await context.queryClient.ensureQueryData(postsOptions());
  },
  component: PostsPage,
});

function PostsPage() {
  const { data } = useSuspenseQuery(postsOptions());
  return <PostList posts={data} />;
}

Common Mistakes

Mistake Correct Pattern
Using validateSearch without adapter Use zodValidator(schema)
Auth check in component Use beforeLoad for route guards
Not awaiting ensureQueryData Await to block navigation until ready
Forgetting Outlet in layouts Layout components need <Outlet />
Hardcoding paths in navigate Use type-safe to with params
Missing $ prefix for dynamic routes Use $id.tsx not id.tsx
Route params without validation Validate with Zod in loader
Not using search middleware Use stripSearchParams for clean URLs
Circular redirects in beforeLoad Check current location before redirect
Not handling 404 in loader Use throw notFound() for missing data

Delegation

  • Query patterns: For data fetching in loaders, see [tanstack-query](../tanstack-query/SKILL.md) skill
  • Server functions: For API calls, see [tanstack-start](../tanstack-start/SKILL.md) skill
  • Auth patterns: For authentication, see [auth](../auth/SKILL.md) skill
  • Code review: After implementing routes, delegate to code-reviewer agent

Topic References

  • [Route Context](route-context.md) - Context inheritance, beforeLoad, nested layouts
  • [Search Params](search-params.md) - zodValidator, stripSearchParams, URL state
  • [Navigation](navigation.md) - Link, useNavigate, active states, type safety
  • [Loaders & Errors](loaders-errors.md) - Data loading, error boundaries, Suspense
  • [Advanced Features](advanced-features.md) - Preloading, scroll restoration, code splitting