Time: 12 min | For: Backend (Database + Auth + Storage)
- Go to supabase.com → New Project
- Fill in:
- Name: Your app name
- Region: Closest to your users
- Password: Save it (for database access)
- Wait ~2 minutes for project creation
Go to Project Settings → API:
📋 Save these:
- Project URL:
https://yourproject.supabase.co - Anon Key:
eyJhbGciOiJIUzI1NiIsIn...
- Supabase: Dashboard → Authentication → Providers → Apple
- Toggle Enable
- Under Authorized Client IDs, paste your Bundle ID (from Xcode)
- Click Save
Already configured via Google OAuth Guide.
Go to SQL Editor and run these scripts:
create table public.profiles (
id uuid not null references auth.users on delete cascade,
email text,
full_name text,
avatar_url text,
updated_at timestamp with time zone,
primary key (id)
);alter table public.profiles enable row level security;
-- Public profiles viewable by everyone
create policy "Public profiles viewable"
on profiles for select using (true);
-- Users can insert own profile
create policy "Users insert own profile"
on profiles for insert with check (auth.uid() = id);
-- Users can update own profile
create policy "Users update own profile"
on profiles for update using (auth.uid() = id);create function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id, email, full_name, avatar_url)
values (
new.id,
new.raw_user_meta_data ->> 'email',
new.raw_user_meta_data ->> 'full_name',
new.raw_user_meta_data ->> 'avatar_url'
);
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();- Go to Storage → New bucket
- Name:
storage - Toggle Public bucket ON
- Click Create bucket
Go to Policies tab on the bucket:
-- Anyone can view files
create policy "Public Access"
on storage.objects for select
using (bucket_id = 'storage');
-- Authenticated users can upload
create policy "Authenticated users upload"
on storage.objects for insert
with check (bucket_id = 'storage' AND auth.role() = 'authenticated');
-- Users can update own files
create policy "Users update own files"
on storage.objects for update
using (auth.uid()::text = (storage.foldername(name))[1]);
-- Users can delete own files
create policy "Users delete own files"
on storage.objects for delete
using (auth.uid()::text = (storage.foldername(name))[1]);For admin operations like account deletion.
- In your project, create:
supabase/functions/delete-account/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req) => {
const supabaseClient = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
)
const authHeader = req.headers.get('Authorization')!
const token = authHeader.replace('Bearer ', '')
const { data: { user } } = await supabaseClient.auth.getUser(token)
if (!user) {
return new Response('Unauthorized', { status: 401 })
}
// Delete user
await supabaseClient.auth.admin.deleteUser(user.id)
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' }
})
})npx supabase functions deploy delete-account- Supabase project created
- API URL and anon key saved
- Apple Sign-In enabled
- Google Sign-In configured
- Profiles table created
- RLS policies enabled
- Storage bucket created (
storage) - Storage policies set
- Edge function deployed (optional)
Saved Values:
Supabase URL: https://yourproject.supabase.co
Anon Key: eyJhbGciOiJIUzI1NiIs...