π₯ Stop Wasting Time with APIs β Build a Full Backend in Minutes using Supabase & React!
Imagine building a full-stack app with authentication, file uploads, and a powerful SQL database... and writing almost no backend code. Sound too good to be true? Let me show you how Supabase makes it possible.
π TL;DR
If you're tired of setting up backends, managing authentication, or just want to ship your product faster, Supabase is your new best friend. In this post, we'll build a full-stack React app with user authentication, a Postgres database, and real-time updates β all powered by Supabase.
π§ͺ What is Supabase?
Supabase is an open-source alternative to Firebase. It gives you:
- A hosted Postgres database
- Automatic RESTful and realtime APIs
- User authentication
- File storage
- Edge functions (serverless functions)
Unlike Firebase, Supabase is built on PostgreSQL, which means you get full SQL power and relational queries.
π§ Tech Stack for this Project
- React (using Vite for speed)
- Supabase (auth + DB)
Weβll build a simple Notes app with:
- User sign up/login/logout
- Real-time note syncing
- CRUD operations on notes
Letβs go! π οΈ
π¬ Step 1: Create a Supabase Project
- Go to https://app.supabase.com/
- Click
New Project
- Choose a name, password, and region
- Wait for your project to initialize
- Go to the
Settings -> API
tab and copy your anon key & project URL
Weβll use these in our React app.
ποΈ Step 2: Create the Notes Table
In your Supabase dash:
-- SQL Editor create table notes ( id uuid primary key default gen_random_uuid(), user_id uuid references auth.users(id), content text, inserted_at timestamp with time zone default timezone('utc', now()) );
Now letβs build the React frontend.
βοΈ Step 3: Set Up React App with Supabase
Using Vite for speed:
npm create vite@latest supabase-notes --template react cd supabase-notes npm install npm i @supabase/supabase-js
Create Supabase Client
Create a file: src/supabaseClient.js
import { createClient } from '@supabase/supabase-js'; const supabaseUrl = 'https://your-project.supabase.co'; const supabaseAnonKey = 'your-anon-key'; export const supabase = createClient(supabaseUrl, supabaseAnonKey);
π Step 4: Add Authentication
In App.jsx
:
import { useState, useEffect } from 'react'; import { supabase } from './supabaseClient'; function App() { const [session, setSession] = useState(null); useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); }); const { data: listener } = supabase.auth.onAuthStateChange((event, session) => { setSession(session); }); return () => listener.subscription.unsubscribe(); }, []); if (!session) return <Auth />; return <Notes user={session.user} />; } function Auth() { const [email, setEmail] = useState(''); const handleLogin = async () => { await supabase.auth.signInWithOtp({ email }); alert('Check your email for the login link!'); }; return ( <div> <h2>Login via Magic Link</h2> <input value={email} onChange={(e) => setEmail(e.target.value)} /> <button onClick={handleLogin}>Send</button> </div> ); }
Supabase magic link auth makes signing in a breeze.
βοΈ Step 5: CRUD Notes in Real-Time
Let's implement our Notes
component:
function Notes({ user }) { const [notes, setNotes] = useState([]); const [newNote, setNewNote] = useState(''); useEffect(() => { fetchNotes(); const realTimeSub = supabase .channel('public:notes') .on('postgres_changes', { event: '*', schema: 'public', table: 'notes' }, payload => { console.log('Realtime update', payload); fetchNotes(); }) .subscribe(); return () => supabase.removeChannel(realTimeSub); }, []); async function fetchNotes() { const { data, error } = await supabase .from('notes') .select('*') .eq('user_id', user.id) .order('inserted_at', { ascending: false }); setNotes(data); } async function addNote() { await supabase.from('notes').insert({ content: newNote, user_id: user.id }); setNewNote(''); } async function deleteNote(id) { await supabase.from('notes').delete().eq('id', id); } return ( <div> <h2>My Notes</h2> <input value={newNote} onChange={(e) => setNewNote(e.target.value)} /> <button onClick={addNote}>Add</button> <ul> {notes.map(note => ( <li key={note.id}> {note.content} <button onClick={() => deleteNote(note.id)}>x</button> </li> ))} </ul> </div> ); }
Boom β You now have real-time, collaborative notes.
π Deploying with Vercel
- Push your code to GitHub
- Go to vercel.com and import your repo
- Set the environment variables:
VITE_SUPABASE_URL
VITE_SUPABASE_ANON_KEY
Then deploy!
π‘ Pro Tips & Gotchas
- Supabase Auth works best with a custom domain to prevent email blackholes
- You can use
Row Level Security
for extra protection on your tables - You can build edge functions directly with Supabase CLI
- Supabase storage lets you add file uploads (profile photos? PDFs?) quickly
π Final Thoughts
Supabase is a total game-changer for developers who want to iterate quickly and still maintain control.
You're using real SQL, you own your data, and you get Firebase-level power β‘οΈ without vendor lock-in.
Who should use Supabase?
- Startup devs who need MVPs fast
- Freelancers working for multiple clients
- Indie hackers looking to ship more
Have you tried Supabase? Tweet me your builds @CodeWizardDev π§ββοΈ
π Resources
Thanks for reading β time to stop writing backends and start building products! π
π If you need this done β we offer fullstack development services.
Top comments (0)