Skip to main content

Supabase Setup

Complete guide for setting up Supabase as your database and authentication provider for SvelteBolt.

Create Supabase Account

  1. Go to supabase.com
  2. Click Start your project
  3. Sign up with GitHub, Google, or email
  4. Verify your email if required

Create New Project

  1. Click + New Project
  2. Choose your organization (or create one)
  3. Fill in project details:
    • Name: sveltebolt-app (or your preferred name)
    • Database Password: Generate a strong password (save it!)
    • Region: Choose closest to your users
  4. Click Create new project
  5. Wait 2-3 minutes for setup to complete

Get API Keys

Once your project is ready:

  1. Go to Project SettingsData API and API Keys
  2. Copy these values to your .env file:
    PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
    PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6...
    SUPABASE_SERVICE_ROLE_SECRET=eyJhbGciOiJIUzI1NiIsInR5cCI6...

Database Schema Setup

SvelteBolt includes database migrations. Apply them to your Supabase project:

  1. Install Supabase CLI:

    npm install -g supabase
  2. Login to Supabase:

    supabase login
  3. Link your project:

    supabase link --project-ref your-project-id
  4. Apply migrations:

    supabase db push

Option 2: Manual SQL Setup

  1. Go to your Supabase dashboard
  2. Navigate to SQL Editor
  3. Copy and run this SQL:
-- Create table for public profiles
create table public.profiles (
id uuid not null references auth.users on delete cascade,
name text,
avatar_url text,
bio text,
company_name text,
website text,
primary key (id)
);
-- Create table for subscriptions
create table public.subscriptions (
id uuid primary key default gen_random_uuid(),
user_id uuid references auth.users on delete cascade,
customer_id text unique,
email text unique,
status text,
plan text,
interval text,
amount numeric(10, 2),
current_period_end timestamp with time zone,
cancel_at_period_end boolean,
updated_at timestamp with time zone
);
-- Create table for contact requests
create table public.contact_requests (
id uuid primary key default gen_random_uuid(),
name text,
email text,
message text,
created_at timestamp with time zone default now()
);
-- Enable Row Level Security
alter table public.profiles enable row level security;
alter table public.subscriptions enable row level security;
alter table public.contact_requests enable row level security;
--- Policies
CREATE POLICY "Can only view own profile data." ON public.profiles FOR
SELECT USING (auth.uid() = id);
--
CREATE POLICY "Can only update own profile data." ON public.profiles FOR
UPDATE USING (auth.uid() = id);
--
CREATE POLICY "Can only view own subscription" ON public.subscriptions FOR
SELECT TO authenticated USING (auth.uid() = user_id);
--
CREATE POLICY "Allow anyone to create contact requests" ON public.contact_requests FOR
INSERT TO authenticated,
anon WITH CHECK (true);
-- Create Function to create profile
CREATE FUNCTION public.create_profile() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER
SET search_path = public AS $$ BEGIN
INSERT INTO public.profiles (id, name, bio, avatar_url, company_name, website)
VALUES (
NEW.id,
NEW.raw_user_meta_data->>'name',
NEW.raw_user_meta_data->>'bio',
NEW.raw_user_meta_data->>'avatar_url',
NEW.raw_user_meta_data->>'company_name',
NEW.raw_user_meta_data->>'website'
);
RETURN NEW;
END;
$$;
-- Create Trigger to create profile
CREATE TRIGGER create_profile_trigger
AFTER
INSERT ON auth.users FOR each ROW EXECUTE PROCEDURE public.create_profile();
-- Create storage bucket for avatars
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
-- Allow authenticated users to insert files into the avatars bucket
CREATE POLICY "Allow authenticated users to insert files into avatars bucket" ON storage.objects FOR
INSERT WITH CHECK (
auth.uid() IS NOT NULL
AND bucket_id = 'avatars'
);
-- Allow authenticated users to update their own files in the avatars bucket
CREATE POLICY "Allow authenticated users to update their own files in avatars bucket" ON storage.objects FOR
UPDATE USING (
auth.uid() = owner
AND bucket_id = 'avatars'
);
-- Allow authenticated users to select their own files in the avatars bucket
CREATE POLICY "Allow authenticated users to select their own files in avatars bucket" ON storage.objects FOR
SELECT USING (
auth.uid() = owner
AND bucket_id = 'avatars'
);
-- Allow authenticated users to delete their own files in the avatars bucket
CREATE POLICY "Allow authenticated users to delete their own files in avatars bucket" ON storage.objects FOR DELETE USING (
auth.uid() = owner
AND bucket_id = 'avatars'
);
-- Create function to update subscription when a new user is created
-- This covers the case where a user subscribes before creating an account
CREATE OR REPLACE FUNCTION public.update_subscription_on_user_creation() RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER AS $$ BEGIN -- Update existing subscription with user_id if email matches
UPDATE public.subscriptions
SET user_id = NEW.id
WHERE email = NEW.email
AND user_id IS NULL;
RETURN NEW;
END;
$$;
-- Create trigger to call the function after user insertion
CREATE TRIGGER update_subscription_trigger
AFTER
INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.update_subscription_on_user_creation();

