What Is Supabase?

Supabase is an open-source Firebase alternative built on PostgreSQL. Where Firebase uses a NoSQL document database (Firestore), Supabase gives you a real relational database — the same PostgreSQL that powers some of the world's largest web applications. For no-code builders, this means you get proper tables, foreign keys, joins, and SQL queries: a data model that can grow with your product rather than hitting a ceiling at 10,000 users.

Beyond the database, Supabase bundles several services that cover the full backend stack. Supabase Auth handles user sign-up, login, and session management with support for email/password, magic links, and OAuth providers like Google and GitHub. Supabase Storage gives you an S3-compatible file storage bucket for images, documents, and uploads. Supabase Realtime lets you subscribe to database changes and push updates to connected clients in real time. And Supabase Edge Functions let you run server-side JavaScript (Deno runtime) for custom backend logic.

For no-code frontends — WeWeb, FlutterFlow, Bubble, or Retool — Supabase is the most complete backend option available. It integrates natively with WeWeb and FlutterFlow, has well-documented REST APIs for any frontend that doesn't have a native connector, and its PostgreSQL foundation means you're never locked into a proprietary data format.

Create Your First Supabase Project

Go to supabase.com and sign up for a free account. Click "New Project," name your project, choose a region closest to your users, and set a database password — store this password securely, you'll need it for direct database connections. Supabase will provision your project in about 60 seconds.

Once your project is ready, explore the dashboard. The Table Editor is where you'll create and manage tables — it's a visual spreadsheet-style interface that doesn't require any SQL knowledge. The SQL Editor lets you run raw SQL queries. The Authentication tab manages your users and auth settings. The API tab contains your project URL and keys — you'll use these to connect frontends and third-party tools.

Before building anything, take note of two API keys in the Settings > API section: the anon (public) key and the service_role (secret) key. The anon key is safe to use in frontend applications — it respects your Row Level Security policies. The service_role key bypasses all security policies and should only ever be used in server-side code. This distinction is fundamental to Supabase security: keep the service_role key out of your frontend, always.

Building Your First Table

In the Table Editor, click "New Table." Name it tasks. Add the following columns: id (int8, primary key, auto-generated — Supabase adds this by default), user_id (uuid), title (text, not null), status (text, default value: pending), and created_at (timestamptz, default: now()). Supabase adds created_at automatically — just confirm it's there.

Data types matter. Use text for strings of any length, int8 for large integers (IDs, counts), bool for true/false values, timestamptz for all date/time values (the tz suffix means timezone-aware — always prefer this over plain timestamp), jsonb for flexible key-value data, and uuid for identifiers that reference users or other records. When in doubt, use text for strings and timestamptz for dates.

Foreign keys link tables together. The user_id column in your tasks table should reference the id column in auth.users — Supabase's built-in users table. Set this up in the table editor under Foreign Keys. This relationship tells the database that every task must belong to a valid user — if you try to insert a task with a non-existent user_id, the database will reject it. These constraints are one of the most important advantages of PostgreSQL over NoSQL databases: the database itself prevents bad data from being stored.

Row Level Security — The Concept That Keeps Your Data Safe

Row Level Security (RLS) is the feature that makes Supabase safe to use directly from a frontend without a traditional server layer. Without RLS, any user who has your Supabase anon key can read and write all data in your tables — a serious security problem. With RLS, you define policies that restrict which rows each user can access, and the database enforces these policies on every query automatically.

To enable RLS on your tasks table, run this SQL in the Supabase SQL editor: ALTER TABLE tasks ENABLE ROW LEVEL SECURITY; Then add a SELECT policy: CREATE POLICY "users can see own tasks" ON tasks FOR SELECT USING (user_id = auth.uid()); — this ensures a logged-in user can only retrieve rows where user_id matches their own ID. Add similar policies for INSERT (WITH CHECK (user_id = auth.uid())), UPDATE, and DELETE.

