Skip to main content

1. Provider setup

import { BrowserRouter } from 'react-router'
import { DeploymentProvider } from '@wacht/react-router'

export function App() {
  return (
    <DeploymentProvider publicKey={import.meta.env.VITE_WACHT_PUBLISHABLE_KEY}>
      <BrowserRouter>{/* routes */}</BrowserRouter>
    </DeploymentProvider>
  )
}

2. Protect a loader

import { json, redirect, type LoaderFunctionArgs } from 'react-router'
import { authenticateRequest } from '@wacht/react-router/server'

export async function loader({ request }: LoaderFunctionArgs) {
  const { auth, headers } = await authenticateRequest(request, {
    publishableKey: process.env.WACHT_PUBLISHABLE_KEY,
  })

  if (!auth.userId) {
    throw redirect('/sign-in', { headers })
  }

  return json({ userId: auth.userId }, { headers })
}

Header propagation contract

authenticateRequest() may rotate/exchange session state and returns response headers that must be preserved.
const { auth, headers } = await authenticateRequest(request, options)
return json(data, { headers })

getAuth vs requireAuth

  • getAuth: returns auth state without forcing protection
  • requireAuth: runs protect() and throws for unauthenticated requests