Build authentication-secure membership platforms using Supabase’s PostgreSQL backend with Row Level Security and Webflow’s visual frontend.
This guide covers the steps to build a membership platform with Supabase as your backend and Webflow as your frontend.
Overview of integration architecture
The Webflow-Supabase integration uses client-side JavaScript and enforces database-level security via Row-Level Security policies, instead of relying on hiding API keys. Security happens at the database layer, not by hiding API keys.
The integration architecture follows this flow:
Data flows between platforms as JSON. Webflow sends authentication requests and receives JWT tokens from Supabase Auth. Database queries return JSON responses that respect the RLS policy.
The Anon key is safe for client-side use. RLS policies determine what data each user has access to.
Key integration components:
- Supabase JavaScript client initialized with your project URL and anon key
- Supabase Auth handles the authentication and returns JWT tokens
- Row-level security policies enforce access control at the database level
- Edge Functions perform privileged operations with the service role key
Requirements and account configuration
Before implementing the integration, you will need accounts on both platforms and your Supabase project details.
At a high level you will need:
- A Webflow account with custom code support
- A Supabase project (create via dashboard or CLI)
- Your Supabase project URL and anon key from Project settings > API
Your Supabase project provides two API keys:
Never expose the service role key in custom Webflow code or client-side JavaScript. Only use it indoors Edge functions or external backend services.
Step 1: Initialize the Supabase client in Webflow
The Supabase JavaScript client is loaded via CDN and initialized with your project data.
At a high level you will:
- Add the Supabase CDN script to your site-wide custom code
- Initialize the client with your project URL and anon key
- Configure session persistence and automatic token renewal
Add this code to Site settings > Custom code > Head:
>
<script>
const supabaseClient = supabase.createClient(
'https://your-project.supabase.co',
'your-anon-key',
{
auth: {
persistSession: true,
autoRefreshToken: true,
detectSessionInUrl: true
}
}
);
script>
Sessions remain in localStorage by default and tokens are automatically refreshed. See the Client initialization documentation for additional configuration options.
Step 2: Implement authentication flows
Supabase Auth supports multiple authentication methods including email/password, OAuth providers, and passwordless magic links.
At a high level you will:
OAuth providers are configured in your Supabase dashboard under Authentication > Providers. See the Social login guide for provider specific configuration.
Check the authentication status
Use the authentication status listener to respond to login and logout events:
supabaseClient.auth.onAuthStateChange((event, session) => {
if (event === 'SIGNED_IN') updateUIForAuthenticatedUser(session.user);
if (event === 'SIGNED_OUT') updateUIForGuest();
});
This listener works across all browser tabs and is activated when sessions are confirmed or re-established.
Step 3: Configure the membership database schema
Membership platforms require a profiles table linked to Supabase’s auth.users table to store user data.
At a high level you will:
- Create a profiles table with a foreign key reference to auth.users
- Set database triggers for automatic profile creation
- Optionally integrate Stripe data using the Stripe foreign data wrapper
Create a profiles table
Create the profiles table with the following schema:
CREATE TABLE public.profiles (
id UUID NOT NULL REFERENCES auth.users ON DELETE CASCADE,
first_name TEXT,
last_name TEXT,
avatar_url TEXT,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY(id)
);
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
The ON DELETE CASCADE throttling allows for automatic profile cleanup when users are deleted.
Automate profile creation with triggers
Create a trigger that automatically generates a profile when a new user signs in:
CREATE FUNCTION public.handle_new_user()
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = ''
AS $$
BEGIN
INSERT INTO public.profiles(id, first_name, last_name)
VALUES (NEW.id, NEW.raw_user_meta_data->>'first_name', NEW.raw_user_meta_data->>'last_name');
RETURN NEW;
END;
$$;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE PROCEDURE public.handle_new_user();This trigger automatically creates a profile record when a new user signs in.
Step 4: Implement row-level security policies
Row-level security policies are the primary security mechanism for Webflow-Supabase integrations. RLS provides database-level protection even if the anon key is visible in client-side code.
At a high level you will:
Profile access policy
Create policies that allow users to view and update their own profile information:
CREATE POLICY "User can see their own profile only."
ON profiles FOR SELECT
USING ((SELECT auth.uid()) = id);
CREATE POLICY "Users can update their own profile."
ON profiles FOR UPDATE TO authenticated
USING ((SELECT auth.uid()) = id)
WITH CHECK ((SELECT auth.uid()) = id);
CREATE INDEX idx_profiles_user_id ON public.profiles(id);The auth.uid() function returns the UUID of the authenticated user from the JWT token. The USING clause determines driving visibility, and WITH CHECK validates data changes.
#build #membership #platform #Supabase #Webflow #Webflow #blog

