Template — Supabase schema + RLS + trigger
Cada SaaS necesita una tabla `profiles` extendiendo `auth.users` — es donde vives los datos propios del app (display_name, avatar, plan, flags). El template la trae con [[rls]] configurado y un trigger que la crea automáticamente cuando el usuario se registra.
Profiles + RLS + trigger "auto-create on signup" resuelven el 90% del schema inicial.
El schema base
`sql
create table profiles (
id uuid primary key references auth.users on delete cascade,
display_name text,
avatar_url text,
plan text default 'free',
created_at timestamp default now()
);
alter table profiles enable row level security;
create policy "select own" on profiles for select using (auth.uid() = id);
create policy "update own" on profiles for update using (auth.uid() = id);
`
El trigger que auto-crea profile
`sql
create function public.handle_new_user() returns trigger as $$
begin
insert into public.profiles (id) values (new.id);
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();
`
Así nunca tienes "usuario sin profile". El trigger garantiza 1:1.
Por qué importa la convención
Con el schema base definido, todas las otras tablas siguen el mismo patrón: user_id references auth.users + RLS con auth.uid() = user_id. El agente internaliza el patrón y lo aplica sin pensarlo.
En tu Supabase: ¿tienes tabla `profiles` con trigger auto-create? Si no, es deuda que crecerá con cada feature que use datos de usuario.
- `profiles` extiende `auth.users` con campos propios del app.
- RLS + policies "own" como default.
- Trigger `handle_new_user` garantiza profile creado en cada signup.