Remix and Supabase Authentication

How to secure a Remix and Supabase application using Row Level Security

Thursday, December 9, 2021


NOTE: This tutorial is deprecated in favor of the official documentation.

Table of Contents

TL;DR: Source and Demo

Here's a live demo

Link to the source code

Link to step by step commits


This blog will focus on securing our Remix application with Supabase's Row Level Security (RLS) feature. If you want to know the context of what application I'm talking about, you can refer to my another blog.

Setting up Supabase

Instead of updating my database from the previous blog, I'm just going to re-create it.

Create a table to contain user_id

Add a foreign key in user_id pointing to auth.users

Create Row Level Security Supabase Policies

Implement server-side utilities to manage Supabase session

Create server instance of Supabase client

Use createCookieSessionStorage to help in managing our Supabase token

Create a utility to set the Supabase token from the Request

Setting up authentication in the Remix side

Create client-side utilities for managing Supabase session

Create Supabase Provider and a custom hook which returns the Supabase instance

Pass Supabase environment variables to our client

Create a Supabase instance and pass it into the root level Supabase provider

Create the /auth route

Since I'm too lazy to implement a login page, I'll just use the UI provided by Supabase.

Install @supabase/ui

Create the main auth component

You can create your custom sign-up and sign-in form if you want.

Create the component to inform the server that we have a Supabase session

Create an action handler to process the Supabase token

After logging in, the user will be redirected to the /words route.

If you want to test without signing up, use the following credentials:


password: testing

Signing out

Create a logout button in the header

Create an action handler

I don't want to pollute my other route, so I will create my signout action handler separately

TL;DR version of using our setup

Using in a loader or action

Conditional rendering based on auth state

NOTE: Conditional server-side rendering might cause hydration warning,

I'll fix this in another blog post.

Using in CRUD Operations

The examples below are a longer version of using our setup for CRUD operations.

Fetching All operation

Retrieve one and Delete one operation

Create operation

Update operation


We can still use Supabase only on the client-side as we use it on a typical React application. However, putting the data fetching on the server-side will allow us to benefit from a typical SSR application.