BuildBaseBuildBase

Protected Routes

Guard routes and UI sections based on authentication state.

There are several patterns for protecting routes. Pick the one that fits your app structure.

import { WhenAuthenticated, WhenUnauthenticated } from '@buildbase/sdk/react';

function Page() {
  return (
    <>
      <WhenAuthenticated>
        <Dashboard />
      </WhenAuthenticated>
      <WhenUnauthenticated>
        <LoginPage />
      </WhenUnauthenticated>
    </>
  );
}

Pattern 1: Component wrapping

Wrap sections of your UI with WhenAuthenticated and WhenUnauthenticated. This is the simplest approach for pages with mixed content.

import { WhenAuthenticated, WhenUnauthenticated } from '@buildbase/sdk/react';

function HomePage() {
  return (
    <div>
      <h1>Welcome to the app</h1>

      <WhenAuthenticated>
        <p>
          You are signed in. Go to your <a href="/dashboard">Dashboard</a>.
        </p>
      </WhenAuthenticated>

      <WhenUnauthenticated>
        <p>Sign in to access your dashboard.</p>
      </WhenUnauthenticated>
    </div>
  );
}

Handling the loading flash

WhenAuthenticated and WhenUnauthenticated render nothing while the session is resolving (unless you pass loadingComponent — see below). If you see a flash of the wrong UI, add an explicit loading check:

import {
  useSaaSAuth,
  WhenAuthenticated,
  WhenUnauthenticated,
} from '@buildbase/sdk/react';

function HomePage() {
  const { isLoading } = useSaaSAuth();

  if (isLoading) return <Spinner />;

  return (
    <>
      <WhenAuthenticated>
        <Dashboard />
      </WhenAuthenticated>
      <WhenUnauthenticated>
        <LandingPage />
      </WhenUnauthenticated>
    </>
  );
}

Pattern 2: Redirect unauthenticated users

Use useSaaSAuth() with your router to redirect users who are not signed in.

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useSaaSAuth } from '@buildbase/sdk/react';

function SettingsPage() {
  const { status, isAuthenticated } = useSaaSAuth();
  const router = useRouter();

  useEffect(() => {
    if (status !== 'loading' && !isAuthenticated) {
      router.push('/login');
    }
  }, [status, isAuthenticated, router]);

  if (!isAuthenticated) return null;

  return <div>Settings content</div>;
}

Pattern 3: Layout-level protection

Protect an entire section of your app by wrapping the layout instead of individual pages. Every page under this layout is automatically guarded.

import {
  useSaaSAuth,
  WhenAuthenticated,
  WhenUnauthenticated,
} from '@buildbase/sdk/react';

function ProtectedLayout({ children }: { children: React.ReactNode }) {
  const { signIn } = useSaaSAuth();

  return (
    <>
      <WhenAuthenticated>
        <nav>Dashboard Nav</nav>
        <main>{children}</main>
      </WhenAuthenticated>

      <WhenUnauthenticated>
        <div>
          <p>You must sign in to continue.</p>
          <button onClick={() => signIn()}>Sign In</button>
        </div>
      </WhenUnauthenticated>
    </>
  );
}

Now every page under this layout (/dashboard, /dashboard/settings, /dashboard/billing) is protected without repeating auth checks.

loadingComponent and fallbackComponent

Both WhenAuthenticated and WhenUnauthenticated accept two optional props:

PropTypeDefaultDescription
loadingComponentReact.ReactNodenullRendered while the auth status resolves
fallbackComponentReact.ReactNodenullRendered when the condition is not met
import { WhenAuthenticated } from '@buildbase/sdk/react';

function DashboardPage() {
  return (
    <WhenAuthenticated
      loadingComponent={<Spinner />}
      fallbackComponent={<LandingPage />}
    >
      <Dashboard />
    </WhenAuthenticated>
  );
}

Pattern 4: Permission-gated sections

Once a user is authenticated, you may need to restrict parts of the UI based on their permissions. Use WhenPermission to conditionally render based on roles.

import {
  Permission,
  WhenAuthenticated,
  WhenPermission,
} from '@buildbase/sdk/react';

function Dashboard() {
  return (
    <WhenAuthenticated>
      <h1>Dashboard</h1>

      <WhenPermission permission={Permission.WORKSPACE_SETTINGS_EDIT}>
        <a href="/dashboard/admin">Admin Dashboard</a>
      </WhenPermission>

      <WhenPermission permission={Permission.WORKSPACE_BILLING_VIEW}>
        <a href="/dashboard/billing">Billing</a>
      </WhenPermission>
    </WhenAuthenticated>
  );
}

Tip

Permission checks only work inside WhenAuthenticated or after confirming isAuthenticated is true. WhenPermission resolves against the user's role in the current workspace — the same data usePermissions() returns.

When to use which pattern

PatternBest forTrade-off
Component wrappingPages with mixed public/private contentMore markup per page
RedirectHard-gated pages where unauthenticated users should not see any contentRequires router integration
Layout-levelApp sections where every nested route needs authAll-or-nothing — no mixed content
Permission-gatedShowing/hiding features based on rolesRequires permissions to be configured in the dashboard

Next Steps