Create a SvelteKit application

Create a new SvelteKit application using the official SvelteKit starter. Run the following command to create a new SvelteKit application:
npx sv create project-name

Install @teamhanko/hanko-elements

The Hanko Elements package provides pre-built authentication components (hanko-auth, hanko-profile) that work with Svelte’s reactive system. Install the package:
cd project-name
npm install @teamhanko/hanko-elements

Setup your Hanko project

Create a Hanko project in the cloud console to get your API URL. Go to the Hanko console and create a project for this application.
Set the APP URL to your development URL (typically http://localhost:5173/ for SvelteKit).

Add your Hanko API URL

Add your Hanko API URL to your environment file. The PUBLIC_ prefix makes it accessible in both server and client-side code in SvelteKit. Retrieve your API URL from the Hanko console and add it to your .env file:
.env
PUBLIC_HANKO_API_URL=https://f4****-4802-49ad-8e0b-3d3****ab32.hanko.io
If you are self-hosting you need to provide the URL of your running Hanko backend.

Create Hanko components

Create a components folder with two files: HankoAuth.svelte and HankoProfile.svelte.

Hanko Auth

Now let’s setup the HankoAuth.tsx file to create a functioning login page. Here we subscribe to the onSessionCreated event, this triggers when a user successfully logs in. You can use these event to perform any desired action.(e.g. redirect to your dashboard). For more information please refer to the Auth Component Page.
components/HankoAuth.svelte
<script>
  import { onMount } from "svelte";
  import { goto } from "$app/navigation";
  import { register } from "@teamhanko/hanko-elements";
  import { env } from "$env/dynamic/public";
  const hankoApi = env.PUBLIC_HANKO_API_URL;

  const redirectAfterLogin = () => {
    //Successfully logged in
    goto("/dashboard");
  };

  onMount(async () => {
    register(hankoApi).catch((error) => {
      // handle error
    });
  });
</script>

<hanko-auth on:onSessionCreated={redirectAfterLogin} />
Now simply import the component you just created into any page.
routes/+page.svelte
<script>
    import HankoAuth from "../components/HankoAuth.svelte";
</script>

<div>
    <HankoAuth/>
</div>
By now, your sign-up and sign-in features should be working. You should see an interface similar to this 👇
sign up

Hanko profile

After setting up the HankoAuth let’s set up the HankoProfile.jsx file to create an interface where users can manage their Email Addresses and credentials. For more information please refer to the Profile Component Page.
components/HankoProfile.svelte
<script>
    import { register } from "@teamhanko/hanko-elements";
    import { onMount } from "svelte";
    import { env } from "$env/dynamic/public";
  
    const hankoApi = env.PUBLIC_HANKO_API_URL;
  
    onMount(async () => {
      register(hankoApi).catch((error) => {
        // handle error
      });
    });
</script>
  
<hanko-profile />
Now simply import the component you just created into any page.
routes/dashboard/+page.svelte
<script>
    import HankoProfile from "../../components/HankoProfile.svelte";
</script>

<div>
    <HankoProfile/>
</div>
It should look something like this 👇
profile page

Implement logout functionality

You can use @teamhanko/hanko-elements to easily logout users. Here we will make a logout button. Create LogoutButton.tsx and insert the code below.
components/LogoutButton.svelte
<script>
    import { Hanko } from "@teamhanko/hanko-elements";
    import { goto } from "$app/navigation";
    import { env } from "$env/dynamic/public";
    const hankoApi = env.PUBLIC_HANKO_API_URL;
  
    const hanko = new Hanko(hankoApi);
    const logout = () => {
      hanko.logout().catch((error) => {
        //Handle Error
      });
      goto("/")//Path to redirect the user to
    };
</script>
  
<button on:click={logout}>Logout</button>

Customize component styles

You can customize the appearance of hanko-auth and hanko-profile components using CSS variables and parts. Refer to our customization guide.

Securing routes

To verify the session token in your SvelteKit application, we’re using the session/validate API request. By checking for a valid session token this middleware will ensure secure access to specific routes, like /dashboard and /protected.
The middleware hook extracts and verifies the session token, and redirect unauthorized users back to the home or login page.
For more info on middlewares / hooks in SvelteKit and where to put the hooks.server.ts file,
please refer to SvelteKit Hooks.
What happens here is that during each request the handle function will be called. It then verifies the session token and redirects the user back if he is on a private route and the session token is not valid.
Hooks like these tends to not always work after creating it, if this is the case try restarting your SvelteKit app.
hooks.server.ts
import { type RequestEvent, redirect, type Handle } from "@sveltejs/kit";

import { env } from "$env/dynamic/public";

const hankoApiUrl = env.PUBLIC_HANKO_API_URL;

export const handle: Handle = async ({ event, resolve }) => {
  const verified = await authenticatedUser(event);

  if (event.url.pathname.startsWith("/dashboard") && !verified) {
    throw redirect(303, "/");
  }

  if (event.url.pathname.startsWith("/profile") && !verified) {
    throw redirect(303, "/");
  }

  const response = await resolve(event);
  return response;
};

const authenticatedUser = async (event: RequestEvent) => {
  const { cookies } = event;
  const cookieToken = cookies.get("hanko");

  const validationOptions = { 
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: `{"session_token":"${cookieToken}"}`
    }

  try {
    const response = await fetch(hankoApiUrl + '/sessions/validate', validationOptions);

    if (!response.ok) throw new Error('Session validation failed');
    
    
    const verifiedResponse = await response.json();
    console.log(verifiedResponse)

    return verifiedResponse.is_valid;
    
  } catch (error) {
    console.log(error)
    return false;
  }
};

Getting user data

Let’s use the Hanko SDK to get user data. Let’s update the dashboard page to display some of the information from the user.
routes/dashboard/+page.svelte
<script>
    import { onMount } from 'svelte';
    import { env } from "$env/dynamic/public";
    import { Hanko } from '@teamhanko/hanko-elements';
    const hankoApi = env.PUBLIC_HANKO_API_URL;

    import HankoProfile from "../../components/HankoProfile.svelte";

    let email = '';
    let id = '';

    async function fetchUserData() {
      const hanko = new Hanko(hankoApi);
      const _email = (await hanko.getUser()).emails?.[0]?.address;
      const _id = (await hanko.getUser()).user_id;
      return { email: _email, id: _id };
    }
  
    onMount(async () => {
      const data = await fetchUserData();
      email = data.email;
      id = data.id;
    });
</script>

<div>
    <HankoProfile/>
    <h2>{email}</h2>
    <h2>{id}</h2>
</div>

Try out yourself

SvelteKit example

Full source code available on our GitHub