Skip to main content

Overview

Supabase is an open-source Firebase alternative that provides a complete backend solution for your Superun applications. It offers a PostgreSQL database, authentication, real-time subscriptions, and storage - all accessible through a simple API.

What is Supabase

Supabase provides everything you need to build a full-stack application:
  • PostgreSQL Database: A powerful, open-source relational database
  • Authentication: Built-in user management with multiple providers
  • Real-time Subscriptions: Listen to database changes in real-time
  • Storage: File upload and management
  • Edge Functions: Serverless functions for custom logic
  • Auto-generated APIs: REST and GraphQL APIs generated from your database schema

Key Benefits

  • Rapid Development: Get a full backend up and running in minutes
  • Real-time Features: Built-in real-time subscriptions for live updates
  • Scalable: Built on PostgreSQL, scales from prototype to production
  • Open Source: No vendor lock-in, self-hostable if needed
  • Developer Experience: Excellent tooling and documentation

Getting Started

1. Create a Supabase Project

  1. Go to supabase.com and sign up
  2. Click “New Project”
  3. Choose your organization and enter project details
  4. Select a region close to your users
  5. Set a strong database password
  6. Click “Create new project”

2. Get Your Project Credentials

Once your project is created, you’ll need:
  • Project URL: Found in Settings → API
  • Anon Key: Public key for client-side operations
  • Service Role Key: Secret key for server-side operations (keep this secure!)

3. Configure Supabase in Superun

In your Superun project:
  1. Go to Settings → Integrations
  2. Find Supabase and click Connect
  3. Enter your Project URL and Anon Key
  4. Click Save
Superun will automatically configure your project to use Supabase.

Database Setup

Creating Tables

You can create tables in two ways:

Using the Supabase Dashboard

  1. Go to your Supabase project dashboard
  2. Navigate to Table Editor
  3. Click New Table
  4. Define your table schema
  5. Set up Row Level Security (RLS) policies

Using SQL

-- Create a users table
CREATE TABLE users (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  name TEXT,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create a posts table
CREATE TABLE posts (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  title TEXT NOT NULL,
  content TEXT,
  author_id UUID REFERENCES users(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

Row Level Security (RLS)

Enable RLS to secure your data:
-- Enable RLS on tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Create policies
CREATE POLICY "Users can view their own data" ON users
  FOR SELECT USING (auth.uid() = id);

CREATE POLICY "Users can update their own data" ON users
  FOR UPDATE USING (auth.uid() = id);

CREATE POLICY "Anyone can view posts" ON posts
  FOR SELECT USING (true);

CREATE POLICY "Users can create posts" ON posts
  FOR INSERT WITH CHECK (auth.uid() = author_id);

Authentication

Setting Up Authentication

  1. Go to Authentication → Settings in your Supabase dashboard
  2. Configure your site URL (your Superun app URL)
  3. Enable desired authentication providers

Available Providers

  • Email/Password: Traditional email and password authentication
  • Magic Links: Passwordless authentication via email
  • OAuth Providers: Google, GitHub, Twitter, Discord, etc.
  • Phone: SMS authentication

Using Authentication in Your App

Superun automatically generates authentication components:
// Login component
import { useState } from 'react';
import { supabase } from './lib/supabase';

export default function Login() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = async (e) => {
    e.preventDefault();
    const { data, error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });
    
    if (error) {
      console.error('Login error:', error);
    } else {
      console.log('Logged in:', data.user);
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
        required
      />
      <button type="submit">Login</button>
    </form>
  );
}

User Management

// Get current user
const { data: { user } } = await supabase.auth.getUser();

// Sign up new user
const { data, error } = await supabase.auth.signUp({
  email: '[email protected]',
  password: 'password123',
});

// Sign out
await supabase.auth.signOut();

Database Operations

Reading Data

// Fetch all posts
const { data: posts, error } = await supabase
  .from('posts')
  .select('*')
  .order('created_at', { ascending: false });

// Fetch posts with author information
const { data: posts, error } = await supabase
  .from('posts')
  .select(`
    *,
    author:users(name, email)
  `);

// Filter and paginate
const { data: posts, error } = await supabase
  .from('posts')
  .select('*')
  .eq('author_id', userId)
  .range(0, 9); // First 10 posts

Creating Data

// Insert a new post
const { data, error } = await supabase
  .from('posts')
  .insert([
    {
      title: 'My First Post',
      content: 'This is the content of my post',
      author_id: user.id,
    }
  ]);

Updating Data

// Update a post
const { data, error } = await supabase
  .from('posts')
  .update({ title: 'Updated Title' })
  .eq('id', postId);

Deleting Data

// Delete a post
const { error } = await supabase
  .from('posts')
  .delete()
  .eq('id', postId);

Real-time Subscriptions

Listen to database changes in real-time:
import { useEffect, useState } from 'react';
import { supabase } from './lib/supabase';

export default function PostsList() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    // Fetch initial data
    fetchPosts();

    // Set up real-time subscription
    const subscription = supabase
      .channel('posts')
      .on('postgres_changes', 
        { event: '*', schema: 'public', table: 'posts' },
        (payload) => {
          console.log('Change received!', payload);
          // Update local state based on the change
          if (payload.eventType === 'INSERT') {
            setPosts(prev => [payload.new, ...prev]);
          } else if (payload.eventType === 'UPDATE') {
            setPosts(prev => prev.map(post => 
              post.id === payload.new.id ? payload.new : post
            ));
          } else if (payload.eventType === 'DELETE') {
            setPosts(prev => prev.filter(post => post.id !== payload.old.id));
          }
        }
      )
      .subscribe();

    return () => {
      subscription.unsubscribe();
    };
  }, []);

  const fetchPosts = async () => {
    const { data, error } = await supabase
      .from('posts')
      .select('*')
      .order('created_at', { ascending: false });
    
    if (data) setPosts(data);
  };

  return (
    <div>
      {posts.map(post => (
        <div key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      ))}
    </div>
  );
}

