# Supabase: Die Open-Source Firebase Alternative für 2026 **Meta-Description:** Supabase als vollständige Backend-Plattform. PostgreSQL, Realtime, Auth, Edge Functions und Vector Embeddings in einem Stack. **Keywords:** Supabase, PostgreSQL, Realtime Database, Edge Functions, Authentication, Firebase Alternative, Vector Embeddings --- ## Einführung Supabase ist die **Open-Source Firebase Alternative**, die auf PostgreSQL aufbaut. 2026 bietet es eine vollständige Backend-Plattform: Database, Auth, Realtime, Edge Functions, Storage und Vector Embeddings – alles integriert. --- ## Supabase Stack ``` ┌─────────────────────────────────────────────────────────────┐ │ SUPABASE PLATFORM │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Database Layer: │ │ ├── PostgreSQL (Enterprise-Grade) │ │ ├── Row Level Security (RLS) │ │ ├── PostgREST (Auto-Generated APIs) │ │ └── pgvector (Vector Embeddings) │ │ │ │ Realtime Layer: │ │ ├── Postgres Changes (CDC) │ │ ├── Broadcast (User-to-User) │ │ ├── Presence (Online Status) │ │ └── WebSocket Connections │ │ │ │ Auth Layer: │ │ ├── Email/Password │ │ ├── OAuth Providers (Google, GitHub, etc.) │ │ ├── Magic Links │ │ └── Phone/SMS Auth │ │ │ │ Edge Functions: │ │ ├── Deno Runtime │ │ ├── TypeScript/JavaScript │ │ └── Global Distribution │ │ │ │ Storage: │ │ ├── S3-Compatible │ │ ├── CDN Integration │ │ └── Image Transformations │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Database Setup ```typescript // lib/supabase.ts import { createClient } from '@supabase/supabase-js'; import { Database } from './database.types'; const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!; const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!; export const supabase = createClient(supabaseUrl, supabaseAnonKey); // Server-Side mit Service Role import { createClient } from '@supabase/supabase-js'; export const supabaseAdmin = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!, { auth: { autoRefreshToken: false, persistSession: false } } ); ``` ### Schema Definition (SQL) ```sql -- Users Tabelle (erweitert auth.users) CREATE TABLE public.profiles ( id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY, username TEXT UNIQUE, full_name TEXT, avatar_url TEXT, bio TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Posts Tabelle CREATE TABLE public.posts ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, author_id UUID REFERENCES public.profiles(id) ON DELETE CASCADE NOT NULL, title TEXT NOT NULL, content TEXT, published BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Trigger für updated_at CREATE OR REPLACE FUNCTION update_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER profiles_updated_at BEFORE UPDATE ON public.profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at(); CREATE TRIGGER posts_updated_at BEFORE UPDATE ON public.posts FOR EACH ROW EXECUTE FUNCTION update_updated_at(); ``` --- ## Row Level Security (RLS) ```sql -- RLS aktivieren ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY; -- Profiles: Jeder kann lesen, nur Owner kann schreiben CREATE POLICY "Profiles sind öffentlich lesbar" ON public.profiles FOR SELECT USING (true); CREATE POLICY "User kann eigenes Profil bearbeiten" ON public.profiles FOR UPDATE USING (auth.uid() = id); -- Posts: Veröffentlichte sind lesbar, Autor kann alles CREATE POLICY "Veröffentlichte Posts sind lesbar" ON public.posts FOR SELECT USING (published = true OR auth.uid() = author_id); CREATE POLICY "Autor kann eigene Posts erstellen" ON public.posts FOR INSERT WITH CHECK (auth.uid() = author_id); CREATE POLICY "Autor kann eigene Posts bearbeiten" ON public.posts FOR UPDATE USING (auth.uid() = author_id); CREATE POLICY "Autor kann eigene Posts löschen" ON public.posts FOR DELETE USING (auth.uid() = author_id); ``` --- ## CRUD Operations ```typescript // CREATE async function createPost(post: { title: string; content: string }) { const { data, error } = await supabase .from('posts') .insert({ title: post.title, content: post.content, author_id: (await supabase.auth.getUser()).data.user?.id }) .select() .single(); if (error) throw error; return data; } // READ async function getPosts() { const { data, error } = await supabase .from('posts') .select(` *, author:profiles(username, avatar_url) `) .eq('published', true) .order('created_at', { ascending: false }) .limit(10); if (error) throw error; return data; } // READ mit Pagination async function getPostsPaginated(page: number, pageSize: number = 10) { const from = page * pageSize; const to = from + pageSize - 1; const { data, error, count } = await supabase .from('posts') .select('*, author:profiles(username)', { count: 'exact' }) .eq('published', true) .range(from, to); return { data, count, hasMore: count ? to < count - 1 : false }; } // UPDATE async function updatePost(id: string, updates: Partial) { const { data, error } = await supabase .from('posts') .update(updates) .eq('id', id) .select() .single(); if (error) throw error; return data; } // DELETE async function deletePost(id: string) { const { error } = await supabase .from('posts') .delete() .eq('id', id); if (error) throw error; } ``` --- ## Realtime Subscriptions ```typescript import { useEffect, useState } from 'react'; import { supabase } from '@/lib/supabase'; import { RealtimeChannel } from '@supabase/supabase-js'; // 1. Database Changes (CDC) function useRealtimePosts() { const [posts, setPosts] = useState([]); useEffect(() => { // Initial Load supabase.from('posts').select('*').then(({ data }) => { if (data) setPosts(data); }); // Subscribe to Changes const channel = supabase .channel('posts-changes') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'posts' }, (payload) => { if (payload.eventType === 'INSERT') { setPosts(prev => [payload.new as Post, ...prev]); } else if (payload.eventType === 'UPDATE') { setPosts(prev => prev.map(p => p.id === payload.new.id ? payload.new as Post : p) ); } else if (payload.eventType === 'DELETE') { setPosts(prev => prev.filter(p => p.id !== payload.old.id)); } } ) .subscribe(); return () => { supabase.removeChannel(channel); }; }, []); return posts; } // 2. Broadcast (User-to-User Messaging) function useBroadcast(roomId: string) { const [messages, setMessages] = useState([]); useEffect(() => { const channel = supabase.channel(`room:${roomId}`) .on('broadcast', { event: 'message' }, ({ payload }) => { setMessages(prev => [...prev, payload]); }) .subscribe(); return () => { supabase.removeChannel(channel); }; }, [roomId]); const sendMessage = (content: string) => { supabase.channel(`room:${roomId}`).send({ type: 'broadcast', event: 'message', payload: { content, timestamp: new Date().toISOString() } }); }; return { messages, sendMessage }; } // 3. Presence (Online Status) function usePresence(roomId: string, userId: string) { const [onlineUsers, setOnlineUsers] = useState([]); useEffect(() => { const channel = supabase.channel(`presence:${roomId}`) .on('presence', { event: 'sync' }, () => { const state = channel.presenceState(); const users = Object.values(state).flat().map(p => p.user_id); setOnlineUsers(users); }) .subscribe(async (status) => { if (status === 'SUBSCRIBED') { await channel.track({ user_id: userId }); } }); return () => { supabase.removeChannel(channel); }; }, [roomId, userId]); return onlineUsers; } ``` --- ## Authentication ```typescript // Sign Up async function signUp(email: string, password: string) { const { data, error } = await supabase.auth.signUp({ email, password, options: { emailRedirectTo: `${window.location.origin}/auth/callback` } }); return { data, error }; } // Sign In async function signIn(email: string, password: string) { const { data, error } = await supabase.auth.signInWithPassword({ email, password }); return { data, error }; } // OAuth Sign In async function signInWithOAuth(provider: 'google' | 'github') { const { data, error } = await supabase.auth.signInWithOAuth({ provider, options: { redirectTo: `${window.location.origin}/auth/callback` } }); return { data, error }; } // Sign Out async function signOut() { const { error } = await supabase.auth.signOut(); return { error }; } // Auth State Hook function useAuth() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setUser(session?.user ?? null); setLoading(false); }); const { data: { subscription } } = supabase.auth.onAuthStateChange( (_event, session) => { setUser(session?.user ?? null); } ); return () => subscription.unsubscribe(); }, []); return { user, loading }; } ``` --- ## Edge Functions ```typescript // supabase/functions/send-email/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'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type' }; serve(async (req) => { if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }); } try { const supabase = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! ); const { to, subject, body } = await req.json(); // Send email via Resend, SendGrid, etc. const response = await fetch('https://api.resend.com/emails', { method: 'POST', headers: { 'Authorization': `Bearer ${Deno.env.get('RESEND_API_KEY')}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ from: 'noreply@example.com', to, subject, html: body }) }); const result = await response.json(); return new Response(JSON.stringify(result), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } catch (error) { return new Response(JSON.stringify({ error: error.message }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } }); // Client-Side Aufruf const { data, error } = await supabase.functions.invoke('send-email', { body: { to: 'user@example.com', subject: 'Welcome!', body: '

