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

# Svelte

> Integrate Commerce Engine Checkout into Svelte 5 apps with readable stores.

Hosted Checkout exposes a readable `checkout` store and fine-grained stores for common state.

## Installation

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
npm install @commercengine/checkout
```

Choose the authentication mode first:

| Application architecture | Mode |
| - | - |
| Hosted Checkout is the only Commerce Engine integration | `managed` |
| App also uses `@commercengine/storefront` or direct session APIs | `provided` with two-way token sync |

## Checkout-only Svelte app

Initialize and destroy checkout from the root lifecycle:

```svelte src/App.svelte theme={"theme":{"light":"github-light","dark":"github-dark"}}
<script lang="ts">
  import { onMount, onDestroy } from "svelte";
  import {
    checkout,
    destroyCheckout,
    initCheckout,
  } from "@commercengine/checkout/svelte";

  onMount(() => {
    initCheckout({
      storeId: import.meta.env.VITE_STORE_ID,
      apiKey: import.meta.env.VITE_API_KEY,
      environment:
        import.meta.env.VITE_CE_ENV === "production"
          ? "production"
          : "staging",
      onComplete: ({ orderNumber }) => {
        window.location.assign(`/thank-you?order=${orderNumber}`);
      },
    });
  });

  onDestroy(() => destroyCheckout());
</script>

<button onclick={() => $checkout.openCart()} disabled={!$checkout.isReady}>
  Cart ({$checkout.cartCount})
</button>
```

## Svelte app with Storefront SDK

For a browser Svelte application using the Storefront SDK, configure SDK-to-checkout token updates inside `session`, then initialize checkout in provided mode.

```typescript src/lib/storefront.ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { getCheckout } from "@commercengine/checkout";
import {
  BrowserTokenStorage,
  Environment,
  createStorefront,
} from "@commercengine/storefront";

export const tokenStorage = new BrowserTokenStorage("brand_");

export const storefront = createStorefront({
  storeId: import.meta.env.VITE_STORE_ID,
  apiKey: import.meta.env.VITE_API_KEY,
  environment:
    import.meta.env.VITE_CE_ENV === "production"
      ? Environment.Production
      : Environment.Staging,
  session: {
    tokenStorage,
    onTokensUpdated: (accessToken, refreshToken) => {
      getCheckout().updateTokens(accessToken, refreshToken);
    },
  },
});

export const sdk = storefront.session();
```

```svelte src/App.svelte theme={"theme":{"light":"github-light","dark":"github-dark"}}
<script lang="ts">
  import { onMount, onDestroy } from "svelte";
  import {
    checkout,
    destroyCheckout,
    initCheckout,
  } from "@commercengine/checkout/svelte";
  import { sdk, tokenStorage } from "$lib/storefront";

  let active = true;

  onMount(async () => {
    try {
      const accessToken = await sdk.ensureAccessToken();
      const refreshToken = await tokenStorage.getRefreshToken();
      if (!active) return;

      initCheckout({
        storeId: import.meta.env.VITE_STORE_ID,
        apiKey: import.meta.env.VITE_API_KEY,
        environment:
          import.meta.env.VITE_CE_ENV === "production"
            ? "production"
            : "staging",
        authMode: "provided",
        accessToken: accessToken ?? undefined,
        refreshToken: refreshToken ?? undefined,
        onTokensUpdated: ({ accessToken, refreshToken }) => {
          void sdk.setTokens(accessToken, refreshToken);
        },
      });
    } catch (error) {
      console.error("Commerce Engine startup failed", error);
    }
  });

  onDestroy(() => {
    active = false;
    destroyCheckout();
  });
</script>
```

## SvelteKit

Use the first-party `@commercengine/storefront/sveltekit` wrapper when the SvelteKit application uses the Storefront SDK. It aligns browser and request-cookie sessions.

Follow [SvelteKit SDK integration](/docs/sdk/sveltekit-integration#hosted-checkout--sveltekit) for the complete provided-mode pattern.

For a checkout-only SvelteKit site, initialize managed mode inside `onMount` and destroy it in `onDestroy`:

```svelte src/routes/+layout.svelte theme={"theme":{"light":"github-light","dark":"github-dark"}}
<script lang="ts">
  import {
    PUBLIC_API_KEY,
    PUBLIC_CE_ENV,
    PUBLIC_STORE_ID,
  } from "$env/static/public";
  import { onMount, onDestroy } from "svelte";
  import {
    destroyCheckout,
    initCheckout,
  } from "@commercengine/checkout/svelte";

  onMount(() => {
    initCheckout({
      storeId: PUBLIC_STORE_ID,
      apiKey: PUBLIC_API_KEY,
      environment:
        PUBLIC_CE_ENV === "production"
          ? "production"
          : "staging",
    });
  });

  onDestroy(() => destroyCheckout());
</script>

<slot />
```

Do not initialize browser-only checkout code during module evaluation or server rendering.

## Use the store

```svelte src/lib/CartButton.svelte theme={"theme":{"light":"github-light","dark":"github-dark"}}
<script lang="ts">
  import { checkout } from "@commercengine/checkout/svelte";
</script>

<button onclick={() => $checkout.openCart()} disabled={!$checkout.isReady}>
  Cart ({$checkout.cartCount})
</button>
```

```svelte src/lib/AddToCartButton.svelte theme={"theme":{"light":"github-light","dark":"github-dark"}}
<script lang="ts">
  import { checkout } from "@commercengine/checkout/svelte";

  let { productId, variantId, hasVariants } = $props<{
    productId: string;
    variantId: string | null;
    hasVariants: boolean;
  }>();
</script>

<button
  disabled={!$checkout.isReady || (hasVariants && !variantId)}
  onclick={() => $checkout.addToCart(productId, variantId, 1)}
>
  Add to cart
</button>
```

Pass `null` for simple products; resolve a valid variant ID before enabling the button for variant products.

## Fine-grained stores

Use the individual stores when a component only needs one value:

```svelte theme={"theme":{"light":"github-light","dark":"github-dark"}}
<script lang="ts">
  import { cartCount } from "@commercengine/checkout/svelte";
</script>

<span aria-live="polite">{$cartCount}</span>
```

Available fine-grained stores include `cartCount`, `cartTotal`, `isReady`, and `isOpen`.

## Store API

| Property | Type | Description |
| - | - | - |
| `isReady` | `boolean` | iframe ready state |
| `isOpen` | `boolean` | overlay visibility |
| `cartCount` | `number` | item count |
| `cartTotal` | `number` | reported cart total |
| `cartCurrency` | `string` | currency code |
| `isLoggedIn` | `boolean` | login state |
| `user` | `UserInfo \| null` | current user |
| `openCart()` | function | open cart drawer |
| `openCheckout()` | function | open checkout directly |
| `close()` | function | close overlay |
| `addToCart(productId, variantId, quantity?)` | function | add item |
| `updateTokens(accessToken, refreshToken?)` | function | update provided-mode tokens |

## Production checklist

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
[ ] browser initialization happens in onMount
[ ] cleanup happens in onDestroy
[ ] async initialization cannot recreate checkout after cleanup
[ ] SvelteKit wrapper used when Storefront SDK is present
[ ] provided mode and two-way token sync configured
[ ] controls disabled until checkout is ready
[ ] completion, error, and session-error states handled
```

<Card title="SvelteKit production starters" icon="github" href="https://github.com/tark-ai/ce-starter-projects">
  Review native SvelteKit storefront implementations for load boundaries, prerendering, session bootstrap, search races, SEO, and deployment patterns.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.