Supabase in Flutter: solved exercise with auth and task CRUD
Supabase in Flutter: solved exercise with auth and CRUD
Supabase is the most widely used open-source Firebase alternative in 2025-26. It combines a PostgreSQL database, authentication, storage, and edge functions in a single service. supabase_flutter provides an official client that handles sessions, tokens, and API communication reactively.
Problem statement
Build a task manager app that:
- Allows registration and sign-in with email and password.
- Shows the tasks screen only when a session is active.
- Creates, completes, and deletes tasks in Supabase.
- Applies Row Level Security so each user only sees their own tasks.
- Handles authentication errors with readable messages.
Dependencies
Configuration
1. Create a Supabase project (supabase.com) and copy the URL and anon key from Settings → API.
2. Create the tasks table in the Supabase SQL Editor:
3. Initialize Supabase before runApp:
In production, store credentials with --dart-define or environment variables, never in source code.
Full solution
Key concepts
| API | Purpose |
|---|---|
Supabase.initialize() | Initializes the global client once at startup |
supabase.auth.onAuthStateChange | Reactive stream of session state |
supabase.auth.signInWithPassword() | Sign in with email and password |
supabase.auth.signUp() | Register a new user |
supabase.auth.signOut() | Close the active session |
supabase.from('table').select() | Read records (RLS enforced automatically) |
supabase.from('table').insert({}) | Create a record |
supabase.from('table').update({}).eq() | Update by condition |
supabase.from('table').delete().eq() | Delete by condition |
AuthException | Typed auth error with a readable message |
Common mistakes
- Credentials in source code: use
--dart-defineor a secrets manager. The Supabaseanon keyis not an absolute secret (protected by RLS), but the URL should still be controlled in production. - Missing
awaiton write operations:insert,update, anddeleteareFuture; withoutawaityou won’t see errors and state won’t update. - RLS enabled without policies: if you enable RLS without creating policies, all queries return 0 records even if data exists — correct by design, but confusing when undocumented.
- Not checking
mountedafterawait: the widget may have been disposed during the async operation; always checkmountedbefore callingsetStateorScaffoldMessenger.
Practical application
This pattern is the foundation for any app with users and private data: note managers, lightweight CRMs, personal tracking apps, or internal admin dashboards. Supabase adds real-time subscriptions via supabase.from('tasks').stream() when you need instant updates without polling.
Recommended next exercises
- Secure storage with token in Flutter: solved exercise
- Auth with refresh token in Flutter: solved exercise
- Firebase Auth login in Flutter: solved exercise
- All Flutter exercises
Guided practice and next step
- More Flutter exercises
- C exercises to strengthen fundamentals
- Programming in C in 100 Solved Exercises
- View on Amazon (included in Kindle Unlimited)
FAQ
Is Supabase free for small projects?
Yes. The free plan includes 500 MB of database storage, 50,000 monthly active users, and 2 GB of file storage. It is enough for MVPs and personal projects.
What is the main difference from Firebase?
Firebase uses a NoSQL database (Firestore) while Supabase uses relational PostgreSQL. Supabase is open-source and can be self-hosted; Firebase is a Google service with no self-hosting option.
How do I protect the anon key in production?
The anon key is not a critical secret because data access is controlled by Row Level Security. What you must never expose is the service_role key, which bypasses RLS entirely and must never be used on the client side.