Welcome to our platform!

' } }); ``` --- ## Vector Embeddings (AI) ```sql -- pgvector Extension aktivieren CREATE EXTENSION IF NOT EXISTS vector; -- Documents Tabelle mit Embeddings CREATE TABLE documents ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, content TEXT NOT NULL, embedding VECTOR(1536), -- OpenAI ada-002 Dimension metadata JSONB, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Index für schnelle Similarity Search CREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); -- Similarity Search Funktion CREATE OR REPLACE FUNCTION search_documents( query_embedding VECTOR(1536), match_count INT DEFAULT 5 ) RETURNS TABLE ( id UUID, content TEXT, similarity FLOAT ) AS $$ BEGIN RETURN QUERY SELECT documents.id, documents.content, 1 - (documents.embedding <=> query_embedding) AS similarity FROM documents ORDER BY documents.embedding <=> query_embedding LIMIT match_count; END; $$ LANGUAGE plpgsql; ``` ```typescript // Embedding generieren und speichern async function addDocument(content: string) { // Embedding via OpenAI const embeddingResponse = await openai.embeddings.create({ model: 'text-embedding-ada-002', input: content }); const embedding = embeddingResponse.data[0].embedding; // In Supabase speichern const { data, error } = await supabase .from('documents') .insert({ content, embedding }) .select() .single(); return data; } // Similarity Search async function searchDocuments(query: string) { // Query Embedding const embeddingResponse = await openai.embeddings.create({ model: 'text-embedding-ada-002', input: query }); const queryEmbedding = embeddingResponse.data[0].embedding; // Search via RPC const { data, error } = await supabase.rpc('search_documents', { query_embedding: queryEmbedding, match_count: 5 }); return data; } ``` --- ## Fazit Supabase bietet 2026: 1. **PostgreSQL Power**: Enterprise-DB mit RLS, Triggers, Functions 2. **Realtime Built-in**: CDC, Broadcast, Presence über WebSockets 3. **Edge Functions**: Deno-basiert, global verteilt 4. **Vector Search**: pgvector für AI/RAG-Anwendungen Eine vollständige Backend-Plattform für moderne Anwendungen. --- ## Bildprompts 1. "Database and real-time connections flowing together, Supabase architecture visualization" 2. "PostgreSQL elephant with real-time lightning bolts, modern database concept" 3. "Edge functions distributed globally on world map, serverless infrastructure" --- ## Quellen - [Supabase Documentation](https://supabase.com/docs) - [Supabase Features](https://supabase.com/features) - [Supabase GitHub](https://github.com/supabase/supabase) - [Supabase Review 2026](https://hackceleration.com/supabase-review/)