---
url: 'https://www.corbado.com/blog/sveltekit-passkeys'
title: 'How to Build SvelteKit Apps with Passkeys'
description: 'A developer tutorial on how to implement passkeys in SvelteKit apps. We show how to integrate passkeys using UI components, Flowbite (Tailwind CSS) and npm.'
lang: 'en'
author: 'Lukas'
date: '2024-01-29T00:00:00.000Z'
lastModified: '2026-03-25T10:00:20.601Z'
keywords: 'SvelteKit'
category: 'Passkeys Implementation'
---

# How to Build SvelteKit Apps with Passkeys

## Key Facts

- **SvelteKit passkey integration** requires two Corbado packages: `@corbado/web-js` for
  client-side authentication UI and `@corbado/node-sdk` for server-side session
  validation.
- **SSR must be disabled** in SvelteKit when using Corbado web-js. Set
  `export const ssr = false` in your +layout.server.ts file to prevent server-side
  rendering conflicts.
- The **`setShortSessionCookie`** config option must be set to `true` during Corbado
  initialization so the `cbo_short_session` JWT cookie is created and available for
  server-side user retrieval.
- The **`mountAuthUI`** method renders the passkey sign-up and login component into a
  target DOM element and accepts an `onLoggedIn` callback to handle post-authentication
  navigation.
- Server-side user validation uses **`sdk.sessions().validateToken()`** against the
  `cbo_short_session` cookie, returning a user object with `userId` on success.

## 1. Introduction

