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

# SvelteKit

> Add your Invent assistant to SvelteKit apps

## Overview

Add your Invent AI assistant to any SvelteKit application. Perfect for Svelte applications with server-side rendering and static generation.

## Installation

<Steps>
  <Step title="Create Assistant Component">
    ```svelte theme={"system"}
    <!-- src/lib/components/InventAssistant.svelte -->
    <script lang="ts">
      export let assistantId: string;
      export let themeAppearance: 'auto' | 'light' | 'dark' = 'auto';
      export let themeButtonBackgroundColor: string | undefined = undefined;
      export let themeButtonColor: string | undefined = undefined;
      export let userId: string | undefined = undefined;
      export let userName: string | undefined = undefined;
      export let userHash: string | undefined = undefined;
      export let userAvatar: string | undefined = undefined;
    </script>

    <invent-assistant
      assistant-id={assistantId}
      theme-appearance={themeAppearance}
      theme-button-background-color={themeButtonBackgroundColor}
      theme-button-color={themeButtonColor}
      user-id={userId}
      user-name={userName}
      user-hash={userHash}
      user-avatar={userAvatar}
    />
    <script
      type="text/javascript"
      src="https://www.useinvent.com/embed.js"
      async
      defer
    ></script>
    ```

    ````
    </Step>

    <Step title="Add to Root Layout">
    ```svelte
    <!-- src/routes/+layout.svelte -->
    <script lang="ts">
      import InventAssistant from '$lib/components/InventAssistant.svelte';
      import { PUBLIC_INVENT_ASSISTANT_ID } from '$env/static/public';
    </script>

    <slot />

    <InventAssistant assistantId={PUBLIC_INVENT_ASSISTANT_ID} />
    ````
  </Step>

  <Step title="Configure Environment">
    Add to `.env`:

    ```bash theme={"system"}
    PUBLIC_INVENT_ASSISTANT_ID=ast_YOUR_ASSISTANT_ID
    INVENT_SECRET_KEY=your_secret_key_here
    ```
  </Step>
</Steps>

## User Authentication

<Warning>
  **Security Requirement:** When using any `user-*` attributes (`user-id`, `user-name`, `user-avatar`), you **must** also provide `user-hash`. Both `user-id` and `user-hash` must be provided together, or neither should be provided. The `user-hash` must be generated on your backend using HMAC-SHA256 with your assistant's secret key. Never expose the secret key to the client.
</Warning>

### Server-Side Hash Generation

Use SvelteKit server endpoints:

```typescript theme={"system"}
// src/routes/api/user-hash/+server.ts
import { json } from '@sveltejs/kit';
import { createHmac } from 'crypto';
import { INVENT_SECRET_KEY } from '$env/static/private';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async ({ locals }) => {
  // Get user from your auth system (e.g., lucia, session)
  const user = locals.user;

  if (!user) {
    return json({ error: 'Unauthorized' }, { status: 401 });
  }

  const userId = user.id;
  const userHash = createHmac('sha256', INVENT_SECRET_KEY)
    .update(userId)
    .digest('hex');

  return json({
    userId,
    userName: user.name,
    userAvatar: user.avatar,
    userHash,
  });
};
```

### Using Server Load Functions

```typescript theme={"system"}
// src/routes/+layout.server.ts
import { createHmac } from 'crypto';
import { INVENT_SECRET_KEY } from '$env/static/private';
import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ locals }) => {
  const user = locals.user;

  if (!user) {
    return { userData: null };
  }

  const userId = user.id;
  const userHash = createHmac('sha256', INVENT_SECRET_KEY)
    .update(userId)
    .digest('hex');

  return {
    userData: {
      userId,
      userName: user.name,
      userAvatar: user.avatar,
      userHash,
    },
  };
};
```

Then use in your layout:

```svelte theme={"system"}
<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import InventAssistant from '$lib/components/InventAssistant.svelte';
  import { PUBLIC_INVENT_ASSISTANT_ID } from '$env/static/public';
  import type { LayoutData } from './$types';

  export let data: LayoutData;
</script>

<slot />

<InventAssistant
  assistantId={PUBLIC_INVENT_ASSISTANT_ID}
  userId={data.userData?.userId}
  userName={data.userData?.userName}
  userHash={data.userData?.userHash}
  userAvatar={data.userData?.userAvatar}
