React Example: Start Basic Auth

tsx
/// <reference types="vite/client" /> import { HeadContent, Link, Outlet, Scripts, createRootRoute, } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import { createServerFn } from '@tanstack/react-start' import * as React from 'react' import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' import { NotFound } from '~/components/NotFound.js' import appCss from '~/styles/app.css?url' import { seo } from '~/utils/seo.js' import { useAppSession } from '~/utils/session.js' const fetchUser = createServerFn({ method: 'GET' }).handler(async () => { // We need to auth on the server so we have access to secure cookies const session = await useAppSession() if (!session.data.userEmail) { return null } return { email: session.data.userEmail, } }) export const Route = createRootRoute({ beforeLoad: async () => { const user = await fetchUser() return { user, } }, head: () => ({ meta: [ { charSet: 'utf-8', }, { name: 'viewport', content: 'width=device-width, initial-scale=1', }, ...seo({ title: 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, }), ], links: [ { rel: 'stylesheet', href: appCss }, { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png', }, { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png', }, { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png', }, { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, { rel: 'icon', href: '/favicon.ico' }, ], }), errorComponent: (props) => { return ( <RootDocument> <DefaultCatchBoundary {...props} /> </RootDocument> ) }, notFoundComponent: () => <NotFound />, component: RootComponent, }) function RootComponent() { return ( <RootDocument> <Outlet /> </RootDocument> ) } function RootDocument({ children }: { children: React.ReactNode }) { const { user } = Route.useRouteContext() return ( <html> <head> <HeadContent /> </head> <body> <div className="p-2 flex gap-2 text-lg"> <Link to="/" activeProps={{ className: 'font-bold', }} activeOptions={{ exact: true }} > Home </Link>{' '} <Link to="/posts" activeProps={{ className: 'font-bold', }} > Posts </Link> <div className="ml-auto"> {user ? ( <> <span className="mr-2">{user.email}</span> <Link to="/logout">Logout</Link> </> ) : ( <Link to="/login">Login</Link> )} </div> </div> <hr /> {children} <TanStackRouterDevtools position="bottom-right" /> <Scripts /> </body> </html> ) } 
/// <reference types="vite/client" /> import { HeadContent, Link, Outlet, Scripts, createRootRoute, } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import { createServerFn } from '@tanstack/react-start' import * as React from 'react' import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' import { NotFound } from '~/components/NotFound.js' import appCss from '~/styles/app.css?url' import { seo } from '~/utils/seo.js' import { useAppSession } from '~/utils/session.js' const fetchUser = createServerFn({ method: 'GET' }).handler(async () => { // We need to auth on the server so we have access to secure cookies const session = await useAppSession() if (!session.data.userEmail) { return null } return { email: session.data.userEmail, } }) export const Route = createRootRoute({ beforeLoad: async () => { const user = await fetchUser() return { user, } }, head: () => ({ meta: [ { charSet: 'utf-8', }, { name: 'viewport', content: 'width=device-width, initial-scale=1', }, ...seo({ title: 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, }), ], links: [ { rel: 'stylesheet', href: appCss }, { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png', }, { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png', }, { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png', }, { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, { rel: 'icon', href: '/favicon.ico' }, ], }), errorComponent: (props) => { return ( <RootDocument> <DefaultCatchBoundary {...props} /> </RootDocument> ) }, notFoundComponent: () => <NotFound />, component: RootComponent, }) function RootComponent() { return ( <RootDocument> <Outlet /> </RootDocument> ) } function RootDocument({ children }: { children: React.ReactNode }) { const { user } = Route.useRouteContext() return ( <html> <head> <HeadContent /> </head> <body> <div className="p-2 flex gap-2 text-lg"> <Link to="/" activeProps={{ className: 'font-bold', }} activeOptions={{ exact: true }} > Home </Link>{' '} <Link to="/posts" activeProps={{ className: 'font-bold', }} > Posts </Link> <div className="ml-auto"> {user ? ( <> <span className="mr-2">{user.email}</span> <Link to="/logout">Logout</Link> </> ) : ( <Link to="/login">Login</Link> )} </div> </div> <hr /> {children} <TanStackRouterDevtools position="bottom-right" /> <Scripts /> </body> </html> ) }