Skip to main content

Overview

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

Installation

1

Create Assistant Component

<!-- 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/button.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} />
2

Configure Environment

Add to .env:
PUBLIC_INVENT_ASSISTANT_ID=ast_YOUR_ASSISTANT_ID
INVENT_SECRET_KEY=your_secret_key_here

User Authentication

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.

Server-Side Hash Generation

Use SvelteKit server endpoints:
// 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

// 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:
<!-- 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

// 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:
// 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:
// 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:
<!-- 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

Server Load Functions

Use server load for secure hash generation

Type Safety

Full TypeScript support with proper types

SSR Compatible

Works with SSR and SPA modes

Reactive

Leverage Svelte’s reactivity system

Troubleshooting

Solutions:
  • Check browser guard: if (browser)
  • Ensure script loads in onMount
  • Verify URL is correct
  • Check browser console for errors
Solutions:
  • Use browser check before accessing window
  • Load script client-side only
  • Ensure user data is fetched client-side if needed
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

Best Practices

  • 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