forrealtime

Getting Started

Install forrealtime and get a server-sent events endpoint running in minutes.

Installation

Choose your Redis client and install the matching packages.

With ioredis

bun add forrealtime ioredis zod

With Bun Redis (built-in)

bun add forrealtime zod

Server quickstart

Define a schema, create a Realtime instance, and export the handler.

import Redis from "ioredis";
import z from "zod/v4";
import { Realtime, handle } from "forrealtime";
import { createIORedisAdapter } from "forrealtime/adapters/ioredis";

const schema = {
  notification: {
    alert: z.string(),
  },
  chat: {
    message: z.object({
      text: z.string(),
      user: z.string(),
    }),
  },
};

const realtime = new Realtime({
  schema,
  redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)),
  history: {
    maxLength: 1000,
  },
});

// Next.js App Router — export as GET handler
export const GET = handle({ realtime });

Emit your first event

Once the handler is running, emit events from any server-side code:

await realtime.emit("notification.alert", "Welcome!");

await realtime.emit("chat.message", {
  text: "Hello world",
  user: "lasse",
});

React client quickstart

Wrap your app in RealtimeProvider and create a typed hook:

// realtime.ts
import { createRealtime } from "forrealtime/client";
import type { realtime } from "./server"; // type-only import

export const { useRealtime } = createRealtime<typeof realtime>();
// App.tsx
import { RealtimeProvider } from "forrealtime/client";

export function App({ children }: { children: React.ReactNode }) {
  return (
    <RealtimeProvider api={{ url: "/api/realtime" }}>
      {children}
    </RealtimeProvider>
  );
}
// Notifications.tsx
import { useState } from "react";
import { useRealtime } from "./realtime";

export function Notifications() {
  const [messages, setMessages] = useState<string[]>([]);

  const { status } = useRealtime({
    channels: ["default"],
    events: ["notification.alert"],
    onData(payload) {
      if (payload.event === "notification.alert") {
        setMessages((prev) => [...prev, payload.data]);
      }
    },
  });

  return (
    <div>
      <p>Status: {status}</p>
      <ul>
        {messages.map((m, i) => (
          <li key={i}>{m}</li>
        ))}
      </ul>
    </div>
  );
}

Svelte client quickstart

Call provideRealtime() in a parent component and create the same typed useRealtime() helper:

// realtime.ts
import { createRealtime } from "forrealtime/client/svelte";
import type { realtime } from "./server"; // type-only import

export const { useRealtime } = createRealtime<typeof realtime>();
<!-- +layout.svelte or App.svelte -->
<script lang="ts">
  import { provideRealtime } from "forrealtime/client/svelte";

  provideRealtime({
    api: { url: "/api/realtime" },
  });
</script>

<slot />
<!-- Notifications.svelte -->
<script lang="ts">
  import { useRealtime } from "./realtime";

  let messages: string[] = [];

  const { status } = useRealtime({
    channels: ["default"],
    events: ["notification.alert"],
    onData(payload) {
      if (payload.event === "notification.alert") {
        messages = [...messages, payload.data];
      }
    },
  });
</script>

<div>
  <p>Status: {$status}</p>
  <ul>
    {#each messages as message}
      <li>{message}</li>
    {/each}
  </ul>
</div>

Next steps

  • Server APIRealtime, handle, channels, and emitting events
  • React clientRealtimeProvider, createRealtime, useRealtime options
  • Svelte clientprovideRealtime, createRealtime, reactive useRealtime options
  • Adapters — ioredis, Bun.redis, and custom adapters
  • Middleware — gate or reject connections before the stream opens
  • History & reconnects — replay missed events on reconnect
  • Plugins — extend Realtime with additional functionality (e.g. Postgres sync)
  • Examples — Hono and TanStack Start integration

On this page