> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scute.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Svelte

> Using Scute with Svelte

If you would like to integrate Scute authentication with your Svelte app, you can do so using the `@scute/js-core` package. This approach gives you full control over the authentication flow and allows you to build custom UI components that match your app's design.

Head over to the [example project repo](https://github.com/scuteai/js/tree/main/examples/with-svelte) to check out the complete Svelte example and see how all the components work together.

To get started, install the Scute core SDK with your favorite package manager:

```sh title="Terminal" theme={null}
npm install @scute/js-core
```

Add your [credentials](/docs) to your environment variable handler:

```sh theme={null}
VITE_SCUTE_APP_ID="YOUR_SCUTE_PROJECT_ID"
VITE_SCUTE_BASE_URL="YOUR_SCUTE_BASE_URL"
```

### Initialize the Scute client

First initialize the Scute client using the `createClient` method exposed by `@scute/js-core` package:

```ts theme={null}
// scute.ts

import { createClient } from "@scute/js-core";

export const scuteClient = createClient({
  appId: import.meta.env.VITE_SCUTE_APP_ID,
  baseUrl: import.meta.env.VITE_SCUTE_BASE_URL,
});
```

### Create your main App component

Create your main `App.svelte` component that handles the authentication flow:

```svelte theme={null}
<!-- App.svelte -->
<script lang="ts">
  import { onMount } from 'svelte';
  import {
    getMeaningfulError,
    SCUTE_MAGIC_PARAM,
    SCUTE_SKIP_PARAM,
    type ScuteTokenPayload,
    type ScuteUserData,
  } from "@scute/js-core";
  import { scuteClient } from './scute';
  import LoginForm from './lib/LoginForm.svelte';
  import MagicSent from './lib/MagicSent.svelte';
  import MagicVerify from './lib/MagicVerify.svelte';
  import OtpForm from './lib/OtpForm.svelte';
  import RegisterDevice from './lib/RegisterDevice.svelte';
  import Profile from './lib/Profile.svelte';

  let identifier = '';
  let component = '';
  let magicLinkToken: string | null = null;
  let tokenPayload: ScuteTokenPayload | null = null;

  // Catch magic link token from url if it exists and verify it
  // OAuth token is also a magic link token and will be handled by this block.
  onMount(() => {
    const token = scuteClient.getMagicLinkToken();
    if (token) {
      component = 'magic_verify';
      magicLinkToken = token;
      return;
    }

    // Check existing session on app load
    const getSession = async () => {
      const { data, error } = await scuteClient.getSession();
      if (error) {
        console.error(error);
      }
      if (data?.session && data.session.status === "authenticated") {
        component = "profile";
      } else {
        component = "login";
      }
    };
    getSession();
  });

  function setComponent(newComponent: string) {
    component = newComponent;
  }

  function setIdentifier(newIdentifier: string) {
    identifier = newIdentifier;
  }

  function setTokenPayload(newTokenPayload: ScuteTokenPayload | null) {
    tokenPayload = newTokenPayload;
  }

  function setMagicLinkToken(token: string | null) {
    magicLinkToken = token;
  }
</script>

<main class="app">
  {#if component === "profile"}
    <Profile {setComponent} />
  {:else if component === "login"}
    <LoginForm {scuteClient} {identifier} {setIdentifier} {setComponent} />
  {:else if component === "magic_verify"}
    <MagicVerify {scuteClient} {magicLinkToken} {setTokenPayload} {setComponent} />
  {:else if component === "magic_sent"}
    <MagicSent {identifier} />
  {:else if component === "register_device"}
    <RegisterDevice {scuteClient} {tokenPayload} {setComponent} />
  {:else if component === "otp_verify"}
    <OtpForm {scuteClient} {identifier} {setComponent} {setTokenPayload} />
  {/if}
</main>

<style>
  .app {
    display: flex;
    flex-direction: column;
    gap: 32px;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 2rem;
  }
</style>
```

### Create a Login component

Create a `LoginForm.svelte` component for handling user authentication:

```svelte theme={null}
<!-- lib/LoginForm.svelte -->
<script lang="ts">
  import { getMeaningfulError, type ScuteClient } from "@scute/js-core";

  export let scuteClient: ScuteClient;
  export let identifier: string;
  export let setIdentifier: (identifier: string) => void;
  export let setComponent: (component: string) => void;

  async function handleSubmit(e: Event) {
    e.preventDefault();
    const { data, error } = await scuteClient.signInOrUp(identifier);

    if (error) {
      console.log("signInOrUp error", getMeaningfulError(error));
      return;
    }

    if (!data) {
      // passkey verified.
      setComponent("profile");
    } else {
      if (identifier.includes("@")) {
        setComponent("magic_sent");
      } else {
        setComponent("otp_verify");
      }
    }
  }
</script>

<div class="login-form">
  <h1>Sign In</h1>
  <form on:submit={handleSubmit}>
    <input
      type="text"
      placeholder="Email or phone number"
      bind:value={identifier}
      required
    />
    <button type="submit">Continue</button>
  </form>
</div>

<style>
  .login-form {
    max-width: 400px;
    padding: 2rem;
    border: 1px solid #ddd;
    border-radius: 8px;
  }
  
  input {
    width: 100%;
    padding: 0.75rem;
    margin: 0.5rem 0;
    border: 1px solid #ddd;
    border-radius: 4px;
  }
  
  button {
    width: 100%;
    padding: 0.75rem;
    background: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }
  
  button:hover {
    background: #0056b3;
  }
</style>
```

### Create a Profile component

Create a `Profile.svelte` component for authenticated users:

```svelte theme={null}
<!-- lib/Profile.svelte -->
<script lang="ts">
  import { onMount } from 'svelte';
  import { type ScuteUserData } from "@scute/js-core";
  import { scuteClient } from '../scute';

  export let setComponent: (component: string) => void;

  let user: ScuteUserData | null = null;

  onMount(() => {
    const getSession = async () => {
      const { data, error } = await scuteClient.getSession();
      if (error) {
        console.error(error);
      }
      if (!data?.session || data.session.status === "unauthenticated") {
        setComponent("login");
      } else {
        user = data.user;
      }
    };
    getSession();
  });

  async function handleSignOut() {
    await scuteClient.signOut();
    setComponent("login");
  }
</script>

{#if user}
  <div class="profile">
    <h1>Welcome!</h1>
    <p>User ID: {user.id}</p>
    <p>Email: {user.email || 'N/A'}</p>
    <p>Phone: {user.phoneNumber || 'N/A'}</p>
    <button on:click={handleSignOut}>Sign Out</button>
  </div>
{:else}
  <div>Loading...</div>
{/if}

<style>
  .profile {
    max-width: 400px;
    padding: 2rem;
    border: 1px solid #ddd;
    border-radius: 8px;
    text-align: center;
  }
  
  button {
    padding: 0.75rem 1.5rem;
    background: #dc3545;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    margin-top: 1rem;
  }
  
  button:hover {
    background: #c82333;
  }
</style>
```

### Additional Components

The example also includes additional components for handling different authentication flows:

* **`MagicVerify.svelte`** - For verifying magic link tokens
* **`MagicSent.svelte`** - Shows confirmation when magic link is sent
* **`OtpForm.svelte`** - For OTP verification (SMS/phone)
* **`RegisterDevice.svelte`** - For WebAuthn device registration

You can find the complete implementation of these components in the [example repository](https://github.com/scuteai/js/tree/main/examples/with-svelte/src/lib).

### Running the Example

1. Clone the example repository
2. Copy `env.example` to `.env` and add your credentials
3. Install dependencies: `npm install`
4. Start the development server: `npm run dev`

Congrats! You now have a working Scute authentication system in your Svelte app!

## Core Methods

The `scuteClient` provides several methods for authentication:

### `signInOrUp(identifier: string)`

Initiates the sign-in or sign-up process with an email or phone number.

### `getSession()`

Retrieves the current user session and user data.

### `signOut()`

Signs out the current user and clears the session.

### `getMagicLinkToken()`

Extracts magic link tokens from the current URL for verification.

### `verifyMagicLink(token: string)`

Verifies a magic link token and completes authentication.

For more methods and detailed API documentation, check out the [type docs](https://scute-js-docs.netlify.app/).