Enable Email Authentication

  1. Go to AuthenticationURL Configuration
  2. Under Site URL, add your domain:
    • Development: http://localhost:5173
    • Production: https://yourdomain.com
  3. Under Redirect URLs, add:
    • http://localhost:5173/api/auth/callback
    • https://yourdomain.com/api/auth/callback

Add Email Templates

  1. Go to AuthenticationEmails

Confirm signup

<h2>Confirm your signup</h2>
<p>Follow this link to confirm your user:</p>
<p><a href="{{ .SiteURL }}/api/auth/confirm?token_hash={{ .TokenHash }}&type=email">Confirm your mail</a></p>

Password reset

<h2>Reset Password</h2>

<p>Follow this link to reset the password for your user:</p>
<p>
<a
href="{{ .SiteURL }}/api/auth/confirm?token_hash={{ .TokenHash }}&type=recovery&next=/dashboard/settings/account/update-password"
>Reset Password</a
>
</p>
<h2>Magic Link</h2>

<p>Follow this link to login:</p>
<p><a href="{{ .SiteURL }}/api/auth/confirm?token_hash={{ .TokenHash }}&type=magiclink">Log In</a></p>

Configure Social Login (Optional)

SvelteBolt comes pre-configured with Google, GitHub, and Twitter OAuth providers. To enable them:

Quick Setup

  1. Go to AuthenticationProviders in your Supabase dashboard
  2. Enable the providers you want to use
  3. Add your OAuth app credentials from each provider
  4. Use the redirect URL format: https://your-project-id.supabase.co/auth/v1/callback

Example: Google OAuth Setup

  1. Go to AuthenticationProviders
  2. Enable Google
  3. Add your Google OAuth credentials:
    • Client ID: From Google Cloud Console
    • Client Secret: From Google Cloud Console
  4. Add redirect URL to Google Cloud Console:
    • https://your-project-id.supabase.co/auth/v1/callback

Example: GitHub OAuth Setup

  1. Enable GitHub in providers
  2. Add GitHub OAuth app credentials
  3. Set redirect URL in GitHub app settings

Adding More Providers

SvelteBolt supports all Supabase OAuth providers including Discord, LinkedIn, Microsoft, and more.

📖 For detailed instructions on adding new OAuth providers, see the Authentication Guide

Test Database Connection

  1. Start your SvelteBolt development server:

    bun run dev
  2. Visit http://localhost:5173

  3. Try signing up with an email

  4. Check your Supabase dashboard → AuthenticationUsers

  5. Verify the user appears and a profile is created

Production Considerations

  • Backups: Enable automatic backups in project settings
  • Database Size: Monitor usage in dashboard
  • Rate Limiting: Configure in project settings
  • Custom Domain: Set up custom domain for auth emails
  • Environment: Use separate projects for dev/staging/prod

Troubleshooting

Connection Issues:

  • Verify API keys are correct
  • Check project is not paused
  • Ensure database password is correct

Authentication Issues:

  • Verify redirect URLs are configured
  • Check email templates are enabled
  • Confirm site URL matches your domain

Migration Issues:

  • Run migrations one at a time if errors occur
  • Check for syntax errors in SQL
  • Verify you have proper permissions

Next Steps