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 zodWith Bun Redis (built-in)
bun add forrealtime zodServer 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 API —
Realtime,handle, channels, and emitting events - React client —
RealtimeProvider,createRealtime,useRealtimeoptions - Svelte client —
provideRealtime,createRealtime, reactiveuseRealtimeoptions - 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