npm package: @replanejs/svelte
Description: Svelte SDK for Replane - feature flags and remote configuration
Latest version: 1.1.1

<h1 align="center">Replane Svelte SDK</h1>
<p align="center">Dynamic configuration for Svelte and SvelteKit applications.</p>

<p align="center">
  <a href="https://cloud.replane.dev"><img src="https://img.shields.io/badge/Try-Replane%20Cloud-blue" alt="Replane Cloud"></a>
  <a href="https://www.npmjs.com/package/@replanejs/svelte"><img src="https://img.shields.io/npm/v/@replanejs/svelte" alt="npm"></a>
  <a href="https://github.com/replane-dev/replane-javascript/blob/main/LICENSE"><img src="https://img.shields.io/github/license/replane-dev/replane-javascript" alt="License"></a>
  <a href="https://github.com/orgs/replane-dev/discussions"><img src="https://img.shields.io/badge/discussions-join-blue?logo=github" alt="Community"></a>
</p>

<picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/replane-dev/replane/main/public/replane-window-screenshot-dark-v1.png">
    <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/replane-dev/replane/main/public/replane-window-screenshot-light-with-border-v2.jpg">
    <img alt="Replane Screenshot" src="https://raw.githubusercontent.com/replane-dev/replane/main/public/replane-window-screenshot-light-with-border-v2.jpg">
</picture>

