Back to Supabase

Build a User Management App with SvelteKit

apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx

1.26.057.6 KB
Original Source

<$Partial path="quickstart_intro.mdx" />

<Admonition type="note">

If you get stuck while working through this guide, you can find the full example on GitHub.

</Admonition>

<$Partial path="project_setup.mdx" variables={{ "framework": "sveltekit", "tab": "frameworks" }} />

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):

bash
npx sv create supabase-sveltekit
cd supabase-sveltekit
npm install

Then install the Supabase client library: supabase-js

bash
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.

<$CodeTabs>

bash
PUBLIC_SUPABASE_URL="YOUR_SUPABASE_URL"
PUBLIC_SUPABASE_PUBLISHABLE_KEY="YOUR_SUPABASE_PUBLISHABLE_KEY"

</$CodeTabs>

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 Supabase client for SSR

The ssr package configures Supabase to use Cookies, which are required for server-side languages and frameworks.

Install the SSR package:

bash
npm install @supabase/ssr

Creating a Supabase 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:

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/hooks.server.ts" lines={[[1, -1]]} meta="name=src/hooks.server.ts" />

</$CodeTabs>

<$Partial path="get_session_warning.mdx" /> As this tutorial uses TypeScript the compiler complains about event.locals.supabase and event.locals.safeGetSession, you can fix this by updating the src/app.d.ts with the content below:

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/app.d.ts" lines={[[1, -1]]} meta="name=src/app.d.ts" />

</$CodeTabs>

Create a new src/routes/+layout.server.ts file to handle the session on the server-side.

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/+layout.server.ts" lines={[[1, -1]]} meta="name=src/routes/+layout.server.ts" />

</$CodeTabs>

<Admonition type="tip">

Start the dev server (npm run dev) to generate the ./$types files we are referencing in our project.

</Admonition>

Create a new src/routes/+layout.ts file to handle the session and the supabase object on the client-side.

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/+layout.ts" lines={[[1, -1]]} meta="name=src/routes/+layout.ts" />

</$CodeTabs>

Create src/routes/+layout.svelte:

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/+layout.svelte" lines={[[1, -1]]} meta="name=src/routes/+layout.svelte" />

</$CodeTabs>

Set up a login page

Create a magic link login/signup page for your application by updating the routes/+page.svelte file:

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/+page.svelte" lines={[[1, -1]]} meta="name=src/routes/+page.svelte" />

</$CodeTabs>

Create a src/routes/+page.server.ts file that handles the magic link form when submitted.

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/+page.server.ts" lines={[[1, -1]]} meta="name=src/routes/+page.server.ts" />

</$CodeTabs>

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 {{ .ConfirmationURL }} to {{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email.
  • Repeat the previous step for Magic link template.
<Admonition type="tip" label="Did you know?">

You can also customize emails sent out to new users, including the email's looks, content, and query parameters. Check out the settings of your project.

</Admonition>

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_hash sent back from the Supabase Auth server using the token_hash query parameter.
  • Exchanges this token_hash for a session, which you store in storage (in this case, cookies).
  • Finally, redirect the user to the account page or the error page.

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/auth/confirm/+server.ts" lines={[[1, -1]]} meta="name=src/routes/auth/confirm/+server.ts" />

</$CodeTabs>

Authentication error page

If there is an error with confirming the token, redirect the user to an error page.

<$CodeTabs> <$CodeSample path="/user-management/sveltekit-user-management/src/routes/auth/error/+page.svelte" lines={[[1, -1]]} meta="name=src/routes/auth/error/+page.svelte" />

</$CodeTabs>

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.

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/account/+page.svelte" lines={[[1, 3],[6,12],[15,38],[49,-1]]} meta="name=src/routes/account/+page.svelte" />

</$CodeTabs>

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.

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/account/+page.server.ts" lines={[[1, -1]]} meta="name=src/routes/account/+page.server.ts" />

Profile photos

Next, add a way for users to upload a profile photo. Supabase 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:

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/account/Avatar.svelte" lines={[[1, -1]]} meta="name=src/routes/account/Avatar.svelte" />

</$CodeTabs>

Update the account page

With the Avatar component created, update src/routes/account/+page.svelte to include it:

<$CodeTabs>

<$CodeSample path="/user-management/sveltekit-user-management/src/routes/account/+page.svelte" lines={[[1, -1]]} meta="name=src/routes/account/+page.svelte" />

</$CodeTabs>

Launch!

With all the pages in place, run this command in a terminal:

bash
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!