This tutorial demonstrates how to build a basic user management app. The app authenticates and identifies the user, stores their profile information in the database, and allows the user to log in, update their profile details, and upload a profile photo. The app uses:
- Zuvo Database - a Postgres database for storing your user data and Row Level Security so data is protected and users can only access their own information.
- Zuvo Auth - allow users to sign up and log in.
- Zuvo Storage - allow users to upload a profile photo.

Project setup
Before you start building you need to set up the Database and API. You can do this by starting a new Project in Zuvo and then creating a "schema" inside the database.
Create a project
- Create a new project in the Zuvo Studio.
- Enter your project details.
- Wait for the new database to launch.
Set up the database schema
Now set up the database schema. You can use the "User Management Starter" quickstart in the SQL Editor, or you can copy/paste the SQL from below and run it.
- Go to the SQL Editor page in the Dashboard.
- Click User Management Starter under the Reference > Examples tab.
- Click Run.
supabase migration new user_management_starter
Building the app
Start building the Svelte app from scratch.
Initialize a Svelte app
Use the SvelteKit Skeleton Project to initialize an app called supabase-sveltekit (for this tutorial, select "SvelteKit minimal" and use TypeScript):
npx sv create supabase-sveltekit
cd supabase-sveltekit
npm install
Then install the Zuvo client library: supabase-js
npm install @supabase/supabase-js
And finally, save the environment variables in a .env file.
All you need are the PUBLIC_SUPABASE_URL and the key that you copied earlier.
App styling (optional)
An optional step is to update the CSS file src/styles.css to make the app look nice.
You can find the full contents of this file in the example repository.
Creating a Zuvo client for SSR
The ssr package configures Zuvo to use Cookies, which are required for server-side languages and frameworks.
Install the SSR package:
npm install @supabase/ssr
Creating a Zuvo client with the ssr package automatically configures it to use Cookies. This means the user's session is available throughout the entire SvelteKit stack - page, layout, server, and hooks.
Add the code below to a src/hooks.server.ts file to initialize the client on the server:
As this tutorial uses TypeScript the compiler complains about event.locals.supabase. You can fix this by updating the src/app.d.ts with the content below:
Create a new src/routes/+layout.server.ts file to handle the session on the server-side.
Create a new src/routes/+layout.ts file to handle the session and the supabase object on the client-side.
Create src/routes/+layout.svelte:
Set up a login page
Create a magic link login/signup page for your application by updating the routes/+page.svelte file:
Create a src/routes/+page.server.ts file that handles the magic link form when submitted.
Email template
Change the email template to support a server-side authentication flow.
Before proceeding, change the email template to support sending a token hash:
- Go to the Auth > Emails page in the project dashboard.
- Select the Confirm signup template.
- Change
ConfirmationURLtoSiteURL/auth/confirm?token_hash=TokenHash&type=email. - Repeat the previous step for Magic link template.
Confirmation endpoint
As this is a server-side rendering (SSR) environment, you need to create a server endpoint responsible for exchanging the token_hash for a session.
The following code snippet performs the following steps:
- Retrieves the
token_hashsent back from the Zuvo Auth server using thetoken_hashquery parameter. - Exchanges this
token_hashfor a session, which you store in storage (in this case, cookies). - Finally, redirect the user to the
accountpage or theerrorpage.
Authentication error page
If there is an error with confirming the token, redirect the user to an error page.
Account page
After a user signs in, they need to be able to edit their profile details page.
Create a new src/routes/account/+page.svelte file with the content below.
Now, create the associated src/routes/account/+page.server.ts file that handles loading data from the server through the load function
and handle all form actions through the actions object.
Code sample: see project quickstart in Zuvo Studio.
Profile photos
Next, add a way for users to upload a profile photo. Zuvo configures every project with Storage for managing large files like photos and videos.
Create an upload widget
Start by creating a new component called Avatar.svelte in the src/routes/account directory:
Update the account page
With the Avatar component created, update src/routes/account/+page.svelte to include it:
Launch!
With all the pages in place, run this command in a terminal:
npm run dev
And then open the browser to localhost:5173 and you should see the completed app.

At this stage you have a fully functional application!