[Replane](https://github.com/replane-dev/replane) is a dynamic configuration manager that lets you tweak your software without running scripts or building your own admin panel. Store feature flags, rate limits, UI text, log level, rollout percentage, and more. Delegate editing to teammates and share config across services. No redeploys needed.

## Why Dynamic Configuration?

- **Feature flags** – toggle features, run A/B tests, roll out to user segments
- **Operational tuning** – adjust limits, TTLs, and timeouts without redeploying
- **Per-environment settings** – different values for production, staging, dev
- **Incident response** – instantly revert to a known-good version
- **Cross-service configuration** – share settings with realtime sync
- **Non-engineer access** – safe editing with schema validation

## Installation

```bash
npm install @replanejs/svelte
```

## Quick Start

```svelte
<script>
  import { ReplaneContext, config } from '@replanejs/svelte';
  import { Replane } from '@replanejs/svelte';

  const replane = new Replane();
  await replane.connect({
    baseUrl: 'https://cloud.replane.dev', // or your self-hosted URL
    sdkKey: 'your-sdk-key',
  });
</script>

<ReplaneContext client={replane}>
  <MyComponent />
</ReplaneContext>
```

```svelte
<!-- MyComponent.svelte -->
<script>
  import { config } from '@replanejs/svelte';

  const feature = config<boolean>('feature-flag-name');
</script>

{#if $feature}
  <p>Feature is enabled!</p>
{:else}
  <p>Feature is disabled</p>
{/if}
```

## Provider Props

| Prop         | Type                      | Required | Description                                                  |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------ |
| `connection` | `ConnectOptions \| null`  | Yes      | Connection options (see below), or `null` to skip connection |
| `defaults`   | `Record<string, unknown>` | No       | Default values if server is unavailable                      |
| `context`    | `Record<string, unknown>` | No       | Default context for override evaluations                     |
| `snapshot`   | `ReplaneSnapshot`         | No       | Snapshot for SSR hydration                                   |
| `logger`     | `ReplaneLogger`           | No       | Custom logger (default: console)                             |
| `loader`     | `Snippet`                 | No       | Snippet to show while loading                                |
| `async`      | `boolean`                 | No       | Connect asynchronously (renders immediately with defaults)   |

## Connection Options

The `connection` prop accepts the following options:

| Option                | Type           | Required | Description                               |
| --------------------- | -------------- | -------- | ----------------------------------------- |
| `baseUrl`             | `string`       | Yes      | Replane server URL                        |
| `sdkKey`              | `string`       | Yes      | SDK key for authentication                |
| `connectTimeoutMs`    | `number`       | No       | SDK connection timeout (default: 5000)    |
| `requestTimeoutMs`    | `number`       | No       | Timeout for SSE requests (default: 2000)  |
| `retryDelayMs`        | `number`       | No       | Base delay between retries (default: 200) |
| `inactivityTimeoutMs` | `number`       | No       | SSE inactivity timeout (default: 30000)   |
| `fetchFn`             | `typeof fetch` | No       | Custom fetch implementation               |

See [`@replanejs/sdk` documentation](https://github.com/replane-dev/replane-javascript/tree/main/packages/sdk#api) for more details.

## API

### config

Create a reactive store for a specific config value. Similar to `readable()` or `derived()`.

```svelte
<script>
  import { config } from '@replanejs/svelte';

  // Returns a Svelte readable store
  const featureEnabled = config<boolean>('featureEnabled');

  // With evaluation context
  const greeting = config<string>('greeting', {
    context: { userId: '123', isPremium: true }
  });
</script>

{#if $featureEnabled}
  <p>{$greeting}</p>
{/if}
```

### getReplane

Get direct access to the Replane client from context.

```svelte
<script>
  import { getReplane } from '@replanejs/svelte';

  const replane = getReplane();

  function handleClick() {
    const value = replane.get('some-config');
    console.log(value);
  }
</script>

<button onclick={handleClick}>Get Config</button>
```

### configFrom

Create a reactive store from a client directly (without context). Type-safe with full autocomplete for config names.

```svelte
<script>
  import { configFrom } from '@replanejs/svelte';
  import { replane } from './replane-client';

  // Config name is validated against TConfigs, return type is inferred
  const featureEnabled = configFrom(replane, 'featureEnabled');
</script>

{#if $featureEnabled}
  <p>Feature is enabled!</p>
{/if}
```

### ReplaneContext

Context component that makes the Replane client available to your component tree.

Can be used in several ways:

**1. With a pre-created client:**

```svelte
<script>
  import { ReplaneContext, Replane } from '@replanejs/svelte';

  const replane = new Replane();
  await replane.connect({
    baseUrl: 'https://cloud.replane.dev', // or your self-hosted URL
    sdkKey: 'your-sdk-key',
  });
</script>

<ReplaneContext client={replane}>
  <App />
</ReplaneContext>
```

**2. With connection (client managed internally):**

```svelte
<script>
  import { ReplaneContext } from '@replanejs/svelte';

  const connection = {
    baseUrl: 'https://your-replane-server.com',
    sdkKey: 'your-sdk-key',
  };
</script>

<svelte:boundary onerror={(e) => console.error(e)}>
  <ReplaneContext {connection}>
    <App />

    {#snippet loader()}
      <p>Loading...</p>
    {/snippet}
  </ReplaneContext>

  {#snippet failed(error)}
    <p>Error: {error.message}</p>
  {/snippet}
</svelte:boundary>
```

**3. With async mode:**

Connect in the background while rendering immediately with defaults:

```svelte
<script>
  import { ReplaneContext } from '@replanejs/svelte';

  const connection = {
    baseUrl: 'https://your-replane-server.com',
    sdkKey: 'your-sdk-key',
  };

  const defaults = {
    featureEnabled: false,
  };
</script>

<ReplaneContext {connection} {defaults} async>
  <App />
</ReplaneContext>
```

**4. With a snapshot (for SSR/hydration):**

```svelte
<script>
  import { ReplaneContext } from '@replanejs/svelte';

  let { data, children } = $props();

  const connection = {
    baseUrl: import.meta.env.VITE_REPLANE_BASE_URL,
    sdkKey: import.meta.env.VITE_REPLANE_SDK_KEY,
  };
</script>

<ReplaneContext {connection} snapshot={data.replaneSnapshot}>
  {@render children()}
</ReplaneContext>
```

## Typed Stores

For better type safety, create typed versions of the store functions:

```ts
// $lib/replane/index.ts
import { createTypedConfig, createTypedReplane } from "@replanejs/svelte";

interface AppConfigs {
  theme: { darkMode: boolean; primaryColor: string };
  features: { betaEnabled: boolean };
}

export const appConfig = createTypedConfig<AppConfigs>();
export const getAppReplane = createTypedReplane<AppConfigs>();
```

```svelte
<script lang="ts">
  import { appConfig, getAppReplane } from '$lib/replane';

  // Config names autocomplete, values are fully typed
  const theme = appConfig("theme");
  // $theme is { darkMode: boolean; primaryColor: string }

  // Direct client access
  const replane = getAppReplane();
  const features = replane.get("features"); // fully typed
</script>

<div style:color={$theme.primaryColor}>
  {$theme.darkMode ? "Dark" : "Light"}
</div>
```

## SSR / SvelteKit

For server-side rendering, fetch configs on the server and restore on the client:

```ts
// src/routes/+layout.server.ts
import { getReplaneSnapshot } from "@replanejs/svelte";

export async function load() {
  const snapshot = await getReplaneSnapshot({
    connection: {
      baseUrl: import.meta.env.REPLANE_BASE_URL,
      sdkKey: import.meta.env.REPLANE_SDK_KEY,
    },
  });

  return { replaneSnapshot: snapshot };
}
```

```svelte
<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { ReplaneContext } from '@replanejs/svelte';

  let { data, children } = $props();

  const connection = {
    baseUrl: import.meta.env.VITE_REPLANE_BASE_URL,
    sdkKey: import.meta.env.VITE_REPLANE_SDK_KEY,
  };
</script>

<ReplaneContext {connection} snapshot={data.replaneSnapshot}>
  {@render children()}
</ReplaneContext>
```

## Realtime Updates

All stores automatically subscribe to realtime updates via SSE. When a config changes on the server, the store updates automatically.

```svelte
<script>
  import { config } from '@replanejs/svelte';

  const maintenanceMode = config<boolean>('maintenance-mode');
</script>

{#if $maintenanceMode}
  <MaintenanceBanner />
{/if}
```

## Community

Have questions or want to discuss Replane? Join the conversation in [GitHub Discussions](https://github.com/orgs/replane-dev/discussions).

## License

MIT