-- RIOTZ SUPABASE DATABASE SCHEMA -- Tech Stack: PostgreSQL, Supabase Auth, Storage -- 1. EXTENSIONS create extension if not exists "uuid-ossp"; -- 2. TABLES -- PROFILES: Core user identity create table public.profiles ( user_id uuid references auth.users on delete cascade primary key, username text unique not null, bio text, avatar_url text, featured boolean default false, banned boolean default false, created_at timestamp with time zone default now(), updated_at timestamp with time zone default now() ); -- POSTS: Visual manifestations create table public.posts ( id uuid default uuid_generate_v4() primary key, user_id uuid references public.profiles(user_id) on delete cascade not null, image_url text not null, caption text, likes_count int default 0, featured boolean default false, created_at timestamp with time zone default now() ); -- POST LIKES: Engagement tracking create table public.post_likes ( user_id uuid references public.profiles(user_id) on delete cascade not null, post_id uuid references public.posts(id) on delete cascade not null, created_at timestamp with time zone default now(), primary key (user_id, post_id) ); -- TRACKS: Sonic broadcasts create table public.tracks ( id uuid default uuid_generate_v4() primary key, user_id uuid references public.profiles(user_id) on delete cascade not null, title text not null, audio_url text not null, genre_tag text default 'UNKNOWN', plays int default 0, featured boolean default false, created_at timestamp with time zone default now() ); -- COMMENTS: Chaos discourse create table public.comments ( id uuid default uuid_generate_v4() primary key, post_id uuid references public.posts(id) on delete cascade not null, user_id uuid references public.profiles(user_id) on delete cascade not null, content text not null, created_at timestamp with time zone default now() ); -- BANS: Network exclusion records create table public.bans ( id uuid default uuid_generate_v4() primary key, user_id uuid references public.profiles(user_id) on delete cascade not null, reason text, banned_by uuid references public.profiles(user_id), created_at timestamp with time zone default now() ); -- FEATURED CONTENT: Curated highlights create table public.featured_content ( id uuid default uuid_generate_v4() primary key, content_type text not null check (content_type in ('artist', 'post', 'track')), content_id uuid not null, priority int default 0, created_at timestamp with time zone default now() ); -- 3. FUNCTIONS & TRIGGERS -- Automatically create profile on signup create or replace function public.handle_new_user() returns trigger as $$ begin insert into public.profiles (user_id, username, avatar_url) values (new.id, split_part(new.email, '@', 1), 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(); -- Auto-update likes_count on posts create or replace function public.update_post_likes_count() returns trigger as $$ begin if (TG_OP = 'INSERT') then update public.posts set likes_count = likes_count + 1 where id = new.post_id; elsif (TG_OP = 'DELETE') then update public.posts set likes_count = likes_count - 1 where id = old.post_id; end if; return null; end; $$ language plpgsql security definer; create trigger on_like_changed after insert or delete on public.post_likes for each row execute procedure public.update_post_likes_count(); -- Increment plays RPC create or replace function public.increment_track_plays(track_id uuid) returns void as $$ begin update public.tracks set plays = plays + 1 where id = track_id; end; $$ language plpgsql security definer; -- 4. SECURITY (RLS) alter table public.profiles enable row level security; alter table public.posts enable row level security; alter table public.tracks enable row level security; alter table public.post_likes enable row level security; alter table public.comments enable row level security; -- Profiles: Public read, owner update create policy "Public profiles are viewable by everyone." on public.profiles for select using (true); create policy "Users can update own profile." on public.profiles for update using (auth.uid() = user_id); -- Posts: Public read, Auth create, Owner delete create policy "Posts are viewable by everyone." on public.posts for select using (true); create policy "Authenticated users can create posts." on public.posts for insert with check (auth.role() = 'authenticated'); create policy "Users can delete own posts." on public.posts for delete using (auth.uid() = user_id); -- Tracks: Public read, Auth create create policy "Tracks are viewable by everyone." on public.tracks for select using (true); create policy "Authenticated users can upload tracks." on public.tracks for insert with check (auth.role() = 'authenticated'); -- Likes: Authenticated management create policy "Users can view likes." on public.post_likes for select using (true); create policy "Users can manage own likes." on public.post_likes for all using (auth.uid() = user_id); -- 5. INDEXES for Performance create index idx_posts_user_id on public.posts(user_id); create index idx_posts_created_at on public.posts(created_at desc); create index idx_tracks_plays on public.tracks(plays desc); create index idx_comments_post_id on public.comments(post_id);