69 views
Supabase Local Development
This post is summary of how to setup a local development environment for Supabase. There's a strong emphasis on the database because that's usually the tricky part. I like to use this post as a cheat sheet for my own reference.
Running Supabase locally
The Supabase command line interface (CLI) lets you to run the entire stack locally. Let's start by creating a new project:
npx supabase init
This creates a supabase
folder with a .temp
folder and the config.toml
file.
The former has unimportant stuff, the latter has important configuration stuff.
To start the Supabase stack, you must launch Docker Desktop and run the command below. This takes time the first time because the Docker images need to be downloaded.
npx supabase start
Congrats! You've just created a local development environment for Supabase.
Next, to check the status and get the local development URLs, run:
npx supabase status
To stop the stack, exchange <project_name>
with the actual name of your project and run:
npx supabase stop --project-id <project_name>
Using Google auth locally
While testing, it helps to setup Auth to work locally. Here's a quick guide to setup Google Auth on a local Supabase instance. Setting up other Auth providers is similar.
Google Developer Console
Begin by creating new credentials for an OAuth 2.0 client ID in the APIs and services section of the Google Developer Console. Start the setup by clicking on the "Create credentials" button.
During the setup, add the following redirect URI:
http://localhost:54321/auth/v1/callback
That's the standard path for the callback. For testing purposes, the redirect points to your local Supabase instance (see Redirect URI). After walking though the setup, you will get a client ID and client secret (see Client ID and secret):
Supabase configuration
Back in the project, open the config.toml
file and add the following to the auth_providers
section:
[auth.external.google]
enabled = true
client_id = "env(GOOGLE_CLIENT_ID)"
secret = "env(GOOGLE_CLIENT_SECRET)"
redirect_uri = "http://127.0.0.1:54321/auth/v1/callback"
url = ""
skip_nonce_check = false
Now, create an .env
file in the root of the project and add the id and secret you got from the Google Developer Console:
GOOGLE_CLIENT_ID="insert_id_here"
GOOGLE_CLIENT_SECRET="insert_secret_here"
For these changes to take effect, you need to stop and start Supabase. More details on local auth can be found in the Supabase documentation.
NextJS components
The Google auth flow works as follows:
- User clicks login button which opens Google auth page
- After successful login user is redirected to Supabase callback:
localhost:54321/auth/v1/callback
- Supabase processes OAuth and redirects to the callback in the NextJS app
- App callback exchanges code for session and redirects to final destination
Here's an example of a Google login button component that uses the Supabase client to sign-in with Google.
// .../components/google-login.tsx
'use client';
import { FcGoogle } from "react-icons/fc";
import { Button } from "@/components/ui/button";
import { createClient } from "@/utils/supabase/client";
import { AppRoutes } from "@/routes";
export const GoogleLogin = () => {
const supabase = createClient();
const onClick = async () => {
supabase.auth.signInWithOAuth({
provider: "google",
options: {
redirectTo: `${origin}/api/auth/callback?redirect=${encodeURIComponent("/dashboard")}`,
},
});
}
return (
<div className="flex items-center w-full gap-x-2">
<Button
size="lg"
className="w-full"
variant="outline"
onClick={onClick}
>
<FcGoogle className="h-5 w-5" />
</Button>
</div>
)
}
Local database migrations
Migrations let us version control changes — such as creating tables, adding columns, or inserting data — to a database. This ensures that database changes are consistently applied across different environments.
Create a new migration
Migrations are .sql
files stored in the supabase/migrations
folder.
To create a new and empty migration file, run:
npx supabase migration new example_migration
This will create a new file with the name structure <timestamp>_example_migration.sql
inside the supabase/migrations
folder.
You can add any SQL statements to the migration file, such as:
-- Example migration file
create table if not exists example_table (
id uuid default gen_random_uuid() primary key,
message text not null
);
insert into example_table (message) values ('Hello, world!');
This migration file creates the example_table
with an id
and a message
column and inserts a row with data into the table.
Apply a migration locally
By applying a migration, the SQL code in the migration files gets applied to the database on the local Supabase instance. To apply a migration such as the one above, run:
npx supabase migration up
Afterwards, you'll see the changes applied in the Supabase studio?Similar to the dashboard on the Supabase platform but tailored to local development. As you can see from the studio snapshot below, the table and row have been created from the content of the migration file:
Pull local schema changes
Pulls schema changes from the local database. A new migration file will be created in the supabase/migrations
directory.
By default, the the command pulls from the remote database so --local
flag is required to pull from the local database.
supabase db pull --local
If the migration history table is empty, pg_dump
is used to capture the content of the remote schemas.
However, if the migration table has entries, this command will diff schema changes equivalent to npx supabase db diff
.
Diff local schema changes
The diff
command compares the schema of a target database against a shadow database?The shadow database is created by applying the migration files from your local migrations directory in a separate container generated from the SQL files in your local project's migrations
directory.
For convenience, you can add the -f
flag to save the schema diff
as a new migration file.
npx supabase db diff -f new_changes_migration
Here's an example of a migration file that contains the diff after adding a column to the example_table
table (mentioned earlier) in the Supabase studio:
-- Example 'diff'
alter table "public"."example_table" add column "user" text;
It basically created a shadow database from the SQL files in migrations
folder from my editor and then compared it to the local database schema.
After that, it evaluated the difference and created a new migration file.
Dump the local database
A dump let's us get the schema and data from the database. Here's how to dump the local database schema, data and a specific schema:
npx supabase db dump --local -f supabase/dump_schema.sql
Reset the local database
A reset recreates the local Postgres container and applies all local migrations found in supabase/migrations
directory
npx supabase db reset
If test data is defined in supabase/seed.sql
, it will be seeded after the migrations are run.
Remote database migrations
The remote database CLI commands are similar to local ones, with a few key differences. For ease of reference, I've dedicated a separate section for the remote database migrations.
Linking to a hosted project
Applying database migrations to the Supabase platform requires a link between your local project and the Supabase platform.
To create the link, insert your project_id
(aka. project ref.) into:
npx supabase link --project-ref <project_id>
You'll be prompted for the database password which can be found in Settings / Database
.
To remove the link, run:
npx supabase unlink
Apply a remote migration
Applying a migration to a linked remote database is done using:
supabase db push
Once pushed, you can check that the migration version is up to date for the local and remote database by running:
supabase migration list
Pull remote schema changes
Pulls schema changes from a linked remote database. A new migration file will be created under supabase/migrations
directory.
By default, the the command pulls from the remote database (i.e., --linked
flag is optional).
npx supabase db pull
Diff remote schema changes
In contrast to diff'ing against the local database, we need to add the --linked
flag to diff against the remote database.
npx supabase db diff -f new_changes_migration --linked
Dump the remote database
The CLI commands are similar to the ones we used for the local database except that we don't use the --local
flag:
npx supabase db dump -f supabase/dump_schema.sql
Reset the remote database
To reset the remote database using the migrations in your supabase/migrations
folder, include the --linked
flag:
npx supabase db reset --linked
Careful with this one. Make a data and schema backup before running this command.
Generating TypeScript Types
To generate TypeScript types for the local or remote database, run:
npx supabase gen types --local --lang=typescript > ./types.ts
More information on how to use the generated types file can be found in these two blog YouTube videos: