> ## Documentation Index
> Fetch the complete documentation index at: https://help.emergent.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Supabase Integration In Emergent

## Overview

Supabase is an open-source Firebase alternative that provides PostgreSQL database, authentication, real-time subscriptions, and storage. This guide walks you through integrating Supabase into your Emergent application.

<Tip>
  Supabase is perfect when you need a powerful relational database with real-time capabilities and built-in authentication.
</Tip>

## What You'll Build

By the end of this guide, you'll have:

* Supabase PostgreSQL database connected
* CRUD operations for your data
* Real-time subscriptions (optional)
* Supabase Authentication (optional)
* File storage (optional)

## Prerequisites

<Steps>
  <Step title="Supabase Account">
    Create a free account at [supabase.com](https://supabase.com)
  </Step>

  <Step title="Create Project">
    Create a new Supabase project
  </Step>

  <Step title="Get Credentials">
    Copy your project URL and API keys
  </Step>
</Steps>

***

## Step 1: Create Supabase Project & Get Credentials

### Create Supabase Project

1. Go to [https://supabase.com](https://supabase.com)
2. Sign up or log in
3. Click **New Project**
4. Fill in project details:
   * **Name:** Your project name
   * **Database Password:** Strong password (save this!)
   * **Region:** Choose closest to your users
5. Click **Create new project**
6. Wait \~2 minutes for project initialization

### Get Your Credentials

1. Once project is ready, go to **Settings** → **API**
2. Copy these three values:

<CardGroup cols={3}>
  <Card title="Project URL" icon="link">
    **Format:** `https://xxxxx.supabase.co`

    **Use:** Both frontend and backend
  </Card>

  <Card title="Anon (Public) Key" icon="eye">
    **Starts with:** `eyJhbGci...`

    **Use:** Frontend (safe to expose)

    **Length:** Very long JWT token
  </Card>

  <Card title="Service Role Key" icon="key">
    **Starts with:** `eyJhbGci...`

    **Use:** Backend (keep secret!)

    **Note:** Has full database access
  </Card>
</CardGroup>

<Warning>
  **Never expose the Service Role Key in frontend!** It bypasses all security rules.
</Warning>

## Step 2: Request Integration from Emergent Agent

### Basic Database Integration

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
I need to integrate Supabase PostgreSQL database:

Purpose: Replace MongoDB with PostgreSQL for [your use case]

Supabase Credentials:
- Project URL: https://xxxxx.supabase.co
- Anon Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
- Service Role Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Database Tables Needed:
- users: id (uuid), email (text), name (text), created_at (timestamp)
- posts: id (uuid), user_id (uuid), title (text), content (text), created_at (timestamp)
- comments: id (uuid), post_id (uuid), user_id (uuid), content (text), created_at (timestamp)

Features Required:
- CRUD operations for all tables
- Backend API endpoints
- Frontend client for data fetching
- Foreign key relationships

Technical Setup:
- Backend: Supabase Python client for API endpoints
- Frontend: Supabase JS client for direct queries
- Create SQL migration script for tables

Please call integration_playbook_expert for Supabase setup.
```

### With Authentication

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
I need Supabase with database and authentication:

Purpose: PostgreSQL database + Google social login

Supabase Credentials:
- Project URL: https://xxxxx.supabase.co
- Anon Key: eyJhbGci...
- Service Role Key: eyJhbGci...

Database Tables:
[List your tables]

Authentication:
- Google social login
- Email/password signup
- Protected routes
- User session management

Setup:
- Backend: API with Supabase auth
- Frontend: Login UI + auth context
- Database: User profiles table

Please call integration_playbook_expert.
```

### With Real-Time Features

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
I need Supabase with real-time subscriptions:

Purpose: Chat app with real-time message updates

Supabase Credentials:
- Project URL: https://xxxxx.supabase.co
- Anon Key: eyJhbGci...
- Service Role Key: eyJhbGci...

Real-Time Features:
- Subscribe to new messages
- Live updates without refresh
- Typing indicators
- Online presence

Database Tables:
- messages: id, room_id, user_id, content, created_at
- rooms: id, name, created_at

Setup:
- Backend: Message API endpoints
- Frontend: Real-time subscription to messages table

Please call integration_playbook_expert.
```

## Step 3: What the Integration Agent Will Create

### Backend Implementation

**`1. Environment Variables (/app/backend/.env)`**

```env theme={"theme":{"light":"github-light","dark":"dracula"}}
SUPABASE_URL=https://xxxxx.supabase.co
SUPABASE_KEY=your_service_role_key_here
```

**2. Supabase Client Setup**

```python theme={"theme":{"light":"github-light","dark":"dracula"}}
from supabase import create_client, Client
import os

supabase_url = os.environ.get("SUPABASE_URL")
supabase_key = os.environ.get("SUPABASE_KEY")
supabase: Client = create_client(supabase_url, supabase_key)
```

**3. API Endpoints**

<Accordion title="Get All Records">
  ```python theme={"theme":{"light":"github-light","dark":"dracula"}}
  @app.get("/api/users")
  async def get_users():
      try:
          response = supabase.table('users').select("*").execute()
          return {"users": response.data}
      except Exception as e:
          return {"error": str(e)}
  ```
</Accordion>

<Accordion title="Create Record">
  ```python theme={"theme":{"light":"github-light","dark":"dracula"}}
  @app.post("/api/users")
  async def create_user(user_data: dict):
      try:
          response = supabase.table('users').insert(user_data).execute()
          return {"user": response.data[0]}
      except Exception as e:
          return {"error": str(e)}
  ```
</Accordion>

<Accordion title="Update Record">
  ```python theme={"theme":{"light":"github-light","dark":"dracula"}}
  @app.put("/api/users/{user_id}")
  async def update_user(user_id: str, user_data: dict):
      try:
          response = supabase.table('users').update(user_data).eq('id', user_id).execute()
          return {"user": response.data[0]}
      except Exception as e:
          return {"error": str(e)}
  ```
</Accordion>

<Accordion title="Delete Record">
  ```python theme={"theme":{"light":"github-light","dark":"dracula"}}
  @app.delete("/api/users/{user_id}")
  async def delete_user(user_id: str):
      try:
          response = supabase.table('users').delete().eq('id', user_id).execute()
          return {"message": "User deleted successfully"}
      except Exception as e:
          return {"error": str(e)}
  ```
</Accordion>

<Accordion title="Complex Query with Joins">
  ```python theme={"theme":{"light":"github-light","dark":"dracula"}}
  @app.get("/api/posts-with-users")
  async def get_posts_with_users():
      try:
          response = supabase.table('posts').select(
              "*, users(id, name, email)"
          ).execute()
          return {"posts": response.data}
      except Exception as e:
          return {"error": str(e)}
  ```
</Accordion>

### Frontend Implementation

**`1. Environment Variables (/app/frontend/.env)`**

```env theme={"theme":{"light":"github-light","dark":"dracula"}}
REACT_APP_SUPABASE_URL=https://xxxxx.supabase.co
REACT_APP_SUPABASE_ANON_KEY=your_anon_key_here
```

**2. Supabase Client Setup**

```javascript theme={"theme":{"light":"github-light","dark":"dracula"}}
// src/supabaseClient.js
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.REACT_APP_SUPABASE_URL
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY

export const supabase = createClient(supabaseUrl, supabaseAnonKey)
```

**3. Using Supabase in Components**

<Accordion title="Fetch Data">
  ```javascript theme={"theme":{"light":"github-light","dark":"dracula"}}
  import { supabase } from './supabaseClient'
  import { useState, useEffect } from 'react'

  function UsersList() {
    const [users, setUsers] = useState([])
    const [loading, setLoading] = useState(true)
    
    useEffect(() => {
      fetchUsers()
    }, [])
    
    const fetchUsers = async () => {
      try {
        const { data, error } = await supabase
          .from('users')
          .select('*')
          .order('created_at', { ascending: false })
        
        if (error) throw error
        setUsers(data)
      } catch (error) {
        console.error('Error fetching users:', error)
      } finally {
        setLoading(false)
      }
    }
    
    if (loading) return <div>Loading...</div>
    
    return (
      <div>
        {users.map(user => (
          <div key={user.id}>
            <h3>{user.name}</h3>
            <p>{user.email}</p>
          </div>
        ))}
      </div>
    )
  }
  ```
</Accordion>

<Accordion title="Insert Data">
  ```javascript theme={"theme":{"light":"github-light","dark":"dracula"}}
  const createUser = async (userData) => {
    try {
      const { data, error } = await supabase
        .from('users')
        .insert([userData])
        .select()
      
      if (error) throw error
      
      console.log('User created:', data[0])
      return data[0]
    } catch (error) {
      console.error('Error creating user:', error)
    }
  }

  // Usage
  await createUser({
    name: 'John Doe',
    email: 'john@example.com'
  })
  ```
</Accordion>

<Accordion title="Real-Time Subscription">
  ```javascript theme={"theme":{"light":"github-light","dark":"dracula"}}
  import { useEffect, useState } from 'react'
  import { supabase } from './supabaseClient'

  function RealTimeMessages() {
    const [messages, setMessages] = useState([])
    
    useEffect(() => {
      // Fetch initial messages
      fetchMessages()
      
      // Subscribe to new messages
      const subscription = supabase
        .channel('messages')
        .on('postgres_changes', 
          { 
            event: 'INSERT', 
            schema: 'public', 
            table: 'messages' 
          },
          (payload) => {
            console.log('New message:', payload.new)
            setMessages(prev => [payload.new, ...prev])
          }
        )
        .subscribe()
      
      // Cleanup
      return () => {
        subscription.unsubscribe()
      }
    }, [])
    
    const fetchMessages = async () => {
      const { data } = await supabase
        .from('messages')
        .select('*')
        .order('created_at', { ascending: false })
      
      setMessages(data || [])
    }
    
    return (
      <div>
        {messages.map(msg => (
          <div key={msg.id}>{msg.content}</div>
        ))}
      </div>
    )
  }
  ```
</Accordion>

## Step 4: Create Database Tables in Supabase

### Method 1: Using Supabase Dashboard (Recommended)

<Steps>
  <Step title="Open Table Editor">
    In Supabase Dashboard, click **Table Editor** in sidebar
  </Step>

  <Step title="Create New Table">
    Click **Create a new table**
  </Step>

  <Step title="Define Table">
    * **Name:** users
    * **Enable Row Level Security:** Check or uncheck
    * **Columns:** Define your columns
  </Step>

  <Step title="Add Columns">
    Click **Add column** for each field:

    * id (uuid, primary key, default: gen\_random\_uuid())
    * name (text)
    * email (text)
    * created\_at (timestamptz, default: now())
  </Step>

  <Step title="Save Table">
    Click **Save** to create the table
  </Step>
</Steps>

### Method 2: Using SQL Editor

1. Go to **SQL Editor** in Supabase Dashboard
2. Create a new query
3. Run this SQL:

```sql theme={"theme":{"light":"github-light","dark":"dracula"}}
-- Create users table
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Create posts table
CREATE TABLE posts (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES users(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  content TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Create comments table
CREATE TABLE comments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
  user_id UUID REFERENCES users(id) ON DELETE CASCADE,
  content TEXT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Create indexes for better performance
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_comments_post_id ON comments(post_id);
CREATE INDEX idx_comments_user_id ON comments(user_id);
```

### Method 3: Ask Agent to Generate SQL

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
Can you create SQL migration for Supabase with these tables:

**users table:**
- id (uuid, primary key)
- email (text, unique)
- name (text)
- avatar_url (text, nullable)
- created_at (timestamp)

**posts table:**
- id (uuid, primary key)
- user_id (uuid, foreign key to users)
- title (text)
- content (text)
- published (boolean, default false)
- created_at (timestamp)

**tags table:**
- id (uuid, primary key)
- name (text, unique)

**post_tags table (many-to-many):**
- post_id (uuid, foreign key to posts)
- tag_id (uuid, foreign key to tags)
- primary key (post_id, tag_id)

Include indexes for foreign keys and commonly queried fields.
```

## Step 5: Enable Real-Time (Optional)

### Enable Real-Time for Tables

1. In Supabase Dashboard, go to **Database** → **Replication**
2. Find your table (e.g., "messages")
3. Toggle **Real-time** to enabled
4. Click **Save**

### Frontend Real-Time Subscription

Already shown in Step 3 - Frontend Implementation section.

## Step 6: Setup Row Level Security (RLS)

<Warning>
  **Production Security:** Always enable RLS for production apps to protect your data.
</Warning>

### What is RLS?

Row Level Security allows you to restrict which rows users can see and modify based on policies.

### Enable RLS

1. Go to **Authentication** → **Policies**
2. Select your table
3. Click **Enable RLS**

### Create Policies

**Example: Users can only see their own data**

```sql theme={"theme":{"light":"github-light","dark":"dracula"}}
-- Policy: Users can read their own posts
CREATE POLICY "Users can view own posts"
  ON posts
  FOR SELECT
  USING (auth.uid() = user_id);

-- Policy: Users can insert their own posts
CREATE POLICY "Users can create posts"
  ON posts
  FOR INSERT
  WITH CHECK (auth.uid() = user_id);

-- Policy: Users can update their own posts
CREATE POLICY "Users can update own posts"
  ON posts
  FOR UPDATE
  USING (auth.uid() = user_id);

-- Policy: Users can delete their own posts
CREATE POLICY "Users can delete own posts"
  ON posts
  FOR DELETE
  USING (auth.uid() = user_id);
```

**Example: Public read, authenticated write**

```sql theme={"theme":{"light":"github-light","dark":"dracula"}}
-- Anyone can read posts
CREATE POLICY "Public posts are visible"
  ON posts
  FOR SELECT
  USING (published = true);

-- Authenticated users can create posts
CREATE POLICY "Authenticated users can create posts"
  ON posts
  FOR INSERT
  TO authenticated
  WITH CHECK (true);
```

## Step 7: Setup Supabase Authentication (Optional)

### Enable Auth Providers

1. Go to **Authentication** → **Providers**
2. Enable desired providers:
   * Email/Password
   * Google
   * GitHub
   * etc.

### Google OAuth Setup

<Steps>
  <Step title="Get Google Credentials">
    Create OAuth app in Google Cloud Console
  </Step>

  <Step title="Configure in Supabase">
    Add Client ID and Secret in Supabase
  </Step>

  <Step title="Set Redirect URL">
    Add redirect URL to Google OAuth app
  </Step>
</Steps>

### Frontend Auth Implementation

```javascript theme={"theme":{"light":"github-light","dark":"dracula"}}
import { supabase } from './supabaseClient'

// Sign up with email
const signUp = async (email, password) => {
  const { data, error } = await supabase.auth.signUp({
    email,
    password,
  })
  if (error) console.error('Error:', error)
  return data
}

// Sign in with email
const signIn = async (email, password) => {
  const { data, error } = await supabase.auth.signInWithPassword({
    email,
    password,
  })
  if (error) console.error('Error:', error)
  return data
}

// Sign in with Google
const signInWithGoogle = async () => {
  const { data, error } = await supabase.auth.signInWithOAuth({
    provider: 'google',
  })
}

// Sign out
const signOut = async () => {
  const { error } = await supabase.auth.signOut()
}

// Get current user
const getUser = async () => {
  const { data: { user } } = await supabase.auth.getUser()
  return user
}
```

## Step 8: Test the Integration

<Steps>
  <Step title="Start Preview">
    Click Preview in Emergent
  </Step>

  <Step title="Test Database Operations">
    * Try creating a record
    * Fetch and display records
    * Update a record
    * Delete a record
  </Step>

  <Step title="Check Supabase Dashboard">
    Verify data appears in Supabase Table Editor
  </Step>

  <Step title="Test Real-Time (if enabled)">
    * Open app in two browser windows
    * Create record in one
    * Should appear in other instantly
  </Step>

  <Step title="Test Auth (if configured)">
    * Try signing up
    * Try logging in
    * Check protected routes
  </Step>
</Steps>

## Step 9: Deploy

### Configure Environment Variables

In Emergent deployment settings, add:

**Backend:**

```
SUPABASE_URL=https://xxxxx.supabase.co
SUPABASE_KEY=your_service_role_key
```

**Frontend:**

```
REACT_APP_SUPABASE_URL=https://xxxxx.supabase.co
REACT_APP_SUPABASE_ANON_KEY=your_anon_key
```

### Pre-Deployment Checklist

* All tables created in Supabase
* RLS policies configured (if using)
* Environment variables set
* Auth providers configured (if using)
* Real-time enabled on required tables (if using)
* Tested in Preview mode

## Common Use Cases

### Use Case 1: Blog Platform

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
I need Supabase for a blog platform:

**Tables:**
- users: author profiles
- posts: blog posts with rich content
- comments: reader comments
- tags: post categorization

**Features:**
- CRUD for posts
- Real-time comments
- User authentication
- Post search and filtering

Supabase credentials: [will provide]

Please call integration_playbook_expert.
```

### Use Case 2: Real-Time Chat

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
I need Supabase for a chat application:

**Tables:**
- users: user profiles
- rooms: chat rooms
- messages: chat messages
- room_members: room membership

**Features:**
- Real-time message updates
- Typing indicators
- Online presence
- Message history
- User authentication

Supabase credentials: [will provide]

Please call integration_playbook_expert.
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection Error">
    **Error:** "Failed to connect to Supabase"

    **Solutions:**

    * Verify Supabase URL is correct
    * Check API keys are correct
    * Ensure project is active (not paused)
    * Verify environment variables are loaded

    **Ask agent:**

    ```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
    Supabase connection failing with error:
    [paste error]

    Can you verify the Supabase client configuration?
    ```
  </Accordion>

  <Accordion title="RLS Blocking Queries">
    **Error:** "Row level security policy" or empty results

    **Solutions:**

    * Check if RLS is enabled
    * Verify policies allow the operation
    * Use service role key in backend (bypasses RLS)
    * Test with RLS disabled temporarily

    **Ask agent:**

    ```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
    Supabase queries returning empty due to RLS.

    Can you:
    1. Check RLS policies
    2. Update policies to allow [operation]
    3. Or guide me to disable RLS for testing
    ```
  </Accordion>

  <Accordion title="Real-Time Not Working">
    **Error:** Subscriptions not receiving updates

    **Solutions:**

    * Verify Real-time is enabled for table
    * Check subscription code is correct
    * Ensure listening for correct events
    * Check browser console for errors

    **Ask agent:**

    ```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
    Real-time subscriptions not working for [table].

    Updates in database but not appearing in UI.

    Can you debug the real-time subscription code?
    ```
  </Accordion>
</AccordionGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Security" icon="shield" color="#ef4444">
    * Always use RLS in production
    * Never expose service role key in frontend
    * Use anon key for frontend
    * Validate data server-side
    * Use UUID for primary keys
  </Card>

  <Card title="Performance" icon="gauge-high" color="#3b82f6">
    * Create indexes on foreign keys
    * Index frequently queried columns
    * Use select() to specify needed columns
    * Limit query results with .limit()
    * Use pagination for large datasets
  </Card>

  <Card title="Data Modeling" icon="database" color="#10b981">
    * Use foreign keys for relationships
    * Set appropriate ON DELETE actions
    * Use TIMESTAMPTZ for timestamps
    * Add created\_at/updated\_at fields
    * Normalize data appropriately
  </Card>

  <Card title="Real-Time" icon="bolt" color="#f59e0b">
    * Only enable for needed tables
    * Clean up subscriptions on unmount
    * Handle connection errors
    * Consider rate limiting
    * Use channels for grouping
  </Card>
</CardGroup>

***

## Additional Resources

<CardGroup cols={2}>
  <Card title="Supabase Docs" icon="book" href="https://supabase.com/docs">
    Official Supabase documentation
  </Card>

  <Card title="SQL Reference" icon="code" href="https://supabase.com/docs/guides/database">
    PostgreSQL and Supabase SQL guide
  </Card>

  <Card title="RLS Guide" icon="shield" href="https://supabase.com/docs/guides/auth/row-level-security">
    Row Level Security documentation
  </Card>

  <Card title="Supabase Dashboard" icon="chart-mixed" href="https://app.supabase.com">
    Manage your Supabase projects
  </Card>
</CardGroup>

## Quick Reference

### Integration Prompt

```markdown theme={"theme":{"light":"github-light","dark":"dracula"}}
Integrate Supabase:

Credentials: [URL, anon key, service role key]
Tables: [List tables]
Features: [CRUD, real-time, auth]

Please call integration_playbook_expert.
```

### Common Queries

```javascript theme={"theme":{"light":"github-light","dark":"dracula"}}
// Select all
supabase.from('table').select('*')

// Select specific columns
supabase.from('table').select('id, name')

// With filter
supabase.from('table').select('*').eq('status', 'active')

// With join
supabase.from('posts').select('*, users(name, email)')

// Insert
supabase.from('table').insert([{...}])

// Update
supabase.from('table').update({...}).eq('id', id)

// Delete
supabase.from('table').delete().eq('id', id)
```

<Info>
  For Supabase questions, ask: "How do I \[operation] with Supabase?" or "Show me an example of \[feature] in Supabase."
</Info>
