ScaleBun
Skip to article

Svelte & SvelteKit

webDeveloper

Wire ScaleBun into SvelteKit — init from the root layout, route patterns from afterNavigate, and error capture from the client and server handleError hooks.

Updated Reviewed

Install#

Terminal
npm i @scalebun/web @scalebun/web-svelte

Peer dependency: svelte >=4. The adapter imports nothing from svelte itself — these are plain functions the framework hooks call.

Initialize and track routes#

src/routes/+layout.svelteSVELTE
<script>  import { onMount } from 'svelte';  import { afterNavigate } from '$app/navigation';  import { setupScaleBun } from '@scalebun/web-svelte';
  const scalebun = setupScaleBun({    clientKey: 'skb_live_ck_…',    apiBaseUrl: 'https://api.scalebun.com/api/v1',  });
  onMount(scalebun.start);  afterNavigate(scalebun.navigated);</script>
<slot />

setupScaleBun returns { start, navigated, inApp, sdk } and takes inApp (default true) and inAppTheme alongside the config.

The granular exports (initScaleBun, trackNavigation, createInApp) all still work if you prefer to wire them individually.

Errors#

Svelte has no global render-error primitive, so SvelteKit's handleError hooks are the integration point. Wire both: the client hook catches errors in the browser, the server hook catches them during SSR and in endpoints.

src/hooks.client.tsTypeScript
import { reportError } from '@scalebun/web-svelte';
export const handleError = ({ error }) => {  reportError(error);  return { message: 'Something broke.' };};
src/hooks.server.tsTypeScript
import { reportError } from '@scalebun/web-svelte';
export const handleError = ({ error }) => {  reportError(error);  return { message: 'Something broke.' };};

reportError never throws, so it cannot interfere with the message you return to the user.

Reading the facade#

TypeScript
import ScaleBun from '@scalebun/web-svelte';
ScaleBun.track('cart_viewed', { items: 3 });

Feature flags#

SVELTE
<script>  import { onDestroy } from 'svelte';  import ScaleBun from '@scalebun/web-svelte';
  let cta = ScaleBun.flags.variation('checkout-cta', 'control');  const stop = ScaleBun.flags.onChange(() => {    cta = ScaleBun.flags.variation('checkout-cta', 'control');  });  onDestroy(stop);</script>

Coachmarks#

SVELTE
<script>  import { coachmarks, scalebunAnchor } from '@scalebun/web-svelte';  const coach = coachmarks();</script>
<button use:scalebunAnchor={'checkout'}>Checkout</button>

The action is reactive — pass a new name and the anchor updates; the attribute is removed on unmount.

In-app messages#

SVELTE
<script>  import { createInApp, inAppSlot } from '@scalebun/web-svelte';  const client = createInApp('auto');</script>
<div use:inAppSlot={{ client, name: 'empty-state' }} />

Waiting for the SDK#

initScaleBun runs in onMount, and child components mount before their parents' onMount completes — so await whenReady() before reaching for a feature controller, or you will hold a no-op object.

SVELTE
<script>  import { onMount } from 'svelte';  import ScaleBun from '@scalebun/web-svelte';
  onMount(async () => {    await ScaleBun.whenReady();    ScaleBun.inbox().mount({ trigger: el });  });</script>

Next#

Svelte & SvelteKit · Integrations · Web SDK · ScaleBun