/Docs

Vite + Svelte 5 integration

This guide assumes a Vite project using Svelte 5 with runes enabled. By the end you'll have reactive flag evaluation and event tracking wired into your app using @avsbhq/browser and @avsbhq/svelte.

1

Install

bash
1npm install @avsbhq/browser@^1 @avsbhq/svelte@^1
2

Obtain your SDK key

Open Settings > Environments in your A vs B project and copy the SDK key. Store it in your Vite environment file:

.env
bash
1VITE_AVSB_SDK_KEY=sdk_production_xxxxxxxxxxxxxxxx
3

Mount AvsbProvider in App.svelte

Wrap your root component with AvsbProvider. It accepts the same sdkKey and context props as the other framework adapters.

src/App.svelte
svelte
1<script lang="ts">
2 import AvsbProvider from '@avsbhq/svelte/AvsbProvider.svelte'
3 import Home from './Home.svelte'
4</script>
5
6<AvsbProvider
7 sdkKey={import.meta.env.VITE_AVSB_SDK_KEY}
8 context={{ kind: 'user', key: 'anonymous' }}
9>
10 <Home />
11</AvsbProvider>
Info
The .svelte SFC ships as raw source via thesvelte field in package.json — your Vite Svelte plugin compiles it. For non-SFC contexts (e.g. a shared util initialising the client imperatively) import thecreateAvsbContext() factory from @avsbhq/svelte instead.
4

Read a flag

Use the flag store from @avsbhq/svelte. It returns a Readable<Flag<T>>that integrates with Svelte's reactive $ syntax.

src/components/HeroBanner.svelte
svelte
1<script lang="ts">
2 import { flag } from '@avsbhq/svelte'
3
4 const heroVariant = flag('homepage-hero', 'control')
5</script>
6
7{#if $heroVariant.value === 'variant-a'}
8 <HeroBannerVariantA />
9{:else if $heroVariant.value === 'variant-b'}
10 <HeroBannerVariantB />
11{:else}
12 <HeroBannerControl />
13{/if}
Tip
The flag store is a Svelte Readable. It updates whenever the flag value changes — for example after a datafile polling cycle or after identify is called.
5

Track an event

src/components/PurchaseButton.svelte
svelte
1<script lang="ts">
2 import { getContext } from 'svelte'
3 import type { AvsbClient } from '@avsbhq/browser'
4
5 const client = getContext<AvsbClient>('avsb-client')
6
7 function handlePurchase() {
8 client.track('purchase', { value: 49.99, properties: { source: 'cart' } })
9 }
10</script>
11
12<button type="button" on:click={handlePurchase}>Complete purchase</button>

Alternatively, get a stable track function via getTrack():

svelte
1<script lang="ts">
2 import { getTrack } from '@avsbhq/svelte'
3
4 const track = getTrack()
5</script>
6
7<button type="button" on:click={() => track('purchase', { value: 49.99 })}>
8 Complete purchase
9</button>
6

Identify a user

Access the avsbClient context to call identify after login:

svelte
1<script lang="ts">
2 import { getContext } from 'svelte'
3 import type { AvsbClient } from '@avsbhq/browser'
4
5 const client = getContext<AvsbClient>('avsb-client')
6
7 function onLogin(userId: string, plan: string) {
8 client.identify({ kind: 'user', key: userId, plan })
9 }
10</script>

SvelteKit support

For SvelteKit projects, @avsbhq/svelte ships a sveltekit/hooks.ts helper that bootstraps the datafile server-side in hooks.server.ts:

src/hooks.server.ts
ts
1import { withAvsbHooks } from '@avsbhq/svelte/sveltekit'
2import type { Handle } from '@sveltejs/kit'
3
4const baseHandle: Handle = async ({ event, resolve }) => resolve(event)
5
6export const handle = withAvsbHooks(baseHandle, {
7 sdkKey: process.env.AVSB_SDK_KEY!,
8 contextFrom: (event) => ({
9 kind: 'user',
10 key: event.cookies.get('uid') ?? 'anon',
11 }),
12})

Client components then read the bootstrapped datafile from $page.data.avsbBootstrap and pass it to AvsbProvider.

Graceful shutdown

AvsbProvider calls client.close()on the Svelte component's onDestroy lifecycle hook. In a production SPA the provider is never destroyed, but the SDK also handles cleanup via visibilitychange events.

Testing

ts
1import { createMockClient, TestData } from '@avsbhq/test'
2import { render } from '@testing-library/svelte'
3import HeroBanner from './HeroBanner.svelte'
4
5const td = TestData.flag('homepage-hero').stringFlag().fallthroughVariation('variant-a')
6const client = createMockClient({ flags: [td.build()] })
7
8render(HeroBanner, { context: new Map([['avsb-client', client]]) })

What's next