Introduction

Supabase is an open-source alternative to Firebase that provides a powerful PostgreSQL database, authentication, and real-time subscriptions. In this tutorial, we'll walk through building a simple real-time CRUD (Create, Read, Update, Delete) application with authentication.

Prerequisites

Before we begin, make sure you have:

  • Node.js installed on your machine
  • A Supabase account (free tier is fine)
  • Basic knowledge of JavaScript/TypeScript
  • Your favorite code editor

Setting Up Supabase

First, let's create a new Supabase project and set up our development environment.

1. Create a New Supabase Project

  1. Go to supabase.com and sign in
  2. Click "New Project" and fill in your project details
  3. Wait for your database to be provisioned (usually takes about 1 minute)

2. Install Supabase Client

In your project directory, install the Supabase client library:

npm install @supabase/supabase-js

3. Initialize Supabase Client

Create a new file called supabaseClient.js:

import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'YOUR_SUPABASE_URL'
const supabaseKey = 'YOUR_SUPABASE_ANON_KEY'

export const supabase = createClient(supabaseUrl, supabaseKey)

Database Setup

Let's create a simple todos table in Supabase:

create table todos (
  id uuid default uuid_generate_v4() primary key,
  user_id uuid references auth.users,
  task text not null,
  is_complete boolean default false,
  created_at timestamp with time zone default timezone('utc'::text, now())
);

-- Enable Row Level Security (RLS)
alter table todos enable row level security;

-- Create policy to allow users to only see their own todos
create policy "Users can only access their own todos" on todos
  for all using (auth.uid() = user_id);

Implementing Authentication

Supabase provides built-in authentication. Here's how to implement sign-up and sign-in:

// Sign up a new user
async function signUp(email, password) {
  const { data, error } = await supabase.auth.signUp({
    email,
    password,
  })
  return { data, error }
}

// Sign in an existing user
async function signIn(email, password) {
  const { data, error } = await supabase.auth.signInWithPassword({
    email,
    password,
  })
  return { data, error }
}

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

CRUD Operations

Here's how to perform basic CRUD operations with Supabase:

// Create a new todo
async function createTodo(task) {
  const { data, error } = await supabase
    .from('todos')
    .insert([{ task, user_id: supabase.auth.user().id }])
    .select()
  return { data, error }
}

// Read todos
async function getTodos() {
  const { data, error } = await supabase
    .from('todos')
    .select('*')
    .order('created_at', { ascending: false })
  return { data, error }
}

// Update a todo
async function updateTodo(id, updates) {
  const { data, error } = await supabase
    .from('todos')
    .update(updates)
    .match({ id })
  return { data, error }
}

// Delete a todo
async function deleteTodo(id) {
  const { error } = await supabase
    .from('todos')
    .delete()
    .match({ id })
  return { error }
}

Real-time Subscriptions

One of Supabase's powerful features is real-time subscriptions. Here's how to implement them:

// Subscribe to changes in the todos table
const todosSubscription = supabase
  .channel('todos')
  .on('postgres_changes', 
    { event: '*', schema: 'public', table: 'todos' }, 
    (payload) => {
      console.log('Change received!', payload)
      // Handle the change here (e.g., update UI)
    }
  )
  .subscribe()

Live Demo

Try out the real-time todo application below:

Authentication Demo

Best Practices and Tips

  • Always implement Row Level Security (RLS) policies
  • Use TypeScript for better type safety
  • Handle errors appropriately
  • Clean up subscriptions when components unmount
  • Use environment variables for sensitive information

Conclusion

Supabase provides a powerful and developer-friendly platform for building real-time applications. With its PostgreSQL database, built-in authentication, and real-time subscriptions, you can quickly build sophisticated applications without managing complex infrastructure.

For more information, check out the following resources: