Supabase Guide — Open-Source Firebase Alternative for Full-Stack Apps
Supabase is an open-source backend-as-a-service that provides a full PostgreSQL database, authentication, real-time subscriptions, file storage, and edge functions — all wrapped in a developer-friendly dashboard and SDK.
What You’ll Learn
- Setting up a Supabase project and connecting to PostgreSQL
- Implementing authentication with email, social logins, and magic links
- Enforcing Row Level Security (RLS) policies for data access
- Subscribing to real-time database changes
- Uploading and serving files with Supabase Storage
Why Supabase Matters
Firebase locked developers into a proprietary document database (Firestore) with vendor lock-in and unpredictable pricing. Supabase is built on PostgreSQL — the world’s most advanced open-source database — giving you true relational data, SQL queries, and zero vendor lock-in. You can export your data any time, self-host if needed, and use standard PostgreSQL tooling. Doda Browser’s user feedback system runs on Supabase because the RLS policies let users submit feedback that only they can edit, while moderators see everything — all enforced at the database level.
flowchart LR
A[JavaScript & Database Basics] --> B[Supabase]
B --> C[PostgreSQL]
B --> D[Auth]
B --> E[Row Level Security]
B --> F[Realtime]
B --> G[Storage]
C --> H[Relational Data]
D --> I[User Management]
E --> J[Data Access Control]
style B fill:#3ecf8e,color:#fff
Core Concepts
Project Setup
# Install Supabase JavaScript client
npm install @supabase/supabase-js
# Initialize
const { createClient } = require("@supabase/supabase-js");
const supabase = createClient(
"https://your-project.supabase.co",
"your-anon-key" // Safe for client-side use (RLS protected)
);Database and Schema
Supabase gives you a full PostgreSQL database with a web-based SQL editor:
-- Run in Supabase SQL Editor
CREATE TABLE tasks (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) NOT NULL,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Enable Row Level Security
ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;
-- Policy: users can only see their own tasks
CREATE POLICY "Users can view own tasks"
ON tasks FOR SELECT
USING (auth.uid() = user_id);Authentication
// Sign up with email
const { data, error } = await supabase.auth.signUp({
email: "alice@example.com",
password: "secure-password-123",
});
// Sign in
const { data, error } = await supabase.auth.signInWithPassword({
email: "alice@example.com",
password: "secure-password-123",
});
// Get current user
const { data: { user } } = await supabase.auth.getUser();
console.log(user.email); // alice@example.com
// Social login
await supabase.auth.signInWithOAuth({ provider: "google" });
// Sign out
await supabase.auth.signOut();Output: The first call creates a user in auth.users and sends a confirmation email (if enabled). The second returns a session with access and refresh tokens. All subsequent requests include the session automatically.
Row Level Security (RLS)
RLS policies are PostgreSQL rules that run on every query — even direct database connections can’t bypass them:
// Client-side query — RLS filters results automatically
const { data: tasks } = await supabase
.from("tasks")
.select("*");
// Only returns tasks WHERE user_id = auth.uid()
// The policy is enforced by PostgreSQL, not by the client
console.log(tasks);
// [{ id: "...", title: "Buy groceries", user_id: "alice-uuid", ... }]
-- More advanced RLS policies
CREATE POLICY "Users can insert own tasks"
ON tasks FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own tasks"
ON tasks FOR UPDATE
USING (auth.uid() = user_id);Why RLS matters: Even if someone steals your anon key and calls the API directly, they can only access data that belongs to them. The security is at the database level — not trusting the client.
Realtime Subscriptions
// Subscribe to real-time changes
const channel = supabase
.channel("tasks-changes")
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "tasks" },
(payload) => {
console.log("Change received!", payload);
// { eventType: "INSERT", new: { title: "New task", ... } }
}
)
.subscribe();
// Clean up when done
channel.unsubscribe();Output: Any INSERT, UPDATE, or DELETE on the tasks table triggers the callback in real time — no polling, no WebSocket setup. Useful for collaborative apps, dashboards, and live feeds.
Storage
// Upload a file
const { data, error } = await supabase.storage
.from("avatars")
.upload(`public/${user.id}.jpg`, file);
// Get public URL
const { data: { publicUrl } } = supabase.storage
.from("avatars")
.getPublicUrl(`public/${user.id}.jpg`);
console.log(publicUrl);
// https://your-project.supabase.co/storage/v1/object/public/avatars/public/user-uuid.jpg
Common Mistakes
Not enabling Row Level Security: Without RLS, your database is wide open. Anyone with the anon key can read, write, and delete all data. Always enable RLS immediately after creating tables.
Storing the service_role key client-side: The
service_rolekey bypasses all RLS policies. Never expose it in client code. Use it only in server-side or Edge Function code.Forgetting to handle auth session expiration: Supabase tokens expire after 1 hour by default. Use
supabase.auth.onAuthStateChangeto refresh tokens or redirect to login.Not creating RLS policies for INSERT and UPDATE: A
SELECTpolicy alone is not enough. Without INSERT/UPDATE/DELETE policies, authenticated users can’t modify data even if they’re logged in.Using the free tier for production without monitoring: Supabase free tier pauses projects after 7 days of inactivity. Set up periodic health checks or upgrade to a paid plan for production.
Practice Questions
What is Row Level Security and why is it important? Answer: RLS is a PostgreSQL feature that restricts which rows a user can access based on a policy expression. It’s critical because it enforces data access at the database level, not trusting the client.
How does Supabase authentication work? Answer: Supabase uses GoTrue (a JWT-based auth server). Users sign up with email/password or social providers, receive a JWT, and include it in API requests to prove their identity.
What’s the difference between the anon key and the service_role key? Answer: The anon key is safe for client use and respects RLS policies. The service_role key bypasses all RLS and should only be used server-side.
How do real-time subscriptions work? Answer: Supabase uses PostgreSQL’s replication feature with WebSocket connections. When a table changes, PostgreSQL emits the change, and Supabase broadcasts it to subscribed clients.
Challenge
Build a real-time collaborative todo app: set up Supabase with a tasks table and RLS policies, implement user authentication with Google OAuth, create a real-time subscription to sync tasks across browsers, add file upload for task attachments, and deploy the frontend to Vercel.
FAQ
Try It Yourself
# Create a project at supabase.com
# Get your URL and anon key from Settings > API
npm install @supabase/supabase-js
# Run this script
node -e "
const { createClient } = require('@supabase/supabase-js');
const supabase = createClient('https://your-project.supabase.co', 'your-anon-key');
supabase.auth.signUp({ email: 'test@example.com', password: 'test123' })
.then(r => console.log('User created:', r.data.user?.email));
"Then create a table in the SQL editor, enable RLS, and test that queries only return your own data.
What’s Next
| Topic | Description |
|---|---|
| Master the database behind Supabase | |
| Server-side JavaScript with Supabase |
Related topics: JavaScript, PostgreSQL, Node.js, SQL, REST API
What’s Next
Congratulations on completing this Supabase tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro