Quickstart: your first project in 5 minutes
Create a SupaHost project, copy its URL and keys, make a table with Row Level Security in Studio, then read and write it from JavaScript and sign up your first user.
This guide takes you from an empty instance to a working table you can query from code. It uses a small recipe app as the example. You need a SupaHost account with an instance; if you don't have one yet, start the 7-day trial at supahost.app and choose a region close to your users (it can't be changed later).
1. Create a project
- In the dashboard, open Projects and click New project.
- Enter a name. Names are 2 to 30 characters of lowercase letters, digits and hyphens, for example
app-one. The name becomes your project URL:https://app-one.acme.supahost.spaceif your instance is calledacme. - Create the project. It uses the Blank template, an empty Supabase project.
The project shows as provisioning for a short while, and you get an email when it is ready. During the trial you can have up to 3 projects.
2. Copy the URL and keys
Open the project and go to the Connect tab, then App. You'll see three values:
| Value | Label | Where it goes |
|---|---|---|
| Project URL | Every client | |
anon key |
public | Browser and mobile apps. Safe to ship, because Row Level Security decides what it can do. |
service_role key |
secret (click Reveal) | Servers only. It bypasses Row Level Security. |
Put them in environment variables rather than in your code:
SUPABASE_URL=https://app-one.acme.supahost.space
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...
The Overview tab also has a ready-made .env block you can copy.
3. Create a table
Click Studio in the project header to open Supabase Studio. The first open takes about 20 seconds while Studio starts. Go to the SQL editor and run:
create table public.recipes (
id bigint generated always as identity primary key,
title text not null,
minutes int,
user_id uuid references auth.users (id) default auth.uid(),
created_at timestamptz not null default now()
);
alter table public.recipes enable row level security;
grant select on public.recipes to anon, authenticated;
grant insert on public.recipes to authenticated;
create policy "Anyone can read recipes"
on public.recipes for select
to anon, authenticated
using (true);
create policy "Signed-in users add their own recipes"
on public.recipes for insert
to authenticated
with check ((select auth.uid()) = user_id);
insert into public.recipes (title, minutes)
values ('Tomato soup', 25), ('Flatbread', 40);
Row Level Security is what makes the public anon key safe. With RLS on and no policy, nobody can read the table through the API. The two policies above let anyone read recipes and let signed-in users add recipes that belong to them. Read Row Level Security before you put real data in a table.
4. Read the data
From a terminal, with your variables exported:
curl "$SUPABASE_URL/rest/v1/recipes?select=id,title,minutes" \
-H "apikey: $SUPABASE_ANON_KEY"
From JavaScript, install the client:
npm install @supabase/supabase-js
// recipes.ts
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!)
const { data, error } = await supabase
.from('recipes')
.select('id, title, minutes')
.order('minutes')
if (error) throw error
console.log(data)
// [ { id: 1, title: 'Tomato soup', minutes: 25 }, { id: 2, title: 'Flatbread', minutes: 40 } ]
5. Sign up a user and write a row
Auth works out of the box with email and password. By default new users must confirm their email first. To try things quickly, go to the Auth tab, open Sign-in & security, turn on Skip email confirmation, and click Save sign-in settings. Changes apply within about a minute. Turn it back off before you launch.
const { error: signUpError } = await supabase.auth.signUp({
email: '[email protected]',
password: 'a-long-test-password',
})
if (signUpError) throw signUpError
const { data: recipe, error } = await supabase
.from('recipes')
.insert({ title: 'Lemon rice', minutes: 30 })
.select()
.single()
console.log(recipe, error)
The insert works because the client now sends the user's access token, and the column default fills user_id with auth.uid(). Try the same insert without signing in and you get a Row Level Security error instead.
When you keep email confirmation on, set the Site URL and Redirect URLs on the Auth tab so confirmation links send people back to your app. See Site URL and redirect URLs.
6. Connect an AI agent (optional)
If you use Claude Code, Cursor or another MCP client, the AI agents (MCP) page in the dashboard creates a token and a config snippet so the agent can list tables, run SQL and apply migrations in your project. See The SupaHost MCP server.
Next steps
- Pick your framework: Next.js, React, Vue, SvelteKit, Flutter, Python and others in this section
- Tables, columns and data
- Email and password sign-in
- Supabase features on SupaHost