In this blog post, we'll be walking through the process of building a sample application
with passkey authentication using Sveltekit. We'll cover how to embed the Corbado UI
component and implement [passkey login](https://www.corbado.com/blog/passkey-login-best-practices) functionality
for a seamless user experience. Furthermore, we'll use the Corbado node sdk to retrieve
user information on the server.

If you want to see the finished code, please have a look at our
[sample application GitHub repository](https://github.com/corbado/example-passkeys-sveltekit):

The result looks as follows:

![Sveltekit Passkeys Login Page](https://www.corbado.com/website-assets/Screenshot_2024_04_25_at_18_18_35_2cb2238934.png)

## 2. Prerequisites

This tutorial assumes basic familiarity with [Svelte](https://www.corbado.com/blog/svelte-passkeys), HTML, CSS
and JavaScript. Lets dive in! Moreover, you need to have Node and NPM installed on your
machine.

## 3. Svelte Passkey Repository Structure

Lets first discuss the structure of our project
([full GitHub repo](https://github.com/corbado/example-passkeys-svelte)):

```
.
├── .env
├── package.json
└── src
    ├── app.html
    └── routes
        ├── +layout.svelte
        ├── +layout.server.ts
        ├── +page.svelte
        └── profile
            ├── +page.server.ts
            └── +page.svelte
```

The rest of the files of this project can be ignored for the purpose of this tutorial.

## 4. Set Up the Svelte Project

In the following, we explain step-by-step what needs to be done to successfully set up the
[Svelte](https://www.corbado.com/blog/svelte-passkeys) project.

Lets start out by initializing a new [Svelte](https://www.corbado.com/blog/svelte-passkeys) project. In this
tutorial, were using Svelte version 4.2.7:

```bash
npm create svelte@latest example-passkeys-svelte
```

In the installation guide steps, we select the following (if youre asked to install or
update the create-svelte package, click Yes to proceed):

- App template: Skeleton project
- Type checking with TypeScript: We're using TypeScript here, but feel free to choose
  whatever you prefer.
- Additional options: We're using ESLint and Prettier

If you're asked to proceed click "Yes"

```bash
cd example-passkeys-svelte
```

Let's also install the Corbado web-js and node-sdk dependencies:

```bash
npm i @corbado/web-js @corbado/node-sdk
```

Optionally, you can also install the Corbado types for an enhanced typescript experience:

```bash
npm i -D @corbado/types
```

If you run

```bash
npm install
```

and

```bash
npm run dev
```

the sample Svelte skeleton application starts at
[http://localhost:5173](http://localhost:5173):

![Svelte Passkeys Skeleton](https://www.corbado.com/website-assets/65256646fbb47fb7bbe7ff40_svelte_skeleton_0ccafbb6c4.png)

## 5. Set Up the Corbado UI Component for Passkey Authentication

### 5.1 Set up your Corbado account and project

Visit the [Corbado developer panel](https://app.corbado.com/signin) to sign up and create
your account (you'll see the passkey sign-up in action here!).

![Sveltekit Corbado Developer Panel Sign-up](https://www.corbado.com/website-assets/dev_panel_d7f6cc96ed.png)

In the project setup wizard, begin by selecting an appropriate name for your project. For
the product selection, opt for "Corbado Complete". Subsequently, specify your technology
stack and select "DEV along with "Corbado session management" options. Afterwards, you'll
get more foundational setup guidance.

Next, choose "Web app" as an application type and Svelte as your framework. In the
application settings, define your application url and
[relying party](https://www.corbado.com/glossary/relying-party) id as follows:

![App settings](https://www.corbado.com/website-assets/application_settings_e7049b45fa.png)

- **Application URL:** Provide the URL where you embedded the UI component, here:
  [http://localhost:5173](http://localhost:5173).
- [**Relying Party ID**](https://www.corbado.com/blog/webauthn-relying-party-id-rpid-passkeys)**:** Provide the
  domain (no protocol, no port and no path) where passkeys should be bound to, here:
  localhost

Then, retrieve your `project ID`, `API secret`, `Frontend API` and `Backend API` URLs from
the developer panel and store it in your environment file. You can find it
[here](https://app.corbado.com/app/settings/general/project-info) under Corbado API
access.

![Screenshot 2024-09-16 at 18.01.13.png](https://www.corbado.com/website-assets/Screenshot_2024_09_16_at_18_01_13_bf56dc302c.png)

Your environment file should look like this:

```txt
PUBLIC_CORBADO_PROJECT_ID=<your-corbado-project-id>
CORBADO_API_SECRET=<your-corbado-api-secret>
CORBADO_FRONTEND_API=<you-corbado-frontend-api-url>
CORBADO_BACKEND_API=<your-corbado-backend-api-url>
```

You'll need it later to embed the Corbado UI component in your Svelte app.

### 5.2 Embed the UI Component in the Frontend

Now, lets jump back to the code we created from [step 4](#set-up-svelte-project).

First, we'll disable ssr as that's currently not supported by the Corbado web-js package,
but we're working on it ;)

We'll do that by creating a +layout.server.ts file with the following content:

```typescript
export const ssr = false;
```

Then, we'll create our outer layout which will handle the initialization of our Corbado
project. It acts as a boundary that only renders the rest of the app once the Corbado
project is initialized.

```svelte
<script lang="ts">
    import Corbado from "@corbado/web-js";
    import {onMount} from "svelte";
    import { PUBLIC_CORBADO_PROJECT_ID } from '$env/static/public';

    let isInitialized = false;
    onMount(async () => {
        await Corbado.load({
            projectId: PUBLIC_CORBADO_PROJECT_ID,
            darkMode: 'off',
            setShortSessionCookie: true
        });
        isInitialized = true; // Set to true once Corbado is initialized
    });
</script>

<div>
    {#if isInitialized}
        <slot></slot>
    {/if}
</div>
```

It's important that we provide the `setShortSessionCookie: true` config option, so a
cookie is created on login, which we'll need later to retrieve user data on the server.

Next, we modify the home page. The home page is the file in
[src](https://www.corbado.com/glossary/src)/routes/+page.svelte. This file contains the sign up / login UI
component and navigates to `/profile` once the user is authenticated.

```svelte
<script lang="ts">
    import Corbado from '@corbado/web-js';
    import {onMount} from 'svelte';

    let authElement: HTMLDivElement;

    onMount(() => {
        Corbado.mountAuthUI(
            authElement, {
                onLoggedIn: () => window.location.href = "/profile",
            })
    })
</script>

<div bind:this={authElement}></div>
```

### 5.3 Set Up the Profile Page

Lastly, let's create the profile page under the `/profile` route. To demonstrate our node
SDK's capabilitys, we'll retrieve all user information on the server, so let's create our
+page.server.ts file.

First, let's import everything we need, including our environement variables and set up
the Corbado node SDK:

```ts
import { type RequestEvent } from "@sveltejs/kit";
import { PUBLIC_CORBADO_PROJECT_ID } from "$env/static/public";
import {
    CORBADO_API_SECRET,
    CORBADO_FRONTEND_API,
    CORBADO_BACKEND_API,
} from "$env/static/private";
import { SDK, Config } from "@corbado/node-sdk";

const config = new Config(
    PUBLIC_CORBADO_PROJECT_ID,
    CORBADO_API_SECRET,
    CORBADO_FRONTEND_API,
    CORBADO_BACKEND_API,
);
const sdk = new SDK(config);
```

Next, we'll create a load function that retrieves the request cookies and from it the
`cbo_short_session` cookie which stores our jwt session. We'll handle all cases and either
return a user object with his email and id or an undefined user, so we can determine
during render whether the user is logged in.

```ts
export async function load({ request }: RequestEvent) {
    const cookies = parseCookies(request.headers.get("Cookie") || "");
    const cbo_short_session: string | undefined = cookies.cbo_short_session;
    if (!cbo_short_session) {
        return { id: undefined };
    }
    try {
        const user = await sdk.sessions().validateToken(cbo_short_session);

        return { id: user.userId };
    } catch {
        return { id: undefined };
    }
}

function parseCookies(cookieHeader: string): Record<string, string> {
    return Object.fromEntries(
        cookieHeader.split(";").map((cookie) => {
            const [name, ...rest] = cookie.trim().split("=");
            return [name, rest.join("=")];
        }),
    );
}
```

The corresponding page will access our loader's data and show the user's name and
[user ID](https://www.corbado.com/blog/webauthn-user-id-userhandle) and provides a button to log out. If the user
isn't logged in, we'll display a link back to the homepage.

```svelte
<script lang="ts">
    import type { PageData } from './$types';
    import Corbado from '@corbado/web-js';
    import { goto } from '$app/navigation';

    export let data: PageData

    async function handleLogout() {
        await Corbado.logout()
        await goto("/")
    }
</script>

<div>
    {#if (data.id)}
        <h1>
            Profile Page
        </h1>
        <p>
            User-id: {data.id}
        </p>
        <button on:click={handleLogout}>
            Logout
        </button>
    {:else}
        <h1>
            You aren't logged in.
        </h1>
        <p>Go <a href="/">Home</a></p>
    {/if}
</div>
```

With the combination of the web-js package and the node-sdk we have access to
authentication information on the client and the server. If you're interested in what the
profile page would look like if we had retrieved user information on the client side, take
a look at our Svelte blog post.

### 5.4 Start Using Passkeys

If everything is set up and installed, run the application with

```bash
npm run dev
```

You should see the following screen:

![Svelte Passkeys Login Page](https://www.corbado.com/website-assets/Screenshot_2024_04_25_at_18_38_50_c2cafffc15.png)

After successful sign up / login, you see the profile page:

![Svelte Passkeys Profile Page](https://www.corbado.com/website-assets/Svelte_Corbado_Profile_Page_8d2d4ebb3e.png)

## 6. Conclusion

This tutorial showed how easy it is to add
[passwordless authentication](https://www.corbado.com/glossary/passwordless-authentication) with passkeys to a
Svelte app using Corbado. Besides the passkey-first authentication, Corbado provides
simple session management, that we used for a retrieval of basic user data. If you want to
read more about how you can leverage Corbado's session management to retrieve backend
data, please check out our documentation
[here ](https://docs.corbado.com/sessions/overview)or if you want to add Corbado to your
existing app with existing users, please see our documentation
[here](https://docs.corbado.com/products/corbado-connect).

## Frequently Asked Questions

### What npm packages do I need to implement passkeys in a SvelteKit app?

You need `@corbado/web-js` for the client-side passkey UI component and
`@corbado/node-sdk` for server-side session management. Optionally, install
`@corbado/types` as a dev dependency for improved TypeScript support.

### Why do I need to disable SSR when adding passkeys to SvelteKit with Corbado?

The `@corbado/web-js` package does not currently support server-side rendering in
SvelteKit. You must set `export const ssr = false` in +layout.server.ts to ensure the
Corbado UI component only renders on the client.

### How do I validate a passkey session on the server side in SvelteKit?

Parse the incoming request cookies to extract the `cbo_short_session` cookie, then call
`sdk.sessions().validateToken()` from the Corbado Node SDK inside your `load` function.
This returns the authenticated user's details or throws an error if the session is
invalid.

### How do I configure Corbado for local SvelteKit development with passkeys?

Set your Application URL to `http://localhost:5173` and your Relying Party ID to
`localhost` in the Corbado developer panel. Then store your project ID, API secret and
frontend and backend API URLs in a `.env` file for use in your SvelteKit app.
