In TanStarter, protected routes are implemented using a layout route named _auth. This layout uses the beforeLoad hook to intercept navigation and ensure a user is authenticated before allowing access to any child routes (e.g., _auth/app/*).
To protect a route tree, define a _auth layout route that uses context.queryClient.ensureQueryData with authQueryOptions() to check for an active session. If no user is found, the route throws a redirect to the /login page.
Important Security Note: The beforeLoad check is optimized for UX using TanStack Query caching and Better Auth's cookieCache. While this provides fast client-side navigation, it is not a server-side security guarantee. For secure data fetching, mutations, or API routes, you must use authMiddleware (see /lib/auth/middleware.ts).
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
import { authQueryOptions } from "#/lib/auth/queries";
export const Route = createFileRoute("/_auth")({
component: Outlet,
beforeLoad: async ({ context }) => {
const user = await context.queryClient.ensureQueryData({
...authQueryOptions(),
revalidateIfStale: true,
});
if (!user) {
throw redirect({ to: "/login" });
}
},
});