Skip to content

Streaming

aibind's streaming API sends a prompt to your server and streams back text in real-time.

How It Works

  1. Client sends a POST to your endpoint with { prompt, model?, system? }
  2. Server resolves the model and calls streamText() from the AI SDK
  3. Response streams back as raw text chunks
  4. Client accumulates text and updates reactive state

Client API

Each framework has its own reactive wrapper, but the returned API surface is the same.

SvelteKit

svelte
<script lang="ts">
  import { Stream } from '@aibind/sveltekit';

  const stream = new Stream({
    model: 'fast',
    system: 'You are a helpful assistant.',
  });
</script>

<button onclick={() => stream.send('Hello!')}>Send</button>
<p>{stream.text}</p>
<p>Loading: {stream.loading}, Done: {stream.done}</p>

Next.js / React

tsx
"use client";

import { useStream } from "@aibind/nextjs";

function Chat() {
  const { text, loading, send, abort, retry } = useStream({
    model: "fast",
    system: "You are a helpful assistant.",
  });

  return (
    <div>
      <button onClick={() => send("Hello!")}>Send</button>
      <p>{text}</p>
    </div>
  );
}

Nuxt / Vue

vue
<script setup lang="ts">
import { useStream } from "@aibind/nuxt";

const { text, loading, send, abort, retry } = useStream({
  model: "fast",
  system: "You are a helpful assistant.",
});
</script>

<template>
  <button @click="send('Hello!')">Send</button>
  <p>{{ text }}</p>
  <p>Loading: {{ loading }}, Done: {{ done }}</p>
</template>

SolidStart

tsx
import { useStream } from "@aibind/solidstart";

function Chat() {
  const { text, loading, send, abort, retry } = useStream({
    model: "fast",
    system: "You are a helpful assistant.",
  });

  return (
    <div>
      <button onClick={() => send("Hello!")}>Send</button>
      <p>{text()}</p>
      <p>Loading: {loading()}, Done: {done()}</p>
    </div>
  );
}

TanStack Start

tsx
import { useStream } from "@aibind/tanstack-start";

function Chat() {
  const { text, loading, send, abort, retry } = useStream({
    model: "fast",
    system: "You are a helpful assistant.",
  });

  return (
    <div>
      <button onClick={() => send("Hello!")}>Send</button>
      <p>{text}</p>
    </div>
  );
}

Returned State

PropertyTypeDescription
textstringAccumulated streamed text
loadingbooleanWhether a stream is in progress
donebooleanWhether the stream finished
errorError | nullAny error that occurred
statusStreamStatus'idle' | 'streaming' | 'stopped' | 'resuming'
streamIdstring | nullID for durable stream operations
canResumebooleanWhether the stream supports resume

Methods

MethodDescription
send(prompt, opts?)Start streaming with the given prompt
abort()Cancel the current stream
retry()Re-send the last prompt
stop()Stop and save stream for later resume
resume()Resume a stopped stream

Options

OptionTypeDescription
modelstringNamed model key (from defineModels)
systemstringSystem prompt
endpointstringCustom endpoint (fullstack packages default to /__aibind__/stream)
fetchtypeof fetchCustom fetch function
onFinish(text: string) => voidCalled when stream completes
onError(error: Error) => voidCalled on error

Reactivity by Framework

The API is identical — only the access pattern differs:

FrameworkAccess patternExample
SvelteDirect propertystream.text
ReactDirect valuetext (from hook)
Vue.valuetext.value
SolidFunction calltext()

Server Handler

The server handler is created once and handles all routing:

ts
import { createStreamHandler } from "@aibind/sveltekit/server";
import { models } from "./models.server";

export const handle = createStreamHandler({ models });

It automatically routes /__aibind__/stream and /__aibind__/structured requests.

Released under the MIT License.