This is a template for a project using Nuxt3 + Supabase.
See a demo for the sample application here.
Clone this repository in your desired folder:
git clone https://github.com/razvanbaboiucs/nuxt-supabase-poc.git
Open the project in the preffered code editor (Visual Studio Code is recommended).
Add a new file named .env and add the following contents:
SUPABASE_URL="<url>"
SUPABASE_KEY="<project_key>"
SUPABASE_SERVICE_KEY="<service_key>"
Make sure to install the dependencies by running:
npm i
Go to Supabase and create a new account.
Create a new project (make sure to set a region close to you).
After the project is fully initialized go to Settings > API and do the following steps:
- copy the URL and replace from the .env file with the copied value;
- copy the anon public Project API key and replace <project_key> from the .env file with the copied value;
- copy the service_role secret Project API key and replace <service_key> from the .env file with the copied value.
Go to Authentication > Providers and make sure that Email is enabled. Click on it and disable the following Confirm email (to keep things simple we won't be using this feature but feel free to play around with it - note that you will most probably need to create a /confirm page in the Nuxt3 project).
Go to SQL editor and create a new query named: Create user table with the following SQL script and run it:
create table
public.users (
id uuid not null,
created_at timestamp with time zone not null default now(),
email text not null,
role text not null default 'basic_user'::text,
constraint users_pkey primary key (id),
constraint users_id_fkey foreign key (id) references auth.users (id) on update cascade on delete cascade
) tablespace pg_default;
Create a new query named: Create resources table with the following SQL script and run it:
create table
public.resources (
id bigint generated by default as identity,
created_at timestamp with time zone not null default now(),
name text not null,
path text not null,
description text null,
constraint resources_pkey primary key (id)
) tablespace pg_default;
Create a new query named: Create access requests table with the following SQL script and run it:
create table
public.access_requests (
id bigint generated by default as identity,
created_at timestamp with time zone not null default now(),
user_id uuid not null,
resource_id bigint not null,
status text null default 'pending'::text,
constraint access_requests_pkey primary key (id),
constraint access_requests_resource_id_fkey foreign key (resource_id) references resources (id) on delete cascade,
constraint access_requests_user_id_fkey foreign key (user_id) references users (id) on update cascade on delete cascade
) tablespace pg_default;
Go to Table Editor and select the users table. Add the following RLS policy from the "For full customization" option:
- Read policy
- policy name: Enable read to all authenticated users
- allowed operation: SELECT
- target roles: authenticated
- using expression: true
Select the resources table. Add the following RLS policies from the "For full customization" option:
- Read policy
- policy name: Enable read to all authenticated users
- allowed operation: SELECT
- target roles: authenticated
- using expression: true
- Insert policy
- policy name: Enable insert to all authenticated users
- allowed operation: INSERT
- target roles: authenticated
- using expression: true
Select the access_requests table. Add the following RLS policies from the "For full customization" option:
- Read policy
- policy name: Enable read to all authenticated users
- allowed operation: SELECT
- target roles: authenticated
- using expression: true
- Insert policy
- policy name: Enable insert to all authenticated users
- allowed operation: INSERT
- target roles: authenticated
- using expression: true
- Update policy
- policy name: Enable update to all authenticated users
- allowed operation: UPDATE
- target roles: authenticated
- using expression: true
- with check expression: true
While still on the access_requests table, enable the Realtime feature for it.
Go to SQL editor and create a new query called "Handle new user added". Add the following SQL script to it and run it:
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.users (id, email, role)
values (new.id, new.email, 'basic_user');
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_inserted
after insert on auth.users
for each row execute procedure public.handle_new_user();
This script creates a trigger that is ran whenever a new user is created in the system (on insert in the auth.users table). The trigger calls a function which duplicates the id and email of the added user in the public.users table and assigns the user the role basic_user.
Note: if you want a user to have an admin role you need to change the role manually in the public.users table entry.
Note: the choice to create a separate users table might seem odd since there is already a users table in the auth schema of the database. But the table is need if we want to be able to query data on user related data, as it is done in the components/AccessRequestsTable.vue component.
Go to Storage and create a new bucket called: resources. In the newly created bucket, create a new folder called: public. Here is the place where the "resources" from the app will live.
Go to Storage > Policies.
Add a new policy for storage.buckets from the "For full customization" option:
- Read policy
- policy name: Enable read to all authenticated users
- allowed operation: SELECT
- target roles: authenticated
- using expression: true
Add the following new policies for storage.objects from the "For full customization" option:
- Read policy
- policy name: Enable read to all authenticated users
- allowed operation: SELECT
- target roles: authenticated
- using expression: true
- Insert policy
- policy name: Enable insert to all authenticated users
- allowed operation: INSERT
- target roles: authenticated
- using expression: true
Start the development server on http://localhost:3000
:
npm run dev
Build the application for production:
npm run build
Locally preview production build:
npm run preview
Check out the deployment documentation for more information.
Note: for the deployment of the demo I am using Vercel. The deployment setup on Vercel is pretty straight forward and there are plenty of tutorials online for how to it for a Nuxt3 app. See an official tutorial from the Nuxt team.