The mental model for RLS is a filter that runs before every database operation. When user Alice queries SELECT * FROM tasks, Supabase silently adds WHERE user_id = 'alice-uuid' to her query. She cannot access Bob's rows — not because the application prevents it, but because the database itself won't return them. This database-level enforcement is far more robust than application-level checks, which can be bypassed by bugs or API misuse. Learn more about how we use RLS in production on the Supabase tool page.

Writing SQL Queries and Using the Supabase Auto-Generated API

Supabase automatically generates a REST API for every table in your database. No configuration needed — the moment you create a table, you can query it via HTTP. The API follows a predictable pattern: GET /rest/v1/tasks returns all rows (filtered by your RLS policies), POST /rest/v1/tasks creates a new row, PATCH /rest/v1/tasks?id=eq.1 updates a row, and DELETE /rest/v1/tasks?id=eq.1 deletes one. Pass your anon key in the Authorization header and apikey header on every request.

For more complex queries, use the Supabase SQL Editor to write and test SQL directly. Basic queries you'll use constantly: SELECT * FROM tasks WHERE user_id = 'your-uuid' ORDER BY created_at DESC; — fetch tasks sorted by newest first. SELECT COUNT(*) FROM tasks WHERE status = 'completed'; — count completed tasks. These SQL queries can also be turned into database functions (called RPC endpoints) that are callable from the REST API.

Supabase also provides official client libraries for JavaScript, Python, Flutter, Swift, and Kotlin that wrap the REST API with a clean, chainable query syntax. In JavaScript: supabase.from('tasks').select('*').eq('status', 'pending').order('created_at', { ascending: false }) — no raw HTTP needed. For no-code tools like WeWeb and FlutterFlow, the native Supabase connectors handle all of this automatically — you select your table and filters visually.

Setting Up Authentication

Supabase Auth is enabled by default on every project. Navigate to Authentication > Settings to configure your auth providers and email templates. For email/password auth, no configuration is needed — it works out of the box. To test it, go to Authentication > Users and click "Invite User" to create a test account, or use the Supabase client library to call supabase.auth.signUp({ email: 'test@example.com', password: 'securepassword' }).

Magic link auth (passwordless email login) is a single toggle in the auth settings. When enabled, users receive a sign-in link via email instead of entering a password — popular for B2B tools where users prefer not to manage yet another password. OAuth providers (Google, GitHub, Discord) each require creating an OAuth app in the provider's developer console and pasting the client ID and secret into Supabase. Google OAuth takes about 10 minutes to configure and is by far the most-requested auth method in the apps we build.

After a successful login, Supabase issues a JWT (JSON Web Token) that identifies the user. This token is automatically included in all subsequent requests when using the Supabase client library. The token expires after one hour and is refreshed automatically. Your RLS policies use auth.uid() to extract the user's ID from this token — which is why RLS works seamlessly with Supabase Auth without any extra plumbing.

Connecting Supabase to a No-Code Frontend

Supabase integrates natively with the three leading no-code frontends. In WeWeb, install the Supabase plugin, paste your Project URL and anon key, and you have immediate access to data collections, auth workflows, and real-time subscriptions — all configured visually. WeWeb's Supabase connector is the most mature integration available and covers 95% of what production apps need. See more at the WeWeb tool page.

In FlutterFlow, Supabase support is available under Settings > Supabase. Add your credentials and FlutterFlow generates the Supabase Flutter client configuration automatically. You can then bind FlutterFlow UI components directly to Supabase table queries, set up auth flows with built-in FlutterFlow actions, and listen to real-time updates. The FlutterFlow tool page covers mobile-specific integration patterns.

For Bubble or other tools without native Supabase connectors, use the Supabase REST API directly via the tool's built-in API connector. Pass your anon key as a header, set Content-Type to application/json, and call the auto-generated REST endpoints. This pattern works for any no-code tool that supports external HTTP requests. If you're building a production app and want the data model and auth set up correctly from day one, our team specialises in this exact stack and has delivered 50+ apps in production.