File Storage

Uploading Files

// Upload a file
const uploadFile = async (file) => {
  const { data, error } = await supabase.storage
    .from('avatars')
    .upload(`${user.id}/${file.name}`, file);

  if (error) {
    console.error('Upload error:', error);
  } else {
    console.log('File uploaded:', data);
  }
};

Downloading Files

// Get public URL for a file
const { data } = supabase.storage
  .from('avatars')
  .getPublicUrl(`${user.id}/avatar.jpg`);

// Download a file
const { data, error } = await supabase.storage
  .from('avatars')
  .download(`${user.id}/avatar.jpg`);

Edge Functions

Create serverless functions for custom logic:
// functions/send-email/index.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts"

serve(async (req) => {
  const { email, subject, body } = await req.json()
  
  // Send email logic here
  
  return new Response(
    JSON.stringify({ success: true }),
    { headers: { "Content-Type": "application/json" } }
  )
})

Best Practices

Security

  1. Always enable RLS on your tables
  2. Use service role key only on the server side
  3. Validate data on both client and server
  4. Use environment variables for sensitive data

Performance

  1. Use select() to limit returned columns
  2. Implement pagination for large datasets
  3. Use indexes on frequently queried columns
  4. Consider using views for complex queries

Development

  1. Use TypeScript for better type safety
  2. Create database migrations for schema changes
  3. Test your RLS policies thoroughly
  4. Use the Supabase CLI for local development

Common Patterns

User Profiles

// Create user profile on signup
const createUserProfile = async (user) => {
  const { error } = await supabase
    .from('profiles')
    .insert({
      id: user.id,
      email: user.email,
      created_at: new Date().toISOString(),
    });
  
  if (error) console.error('Error creating profile:', error);
};

Data Relationships

// Fetch posts with comments
const { data: posts, error } = await supabase
  .from('posts')
  .select(`
    *,
    comments (
      id,
      content,
      author:profiles(name)
    )
  `);

Search Functionality

// Full-text search
const { data: posts, error } = await supabase
  .from('posts')
  .select('*')
  .textSearch('title,content', 'search term');

Troubleshooting

Common Issues

Q: I’m getting permission denied errors A: Check your RLS policies. Make sure they allow the operations you’re trying to perform. Q: Real-time subscriptions aren’t working A: Ensure you’re subscribed to the correct channel and that RLS policies allow the user to see the data. Q: File uploads are failing A: Check your storage bucket policies and file size limits. Q: Authentication isn’t working A: Verify your site URL is correctly configured in the Supabase dashboard.

Migration from Other Services

From Firebase

  • Firestore → PostgreSQL: Use Supabase’s JSON columns for document-like data
  • Firebase Auth → Supabase Auth: Similar API, easy migration
  • Firebase Storage → Supabase Storage: Compatible S3 API

From Other Databases

  • MySQL → PostgreSQL: Use Supabase’s migration tools
  • MongoDB → PostgreSQL: Restructure data into relational format

Need Help?

Check our FAQ for common Supabase integration questions and troubleshooting tips.