svelte-effect-runtime
Reference

Client Runtime

Client Runtime

Client runtime APIs used by <script effect> components and by the client-side remote adapters.

import { ClientRuntime } from "svelte-effect-runtime";

ClientRuntime.make(...) is the only symbol most apps need. The get_effect_runtime_or_throw, run_component_effect, and run_inline_effect helpers are emitted by the preprocessor; they are exported for completeness but are not intended for hand-written imports.

ClientRuntime

interface ClientRuntimeSeed {
  pipe(): Layer.Layer<never>;
  pipe<const Ops extends readonly RuntimeOperator[]>(
    ...ops: Ops
  ): FinalRuntimeLayer<Ops>;

  make(): ManagedRuntime.ManagedRuntime<never, never>;
  make<const Ops extends readonly RuntimeOperator[]>(
    ...ops: Ops
  ): ManagedRuntimeFromOps<Ops>;
}
interface EffectRuntime<R = unknown> {
  runCallback<A, E, R2>(
    effect: Effect<A, E, R2>,
    options?: { onExit?: (exit: Exit<A, E>) => void }
  ): () => void;
  runPromise<A, E, R2>(effect: Effect<A, E, R2>): Promise<A>;
  dispose(): Promise<void>;
}

Default runtime

ClientRuntime.make(...) is optional. When no runtime has been registered, the first <script effect> component to mount creates a default runtime with an empty layer automatically. That's enough for effects that don't depend on any custom services.

<script lang="ts" effect>
  import { get_version } from "$lib/version.remote";

  let version = $state("");
  version = yield* get_version();
</script>

No hooks.client.ts is required for this case.

Registering services

Call ClientRuntime.make(...) from src/hooks.client.ts when your effects need Context services that should be available everywhere:

// src/hooks.client.ts
import { Layer } from "effect";
import { ClientRuntime } from "svelte-effect-runtime";
import { MyApi } from "$lib/my-api";

export const init = () => {
  ClientRuntime.make(Layer.provide(MyApi.Live));
};

Each argument is a runtime operator — typically Layer.provide(...) applied to the layer you want to add. Calling ClientRuntime.make(...) again disposes the previous runtime and installs the new one.

Internal helpers

These are emitted by the preprocessor; they exist on the public surface only so generated code can import them.

function get_effect_runtime_or_throw<
  T extends EffectRuntime = EffectRuntime<never>
>(): T;

function run_component_effect<A, E, R>(
  runtime: EffectRuntime<R>,
  program: Effect<A, E, R>
): () => void;

function run_inline_effect<A, E, R>(
  runtime: EffectRuntime<R>,
  program: Effect<A, E, R>
): Promise<A>;

get_effect_runtime_or_throw() checks Svelte context first, falls back to the module-scoped runtime registered by ClientRuntime.make(...), and lazily creates a default if neither is set.

On this page