This documentation is for a legacy version of Remix and Supabase. For the latest version, please visit the Remix and Supabase V2 documentation

Guarding Pages | Remix Supabase SaaS Kit

Learn how to guard pages in your Remix Supabase application

As a server-side rendered application, Remix Supabase will always render the page on the server before sending it to the client.

We assume you are in the context of a specific organization, as it is the primary use case for the Starter Kit.

In the following example, we are loading the user role within the organization that is currently selected.

import { LoaderFunctionArgs } from "@remix-run/node";
async function loader(args: LoaderFunctionArgs) {
const data = await loadAppData(args);
const userRole = data.role;
// if the user is not an owner, redirect them to the home page
if (userRole !== MembershipRole.Owner) {
return redirect('/');
}
// return props to the page
}
async function OnlyOwnersPage() {
const data = await useLoaderData<typeof loader>();
// render the page
}

As you can see above:

  1. We are loading the data required to render the page
  2. We are checking the user role within the organization
  3. If the user is not an owner, we redirect them to the home page (but feel free to change this)

Guarding Application Pages with Organization Subscriptions

In this example, we want to make sure the Organization is subscribed to a plan before allowing the user to access the page.

To do so, we check the subscription property of the Organization object and redirect the user to the dashboard if the subscription is active or trialing.

import { LoaderFunctionArgs, redirect } from "@remix-run/node";
async function loader(args: LoaderFunctionArgs) {
const data = await loadAppData(args);
const status = data.organization.subscription?.data?.status;
// if the subscription is not active, redirect the user to the dashboard
if (!isSubscriptionActive(status)) {
return redirect('/');
}
// return props to the page
}
async function OnlySubscribersPage() {
const data = await useLoaderData<typeof loader>();
// render the page
}
function isSubscriptionActive(status: string | undefined) {
return ['trialing', 'active'].includes(status);
}