/>
```

## Integration with Lucia Auth

```typescript theme={"system"}
// src/routes/+layout.server.ts
import { createHmac } from 'crypto';
import { INVENT_SECRET_KEY } from '$env/static/private';
import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ locals }) => {
  const session = await locals.auth.validate();

  if (!session?.user) {
    return { userData: null };
  }

  const userId = session.user.userId;
  const userHash = createHmac('sha256', INVENT_SECRET_KEY)
    .update(userId)
    .digest('hex');

  return {
    userData: {
      userId,
      userName: session.user.name,
      userAvatar: session.user.avatar,
      userHash,
    },
  };
};
```

## TypeScript Support

Add type declarations:

```typescript theme={"system"}
// src/app.d.ts
declare global {
  namespace App {
    interface Locals {
      user?: {
        id: string;
        name: string;
        avatar?: string;
      };
    }
  }

  namespace svelteHTML {
    interface HTMLAttributes<T> {
      'assistant-id'?: string;
      'theme-appearance'?: 'auto' | 'light' | 'dark';
      'theme-button-background-color'?: string;
      'theme-button-color'?: string;
      'user-id'?: string;
      'user-name'?: string;
      'user-hash'?: string;
      'user-avatar'?: string;
    }
  }

  interface Window {
    inventContext?: Record<string, any>;
  }
}

export {};
```

## Using Stores

Create a store for user authentication:

```typescript theme={"system"}
// src/lib/stores/inventAuth.ts
import { writable } from 'svelte/store';
import { browser } from '$app/environment';

interface UserData {
  userId: string;
  userName: string;
  userHash: string;
  userAvatar?: string;
}

function createInventAuthStore() {
  const { subscribe, set } = writable<UserData | null>(null);

  return {
    subscribe,
    fetchUserAuth: async () => {
      if (!browser) return;

      try {
        const response = await fetch('/api/user-hash');
        const data = await response.json();
        set(data);
      } catch (error) {
        set(null);
      }
    },
    clear: () => set(null),
  };
}

export const inventAuth = createInventAuthStore();
```

Usage:

```svelte theme={"system"}
<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { onMount } from 'svelte';
  import { inventAuth } from '$lib/stores/inventAuth';
  import InventAssistant from '$lib/components/InventAssistant.svelte';
  import { PUBLIC_INVENT_ASSISTANT_ID } from '$env/static/public';

  onMount(() => {
    inventAuth.fetchUserAuth();
  });
</script>

<slot />

<InventAssistant
  assistantId={PUBLIC_INVENT_ASSISTANT_ID}
  userId={$inventAuth?.userId}
  userName={$inventAuth?.userName}
  userHash={$inventAuth?.userHash}
  userAvatar={$inventAuth?.userAvatar}
/>
```

## Tips for SvelteKit

<CardGroup cols={2}>
  <Card title="Server Load Functions" icon="server">
    Use server load for secure hash generation
  </Card>

  <Card title="Type Safety" icon="shield-check">
    Full TypeScript support with proper types
  </Card>

  <Card title="SSR Compatible" icon="bolt">
    Works with SSR and SPA modes
  </Card>

  <Card title="Reactive" icon="arrows-rotate">
    Leverage Svelte's reactivity system
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Script not loading">
    **Solutions:**

    * Check browser guard: `if (browser)`
    * Ensure script loads in onMount
    * Verify URL is correct
    * Check browser console for errors
  </Accordion>

  <Accordion title="SSR hydration issues">
    **Solutions:**

    * Use browser check before accessing window
    * Load script client-side only
    * Ensure user data is fetched client-side if needed
  </Accordion>

  <Accordion title="Environment variables not working">
    **Solutions:**

    * Restart dev server after adding env variables
    * Use `PUBLIC_` prefix for public variables
    * Keep secret key without prefix (private)
    * Check import from correct \$env module
  </Accordion>
</AccordionGroup>

## Best Practices

<Note>
  * Use server load functions or endpoints for hash generation
  * Keep secret key in `.env` (never commit)
  * Use `PUBLIC_` prefix only for non-sensitive variables
  * Always check `browser` before accessing window
  * Leverage SvelteKit's built-in security features
</Note>
