### Minimal Bun.serve Setup with forrealtime Source: https://forrealtime.lassejlv.dk/docs/examples/bun-serve This example demonstrates a minimal setup using forrealtime with Bun.serve. It includes schema definition, Redis adapter setup, and basic server configuration for handling realtime events and emitting messages. Dependencies include 'zod/v4' and 'forrealtime'. ```typescript import z from "zod/v4"; import { Realtime, handle } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; import index from "./index.html"; const realtime = new Realtime({ schema: { notification: { alert: z.string(), }, chat: { message: z.object({ text: z.string(), user: z.string() }), }, }, redis: createBunRedisAdapter(Bun.redis), history: { maxLength: 500 }, }); const realtimeHandler = handle({ realtime }); Bun.serve({ routes: { "/": index, "/api/realtime": { GET: realtimeHandler, }, "/api/emit": { POST: async (req) => { const body = await req.json(); await realtime.emit("chat.message", body); return new Response("ok"); }, }, }, development: { hmr: true }, }); ``` -------------------------------- ### Implement forrealtime in TanStack Start Source: https://forrealtime.lassejlv.dk/llms-full.txt A comprehensive guide for TanStack Start, covering server-side route setup, client-side provider injection, and React hook usage for real-time event handling. ```typescript // src/routes/api.realtime.ts import { Realtime, handle } from "forrealtime"; import { createIORedisAdapter } from "forrealtime/adapters/ioredis"; import Redis from "ioredis"; import { z } from "zod/v4"; export const realtime = new Realtime({ schema: { notification: { alert: z.string() } }, redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)), }); export const Route = createFileRoute("/api/realtime")({ server: { handlers: { GET: () => handle({ realtime })(getRequest()) }, }, }); ``` ```tsx // src/routes/__root.tsx import { RealtimeProvider } from "forrealtime/client"; function RootDocument({ children }) { return ( {children} ); } ``` ```tsx // src/routes/index.tsx import { createRealtime } from "forrealtime/client"; import type { realtime } from "./api.realtime"; const { useRealtime } = createRealtime(); function RouteComponent() { const { status } = useRealtime({ channels: ["default"], events: ["notification.alert"], onData(payload) { /* handle data */ } }); return
Status: {status}
; } ``` -------------------------------- ### Install forrealtime and ioredis dependencies Source: https://forrealtime.lassejlv.dk/docs/adapters/ioredis Command to install the necessary packages for using forrealtime with the ioredis client using the Bun package manager. ```bash bun add forrealtime ioredis zod ``` -------------------------------- ### Initialize forrealtime with ioredis adapter Source: https://forrealtime.lassejlv.dk/docs/adapters/ioredis Demonstrates how to instantiate the Realtime client by passing a configured ioredis adapter. This setup supports standalone, Sentinel, and Cluster Redis configurations. ```javascript import Redis from "ioredis"; import { Realtime } from "forrealtime"; import { createIORedisAdapter } from "forrealtime/adapters/ioredis"; const realtime = new Realtime({ schema, redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)), }); ``` -------------------------------- ### Built-in Adapters Source: https://forrealtime.lassejlv.dk/llms-full.txt Examples of initializing forrealtime with the official Bun and ioredis adapters. ```APIDOC ## Built-in Adapters ### Bun Redis ```ts import { Realtime } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; const realtime = new Realtime({ schema, redis: createBunRedisAdapter(Bun.redis), }); ``` ### ioredis ```ts import Redis from "ioredis"; import { Realtime } from "forrealtime"; import { createIORedisAdapter } from "forrealtime/adapters/ioredis"; const realtime = new Realtime({ schema, redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)), }); ``` ``` -------------------------------- ### Hono Web Framework Integration with forrealtime Source: https://forrealtime.lassejlv.dk/docs/examples/hono This snippet shows how to set up and use forrealtime with the Hono web framework. It includes installing necessary packages, defining a schema, and creating a Redis adapter for Bun. The `handle` function from forrealtime is used to create an API endpoint for real-time communication. ```bash bun add forrealtime hono zod ``` ```typescript import { Hono } from "hono"; import z from "zod/v4"; import { Realtime, handle } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; const app = new Hono(); const realtime = new Realtime({ schema: { notification: { alert: z.string(), }, }, redis: createBunRedisAdapter(Bun.redis), }); const realtimeHandler = handle({ realtime, }); app.get("/api/realtime", (c) => realtimeHandler(c.req.raw)); export default app; ``` -------------------------------- ### Configure Server Route with forrealtime and TanStack Start Source: https://forrealtime.lassejlv.dk/docs/examples/tanstack-start Sets up the server route for forrealtime using TanStack Start's createFileRoute. It initializes forrealtime with a Redis adapter and handles incoming requests. ```typescript // src/routes/api.realtime.ts import { createFileRoute } from "@tanstack/react-router"; import { getRequest } from "@tanstack/react-start/server"; import Redis from "ioredis"; import { z } from "zod/v4"; import { Realtime, handle } from "forrealtime"; import { createIORedisAdapter } from "forrealtime/adapters/ioredis"; export const realtime = new Realtime({ schema: { notification: { alert: z.string(), }, }, redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)), }); export const Route = createFileRoute("/api/realtime")({ server: { handlers: { GET: () => { const request = getRequest(); return handle({ realtime })(request); }, }, }, }); ``` -------------------------------- ### Server Quickstart with ioredis Source: https://forrealtime.lassejlv.dk/llms-full.txt Sets up a ForRealtime server handler using ioredis. It defines a Zod schema for data validation, creates a Realtime instance with an ioredis adapter, and exports the handler for use with frameworks like Next.js. ```typescript 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 }); ``` -------------------------------- ### React Client Setup with RealtimeProvider and useRealtime Source: https://forrealtime.lassejlv.dk/llms-full.txt This snippet shows the initial setup for the React client. It involves wrapping the application with RealtimeProvider and creating a typed useRealtime hook using createRealtime. RealtimeProvider manages the EventSource connection, while useRealtime handles event subscriptions. ```typescript import { RealtimeProvider, createRealtime } from "forrealtime/client"; ``` -------------------------------- ### Initialize Realtime Server Instance Source: https://forrealtime.lassejlv.dk/docs/server/realtime Demonstrates how to instantiate the Realtime class by providing a Zod schema, a Redis adapter, and history configuration. This setup is required to manage event streams and persistence. ```typescript import { Realtime } from "forrealtime"; const realtime = new Realtime({ schema, redis, history: { maxLength: 1000, }, }); ``` -------------------------------- ### Install forrealtime and Zod with Bun Source: https://forrealtime.lassejlv.dk/docs/adapters/bun Installs the necessary packages for using forrealtime with Zod for schema validation. This command is executed in a Bun environment. ```bash bun add forrealtime zod ``` -------------------------------- ### Initialize Realtime Client in React Source: https://forrealtime.lassejlv.dk/docs/react-client Demonstrates how to import and initialize the RealtimeProvider and createRealtime factory. This setup enables shared EventSource connections and typed event subscriptions across the component tree. ```typescript import { RealtimeProvider, createRealtime } from "forrealtime/client"; ``` -------------------------------- ### Emit forrealtime Event from Server Source: https://forrealtime.lassejlv.dk/docs/examples/tanstack-start Shows how to emit a forrealtime event from the server-side after the `realtime` instance has been initialized. ```typescript await realtime.emit("notification.alert", "TanStack Start is live"); ``` -------------------------------- ### Add forrealtime Provider at Root with TanStack Start Source: https://forrealtime.lassejlv.dk/docs/examples/tanstack-start Integrates the RealtimeProvider into the root of the TanStack Start application. This makes the forrealtime client available throughout the application. ```typescript // src/routes/__root.tsx import { HeadContent, Scripts, createRootRouteWithContext } from "@tanstack/react-router"; import type { QueryClient } from "@tanstack/react-query"; import { RealtimeProvider } from "forrealtime/client"; interface MyRouterContext { queryClient: QueryClient; } export const Route = createRootRouteWithContext()({ shellComponent: RootDocument, }); function RootDocument({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` -------------------------------- ### Use forrealtime Hook in a TanStack Start Route Source: https://forrealtime.lassejlv.dk/docs/examples/tanstack-start Demonstrates how to use the `useRealtime` hook within a TanStack Start route component to subscribe to events and receive real-time data. ```typescript // src/routes/index.tsx import { createFileRoute } from "@tanstack/react-router"; import { useState } from "react"; import { createRealtime } from "forrealtime/client"; import type { realtime } from "./api.realtime"; // type-only import const { useRealtime } = createRealtime(); export const Route = createFileRoute("/")({ component: RouteComponent, }); function RouteComponent() { const [messages, setMessages] = useState([]); const { status } = useRealtime({ channels: ["default"], events: ["notification.alert"], onData(payload) { if (payload.event === "notification.alert") { setMessages((prev) => [...prev, `alert: ${payload.data}`]); } }, }); return (

Realtime Status: {status}

Messages:

{JSON.stringify(messages, null, 2)}
); } ``` -------------------------------- ### Middleware for Channel-Specific Authorization (TypeScript) Source: https://forrealtime.lassejlv.dk/docs/middleware Illustrates how to use middleware to enforce per-channel authorization. This example checks the 'Authorization' header and also restricts access to channels prefixed with 'admin' if the user is not authorized. ```typescript const auth = (ctx: MiddlewareContext) => { const authorized = ctx.request.headers.get("authorization") === "Bearer secret"; if (!authorized) { return new Response("Unauthorized", { status: 401 }); } if (ctx.channels.includes("admin")) { return new Response("Forbidden", { status: 403 }); } }; ``` -------------------------------- ### React Client Setup with ForRealtime Source: https://forrealtime.lassejlv.dk/llms-full.txt Provides the necessary code to set up the ForRealtime client in a React application. It includes creating a typed hook using `createRealtime` and wrapping the application with `RealtimeProvider` to establish the connection. ```typescript // realtime.ts import { createRealtime } from "forrealtime/client"; import type { realtime } from "./server"; // type-only import export const { useRealtime } = createRealtime(); ``` ```typescript // App.tsx import { RealtimeProvider } from "forrealtime/client"; export function App({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` -------------------------------- ### Node-Redis Adapter Implementation for Realtime Source: https://forrealtime.lassejlv.dk/llms-full.txt Provides an example implementation of the RedisAdapter interface using the 'node-redis' client. This adapter handles stream operations and JSON serialization/deserialization for payloads. ```typescript import { createClient } from "redis"; // node-redis import type { RedisAdapter } from "forrealtime"; function createNodeRedisAdapter(client: ReturnType): RedisAdapter { return { async xadd(channel, payload, options) { const id = await client.xAdd( channel, "*", Object.fromEntries( Object.entries(payload).map(([k, v]) => [k, JSON.stringify(v)]) ), options?.maxLen ? { TRIM: { strategy: "MAXLEN", threshold: options.maxLen } } : undefined, ); return id; }, async xrange(channel, args) { const entries = await client.xRange( channel, args?.start ?? "-", args?.end ?? "+", args?.count ? { COUNT: args.count } : undefined, ); return entries.map((e) => ({ id: e.id, payload: Object.fromEntries( Object.entries(e.message).map(([k, v]) => [k, JSON.parse(v as string)]) ), })); }, async xread({ channels, cursors, blockMs, count, signal }) { // implementation omitted for brevity return []; }, async getLatestCursor(channel) { const entries = await client.xRevRange(channel, "+", "-", { COUNT: 1 }); return entries[0]?.id ?? null; }, }; } ``` -------------------------------- ### Cookie-Based Authentication Middleware (TypeScript) Source: https://forrealtime.lassejlv.dk/docs/middleware Provides an example of middleware that authenticates users based on a 'session' cookie. It parses the cookie header and validates the session using an assumed isValidSession function. ```typescript import { handle } from "forrealtime"; import type { MiddlewareContext } from "forrealtime"; const cookieAuth = (ctx: MiddlewareContext) => { const cookie = ctx.request.headers.get("cookie") ?? ""; const session = parseCookies(cookie).session; if (!session || !isValidSession(session)) { return new Response("Unauthorized", { status: 401 }); } }; export const GET = handle({ realtime, middleware: cookieAuth }); ``` -------------------------------- ### Server-Rendered History Example (Next.js) Source: https://forrealtime.lassejlv.dk/docs/history Demonstrates fetching the last 20 messages for a given room ID on the server and passing them as initial props to a client component. This ensures the user sees recent messages immediately upon page load, even before the realtime connection is fully established. ```typescript // page.tsx (Next.js App Router) import { realtime } from "@/lib/realtime"; import { ChatRoom } from "./ChatRoom"; export default async function Page({ params }: { params: { roomId: string } }) { const room = realtime.channel(`room:${params.roomId}`); const history = await room.history({ limit: 20 }); return ; } ``` -------------------------------- ### Configure Bun.serve with forrealtime Source: https://forrealtime.lassejlv.dk/llms-full.txt Demonstrates how to integrate forrealtime into a native Bun server. It includes schema definition, Redis adapter configuration, and route handling for API endpoints. ```typescript import z from "zod/v4"; import { Realtime, handle } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; import index from "./index.html"; const realtime = new Realtime({ schema: { notification: { alert: z.string(), }, chat: { message: z.object({ text: z.string(), user: z.string() }), }, }, redis: createBunRedisAdapter(Bun.redis), history: { maxLength: 500 }, }); const realtimeHandler = handle({ realtime }); Bun.serve({ routes: { "/": index, "/api/realtime": { GET: realtimeHandler, }, "/api/emit": { POST: async (req) => { const body = await req.json(); await realtime.emit("chat.message", body); return new Response("ok"); }, }, }, development: { hmr: true }, }); ``` -------------------------------- ### Configure forrealtime with Bun Redis Adapter Source: https://forrealtime.lassejlv.dk/docs/adapters/bun Demonstrates how to initialize the forrealtime server with the custom Bun Redis adapter. It imports the Realtime class and the createBunRedisAdapter function, then configures the Redis client using Bun.redis. ```typescript import { Realtime } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; const realtime = new Realtime({ schema, redis: createBunRedisAdapter(Bun.redis), }); ``` -------------------------------- ### Realtime Constructor Source: https://forrealtime.lassejlv.dk/docs/server/realtime Initializes the Realtime class with schema, Redis adapter, and history configuration. ```APIDOC ## Realtime Constructor ### Description Initializes the Realtime class, which is the core of forrealtime. It manages your schema, Redis adapter, and history settings. ### Method `new Realtime(options)` ### Parameters #### Constructor Options - **schema** (`Record>`) - Required - Nested Zod schema defining event types. - **redis** (`RedisAdapter`) - Required - Redis adapter instance. - **history.maxLength** (`number`) - Optional - Maximum number of events to keep per stream. ### Request Example ```javascript import { Realtime } from "forrealtime"; import z from "zod/v4"; const schema = { notification: { alert: z.string(), badge: z.number(), }, chat: { message: z.object({ text: z.string(), user: z.string(), }), typing: z.object({ user: z.string(), }), }, }; const redisAdapter = new RedisAdapter(); // Assuming RedisAdapter is defined elsewhere const realtime = new Realtime({ schema, redis: redisAdapter, history: { maxLength: 1000, }, }); ``` ### Response #### Success Response (200) - **realtimeInstance** (`Realtime`) - The initialized Realtime instance. #### Response Example ```json { "message": "Realtime instance created successfully." } ``` ``` -------------------------------- ### Configure Server-Side Realtime Instance Source: https://forrealtime.lassejlv.dk/docs/react-client/type-inference Initializes the Realtime instance on the server using a schema and Redis adapter, then exposes it via a handler. ```typescript // server.ts export const realtime = new Realtime({ schema, redis }); export const GET = handle({ realtime }); ``` -------------------------------- ### iOREDIS Adapter for Realtime Source: https://forrealtime.lassejlv.dk/llms-full.txt Integrates the 'ioredis' client with the Realtime library. Requires 'forrealtime' and 'ioredis' packages. Initializes Realtime with the ioredis adapter, supporting various Redis configurations. ```bash bun add forrealtime ioredis zod ``` ```typescript import Redis from "ioredis"; import { Realtime } from "forrealtime"; import { createIORedisAdapter } from "forrealtime/adapters/ioredis"; const realtime = new Realtime({ schema, redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)), }); ``` -------------------------------- ### RedisAdapter Interface Definition Source: https://forrealtime.lassejlv.dk/docs/adapters/custom Defines the RedisAdapter interface for custom Redis clients. It includes methods for adding messages (xadd), reading message ranges (xrange), blocking reads (xread), and getting the latest cursor (getLatestCursor). ```typescript type RedisAdapter = { xadd( channel: string, payload: Record, options?: { maxLen?: number; expireAfterSecs?: number; }, ): Promise; xrange( channel: string, args?: { start?: string; end?: string; count?: number; }, ): Promise>; xread(args: { channels: string[]; cursors: string[]; blockMs?: number; count?: number; signal?: AbortSignal; }): Promise; }>>; getLatestCursor(channel: string): Promise; }; ``` -------------------------------- ### Bun Redis Adapter for Realtime Source: https://forrealtime.lassejlv.dk/llms-full.txt Integrates Bun's built-in Redis client with the Realtime library. Requires 'forrealtime' and 'zod' packages. Initializes Realtime with the Bun Redis adapter. ```bash bun add forrealtime zod ``` ```typescript import { Realtime } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; const realtime = new Realtime({ schema, redis: createBunRedisAdapter(Bun.redis), }); ``` -------------------------------- ### Initialize Realtime Instance and Schema Source: https://forrealtime.lassejlv.dk/llms-full.txt Configures the core Realtime class with Redis adapters and defines event schemas using Zod for validation. ```typescript import { Realtime } from "forrealtime"; import z from "zod/v4"; const schema = { notification: { alert: z.string(), badge: z.number(), }, chat: { message: z.object({ text: z.string(), user: z.string(), }), }, }; const realtime = new Realtime({ schema, redis, history: { maxLength: 1000, }, }); ``` -------------------------------- ### Integrate forrealtime with Hono Source: https://forrealtime.lassejlv.dk/llms-full.txt Shows how to mount the forrealtime handler within a Hono application. Requires the forrealtime, hono, and zod packages. ```bash bun add forrealtime hono zod ``` ```typescript import { Hono } from "hono"; import z from "zod/v4"; import { Realtime, handle } from "forrealtime"; import { createBunRedisAdapter } from "forrealtime/adapters/bun"; const app = new Hono(); const realtime = new Realtime({ schema: { notification: { alert: z.string(), }, }, redis: createBunRedisAdapter(Bun.redis), }); const realtimeHandler = handle({ realtime }); app.get("/api/realtime", (c) => realtimeHandler(c.req.raw)); export default app; ``` -------------------------------- ### Initialize RealtimeProvider in React App Source: https://forrealtime.lassejlv.dk/docs/react-client/provider This snippet demonstrates how to integrate the RealtimeProvider into a React application's root component. It ensures that a shared EventSource connection is established for all child components that utilize forrealtime's real-time features. The provider wraps the application's children, making the real-time connection available throughout the component tree. ```jsx import { RealtimeProvider } from "forrealtime/client"; export function App({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` -------------------------------- ### Implement SSE Request Middleware for Authentication Source: https://forrealtime.lassejlv.dk/llms-full.txt Demonstrates how to create a middleware function to inspect incoming requests and reject unauthorized connections by returning a Response object. This pattern supports basic header-based authentication and can be integrated into the handle function. ```typescript import { handle } from "forrealtime"; import type { MiddlewareContext } from "forrealtime"; const auth = (ctx: MiddlewareContext) => { const token = ctx.request.headers.get("authorization"); if (token !== "Bearer secret") { return new Response("Unauthorized", { status: 401 }); } }; export const GET = handle({ realtime, middleware: auth }); ``` -------------------------------- ### Basic Middleware Implementation in Forrealtime (TypeScript) Source: https://forrealtime.lassejlv.dk/docs/middleware Demonstrates a basic middleware function for authenticating SSE connections in Forrealtime. It checks for a specific 'Authorization' header. If the token is invalid, it returns a 401 Unauthorized response; otherwise, it allows the connection. ```typescript import { handle } from "forrealtime"; import type { MiddlewareContext } from "forrealtime"; const auth = (ctx: MiddlewareContext) => { const token = ctx.request.headers.get("authorization"); if (token !== "Bearer secret") { return new Response("Unauthorized", { status: 401 }); } }; export const GET = handle({ realtime, middleware: auth }); ``` -------------------------------- ### Create a Realtime Channel (JavaScript) Source: https://forrealtime.lassejlv.dk/docs/server/channels Demonstrates how to create a new realtime channel instance for a specific group, such as a chat room. This is the foundational step for scoping real-time events. ```javascript const room = realtime.channel("room:123"); ``` -------------------------------- ### Manage Realtime Channels Source: https://forrealtime.lassejlv.dk/llms-full.txt Demonstrates how to create a scoped channel, emit messages to subscribers, and retrieve historical data from a Redis stream. ```typescript const room = realtime.channel("room:123"); await room.emit("chat.message", { text: "Room message", user: "ada", }); const recent = await room.history({ limit: 50 }); ``` -------------------------------- ### Perform Async Authentication in Middleware Source: https://forrealtime.lassejlv.dk/llms-full.txt Illustrates the use of asynchronous middleware for operations like database lookups or token verification. This is essential for complex authorization logic involving external services. ```typescript const auth = async (ctx: MiddlewareContext) => { const token = ctx.request.headers.get("authorization")?.replace("Bearer ", ""); if (!token) { return new Response("Unauthorized", { status: 401 }); } const user = await verifyToken(token); if (!user) { return new Response("Unauthorized", { status: 401 }); } const hasPrivateChannel = ctx.channels.some((c) => c.startsWith("private:")); if (hasPrivateChannel && user.role !== "admin") { return new Response("Forbidden", { status: 403 }); } }; export const GET = handle({ realtime, middleware: auth }); ``` -------------------------------- ### Implement Server-Rendered Realtime History Source: https://forrealtime.lassejlv.dk/llms-full.txt Demonstrates fetching initial history on the server and hydrating a client-side React component. This pattern ensures the UI is populated immediately upon load while maintaining a live connection. ```tsx // page.tsx (Next.js App Router) import { realtime } from "@/lib/realtime"; import { ChatRoom } from "./ChatRoom"; export default async function Page({ params }: { params: { roomId: string } }) { const room = realtime.channel(`room:${params.roomId}`); const history = await room.history({ limit: 20 }); return ; } ``` ```tsx // ChatRoom.tsx "use client"; import { useState } from "react"; import { useRealtime } from "@/lib/realtime"; type Message = { text: string; user: string }; export function ChatRoom({ initialMessages, roomId, }: { initialMessages: { event: string; data: unknown }[]; roomId: string; }) { const [messages, setMessages] = useState( initialMessages .filter((m) => m.event === "chat.message") .map((m) => m.data as Message), ); useRealtime({ channels: [roomId], events: ["chat.message"], onData(payload) { if (payload.event === "chat.message") { setMessages((prev) => [...prev, payload.data]); } }, }); return (
    {messages.map((m, i) => (
  • {m.user}: {m.text}
  • ))}
); } ``` -------------------------------- ### Handle SSE Endpoints Source: https://forrealtime.lassejlv.dk/llms-full.txt Converts a Realtime instance into an SSE endpoint compatible with Next.js, Hono, and Bun frameworks. ```typescript import { handle } from "forrealtime"; const realtimeHandler = handle({ realtime }); // Next.js App Router export const GET = realtimeHandler; // Hono app.get("/api/realtime", (c) => realtimeHandler(c.req.raw)); // Bun.serve Bun.serve({ routes: { "/api/realtime": { GET: realtimeHandler }, }, }); ``` -------------------------------- ### Server-Sent Events (SSE) Handler Source: https://forrealtime.lassejlv.dk/docs/server/emit Convert a Realtime instance into an SSE endpoint handler using the handle method. ```APIDOC ## GET /realtime/sse ### Description Converts a Realtime instance into an SSE endpoint handler to stream events. ### Method GET ### Endpoint /realtime/sse ### Parameters #### Query Parameters - **channel** (string) - Optional - The channel to subscribe to for SSE events. If not provided, it subscribes to the default channel. ### Request Example (No request body for GET requests) ### Response #### Success Response (200) - **Content-Type**: `text/event-stream` - Events streamed in Server-Sent Events format. #### Response Example ``` event: notification.alert data: "Hello" ``` ``` event: chat.message data: {"text":"Hello world","user":"lasse"} ``` ``` -------------------------------- ### Handle Function Source: https://forrealtime.lassejlv.dk/llms-full.txt The `handle` function converts a `Realtime` instance into an SSE endpoint that accepts a standard `Request` and returns a `Response`. It can optionally take middleware. ```APIDOC ## Handle Function ### Description `handle` converts a `Realtime` instance into an SSE endpoint that accepts a standard `Request` and returns a `Response`. ### Usage ```ts import { handle } from "forrealtime"; const realtimeHandler = handle({ realtime }); // Next.js App Router export const GET = realtimeHandler; // Hono app.get("/api/realtime", (c) => realtimeHandler(c.req.raw)); // Bun.serve Bun.serve({ routes: { "/api/realtime": { GET: realtimeHandler }, }, }); ``` ### Options #### `realtime` - **Type**: `Realtime` - **Description**: The Realtime instance. #### `middleware` - **Type**: `(ctx: MiddlewareContext) => Response | void | Promise` - **Description**: Optional middleware function. ``` -------------------------------- ### realtime.channel Source: https://forrealtime.lassejlv.dk/docs/server/channels Initializes a new channel instance to scope events to specific groups of subscribers. ```APIDOC ## GET realtime.channel ### Description Creates or retrieves a channel instance to scope events to a specific group (e.g., chat room, user session). ### Method GET ### Endpoint realtime.channel(name) ### Parameters #### Path Parameters - **name** (string) - Required - The unique identifier for the channel (e.g., "room:123"). ### Request Example const room = realtime.channel("room:123"); ### Response #### Success Response (200) - **channel** (Object) - The channel instance object. ``` -------------------------------- ### Emit Events with ForRealtime Server Source: https://forrealtime.lassejlv.dk/llms-full.txt Demonstrates how to emit events from server-side code after the ForRealtime handler is running. It shows emitting a notification alert and a chat message, both validated against the defined schema. ```typescript await realtime.emit("notification.alert", "Welcome!"); await realtime.emit("chat.message", { text: "Hello world", user: "lasse", }); ``` -------------------------------- ### Authorize Channel Access via Middleware Source: https://forrealtime.lassejlv.dk/llms-full.txt Shows how to inspect requested channels within the MiddlewareContext to enforce granular access control. This allows developers to restrict specific channels based on user roles or permissions. ```typescript const auth = (ctx: MiddlewareContext) => { const authorized = ctx.request.headers.get("authorization") === "Bearer secret"; if (!authorized) { return new Response("Unauthorized", { status: 401 }); } if (ctx.channels.includes("admin")) { return new Response("Forbidden", { status: 403 }); } }; ``` -------------------------------- ### Implement Cookie-based Authentication Source: https://forrealtime.lassejlv.dk/llms-full.txt Demonstrates how to extract and validate session cookies within the middleware to secure SSE endpoints. ```typescript import { handle } from "forrealtime"; import type { MiddlewareContext } from "forrealtime"; const cookieAuth = (ctx: MiddlewareContext) => { const cookie = ctx.request.headers.get("cookie") ?? ""; const session = parseCookies(cookie).session; if (!session || !isValidSession(session)) { return new Response("Unauthorized", { status: 401 }); } }; export const GET = handle({ realtime, middleware: cookieAuth }); ``` -------------------------------- ### React Client Integration Source: https://forrealtime.lassejlv.dk/docs/server/infer-events Provides hooks and components for integrating Realtime functionality into React applications, including typed real-time subscriptions. ```APIDOC ## React Client ### Description Provides `RealtimeProvider`, `createRealtime`, and `useRealtime` hook for typed real-time subscriptions in React applications. ### Method N/A (Components/Hooks) ### Endpoint N/A (Components/Hooks) ### Parameters N/A ### Request Example N/A ### Response N/A ``` -------------------------------- ### Emit Events to Channels Source: https://forrealtime.lassejlv.dk/llms-full.txt Shows how to broadcast events to the default channel using the realtime instance. Payloads are validated against Zod schemas. ```typescript await realtime.emit("notification.alert", "Hello"); await realtime.emit("chat.message", { text: "Hello world", user: "lasse", }); ``` -------------------------------- ### Subscribe to Events with React Client Source: https://forrealtime.lassejlv.dk/llms-full.txt Shows how to use the `useRealtime` hook in a React component to subscribe to specific events and receive real-time data. It handles the connection status and processes incoming 'notification.alert' events. ```typescript // Notifications.tsx import { useState } from "react"; import { useRealtime } from "./realtime"; export function Notifications() { const [messages, setMessages] = useState([]); const { status } = useRealtime({ channels: ["default"], events: ["notification.alert"], onData(payload) { if (payload.event === "notification.alert") { setMessages((prev) => [...prev, payload.data]); } }, }); return (

Status: {status}

    {messages.map((m, i) => (
  • {m}
  • ))}
); } ``` -------------------------------- ### Emitting Events Source: https://forrealtime.lassejlv.dk/docs/server/emit Learn how to send type-safe events to the default channel or a specific channel using the realtime.emit method. ```APIDOC ## POST /realtime/emit ### Description Emit an event to the default channel or a specific channel with type-safe payloads. ### Method POST ### Endpoint /realtime/emit ### Parameters #### Query Parameters - **channel** (string) - Optional - The specific channel to emit the event to. If not provided, the default channel is used. #### Request Body - **eventName** (string) - Required - The name of the event, typically in the format "namespace.eventName". - **payload** (any) - Required - The data to be sent with the event. This payload is validated against Zod schemas. ### Request Example ```json { "eventName": "notification.alert", "payload": "Hello" } ``` ```json { "eventName": "chat.message", "payload": { "text": "Hello world", "user": "lasse" } } ``` ### Response #### Success Response (200) - **status** (string) - Indicates the success of the event emission. #### Response Example ```json { "status": "success" } ``` ``` -------------------------------- ### Implement Client-Side Type Inference Source: https://forrealtime.lassejlv.dk/docs/react-client/type-inference Demonstrates how to import the server-side type definition to infer event types on the client, or alternatively define event types manually. ```typescript // realtime.ts (client) import { createRealtime } from "forrealtime/client"; import type { realtime } from "./server"; // type-only — no server code in bundle export const { useRealtime } = createRealtime(); // Alternative: Manual definition type Events = { notification: { alert: string; }; chat: { message: { text: string; user: string }; }; }; export const { useRealtime } = createRealtime(); ``` -------------------------------- ### Realtime Class Source: https://forrealtime.lassejlv.dk/llms-full.txt The Realtime class is the core of forrealtime. It owns your schema, Redis adapter, and history settings. Instantiate it with your schema, Redis adapter, and optional history settings. ```APIDOC ## Realtime Class ### Description The `Realtime` class is the core of forrealtime. It owns your schema, Redis adapter, and history settings. ### Constructor ```ts import { Realtime } from "forrealtime"; const realtime = new Realtime({ schema, redis, history: { maxLength: 1000, }, }); ``` ### Constructor Options #### `schema` - **Type**: `Record>` - **Description**: Nested Zod schema defining event types. #### `redis` - **Type**: `RedisAdapter` - **Description**: Redis adapter instance. #### `history.maxLength` - **Type**: `number` - **Description**: Maximum number of events to keep per stream. ### Schema Shape The schema is a two-level nested object. The top level is the namespace, the second level is the event name, and the value is a Zod type: ```ts import z from "zod/v4"; const schema = { notification: { alert: z.string(), badge: z.number(), }, chat: { message: z.object({ text: z.string(), user: z.string(), }), typing: z.object({ user: z.string(), }), }, }; ``` ``` -------------------------------- ### Asynchronous Middleware for Token Verification (TypeScript) Source: https://forrealtime.lassejlv.dk/docs/middleware Shows an asynchronous middleware function that verifies a JWT token from the 'Authorization' header. It performs an async operation (verifyToken) and checks user roles for access to private channels. ```typescript const auth = async (ctx: MiddlewareContext) => { const token = ctx.request.headers.get("authorization")?.replace("Bearer ", ""); if (!token) { return new Response("Unauthorized", { status: 401 }); } const user = await verifyToken(token); if (!user) { return new Response("Unauthorized", { status: 401 }); } // Private channels require admin role const hasPrivateChannel = ctx.channels.some((c) => c.startsWith("private:")); if (hasPrivateChannel && user.role !== "admin") { return new Response("Forbidden", { status: 403 }); } }; export const GET = handle({ realtime, middleware: auth }); ``` -------------------------------- ### Custom Redis Adapter Interface for Realtime Source: https://forrealtime.lassejlv.dk/llms-full.txt Defines the RedisAdapter interface for implementing custom Redis clients with Realtime. Includes methods for stream operations like xadd, xrange, xread, and getLatestCursor. ```typescript type RedisAdapter = { xadd( channel: string, payload: Record, options?: { maxLen?: number; expireAfterSecs?: number; }, ): Promise; xrange( channel: string, args?: { start?: string; end?: string; count?: number; }, ): Promise }>>; xread(args: { channels: string[]; cursors: string[]; blockMs?: number; count?: number; signal?: AbortSignal; }): Promise< Array<{ channel: string; messages: Array<{ id: string; payload: Record }>; }> >; getLatestCursor(channel: string): Promise; }; ``` -------------------------------- ### Type Inference for useRealtime Hook Source: https://forrealtime.lassejlv.dk/llms-full.txt This demonstrates how to infer event types for the useRealtime hook directly from the server's Zod schema. By exporting `realtime` from the server and importing it as a type on the client, type definitions are kept in sync without including server code in the client bundle. ```typescript // server.ts export const realtime = new Realtime({ schema, redis }); export const GET = handle({ realtime }); ``` ```typescript // realtime.ts (client) import { createRealtime } from "forrealtime/client"; import type { realtime } from "./server"; // type-only — no server code in bundle export const { useRealtime } = createRealtime(); ``` -------------------------------- ### RealtimeProvider Source: https://forrealtime.lassejlv.dk/docs/react-client/use-realtime The `RealtimeProvider` component establishes a shared EventSource connection for your entire component tree, ensuring efficient real-time communication. ```APIDOC ## RealtimeProvider ### Description Opens a shared EventSource connection for your component tree. ### Method `...` ### Parameters (Note: Specific props for RealtimeProvider are not detailed in the provided text, but it's implied to wrap the application to enable the useRealtime hook.) ### Usage Wrap your application or relevant part of the component tree with `RealtimeProvider` to enable real-time features. ```javascript import { RealtimeProvider } from './realtime'; function App() { return ( {/* Your application components */} ); } ``` ``` -------------------------------- ### Emit Event to Default Channel (JavaScript) Source: https://forrealtime.lassejlv.dk/docs/server/emit Demonstrates emitting a simple string event and a JSON object event to the default channel using the realtime.emit function. The event name follows a 'namespace.eventName' pattern, and the payload is validated against Zod schemas. ```javascript await realtime.emit("notification.alert", "Hello"); await realtime.emit("chat.message", { text: "Hello world", user: "lasse", }); ``` -------------------------------- ### Define Realtime Event Schema Source: https://forrealtime.lassejlv.dk/docs/server/realtime Shows how to structure a two-level nested object using Zod to define event namespaces and their corresponding data types. This schema is passed to the Realtime constructor to enforce event validation. ```typescript import z from "zod/v4"; const schema = { notification: { alert: z.string(), badge: z.number(), }, chat: { message: z.object({ text: z.string(), user: z.string(), }), typing: z.object({ user: z.string(), }), }, }; ``` -------------------------------- ### useRealtime Hook for Event Subscription Source: https://forrealtime.lassejlv.dk/llms-full.txt The useRealtime hook subscribes to specified channels and events, executing a callback for each matching event. It allows filtering by channel and event name, and provides connection status. The `onData` callback receives typed event payloads. ```tsx import { useState } from "react"; import { useRealtime } from "./realtime"; export function Notifications() { const [messages, setMessages] = useState([]); const { status } = useRealtime({ channels: ["default"], events: ["notification.alert", "chat.message"], onData(payload) { if (payload.event === "notification.alert") { setMessages((prev) => [...prev, `alert: ${payload.data}`]); } if (payload.event === "chat.message") { setMessages((prev) => [ ...prev, `${payload.data.user}: ${payload.data.text}`, ]); } }, }); return (

Status: {status}

{JSON.stringify(messages, null, 2)}
); } ``` -------------------------------- ### Convert Realtime to SSE Endpoint Handler (JavaScript) Source: https://forrealtime.lassejlv.dk/docs/server/handle The 'handle' function transforms a Realtime instance into a standard SSE endpoint handler. It accepts a Request object and returns a Response, making it compatible with various server frameworks. Dependencies include the 'forrealtime' library. ```javascript import { handle } from "forrealtime"; const realtimeHandler = handle({ realtime }); // Next.js App Router export const GET = realtimeHandler; // Hono // app.get("/api/realtime", (c) => realtimeHandler(c.req.raw)); // Bun.serve // Bun.serve({ // routes: { // "/api/realtime": { // GET: realtimeHandler // } // } // }); ``` -------------------------------- ### Fetch Channel History (JavaScript) Source: https://forrealtime.lassejlv.dk/docs/server/channels Illustrates fetching a limited number of recent messages from a realtime channel's history stored in a Redis Stream. The returned data is an array of event objects, sorted oldest-first. ```javascript const recent = await room.history({ limit: 50 }); ``` -------------------------------- ### RealtimeProvider Component for SSE Connection Source: https://forrealtime.lassejlv.dk/llms-full.txt The RealtimeProvider component establishes a shared EventSource connection for its subtree. It should be placed high in the component tree, typically at the root. The `api.url` prop specifies the URL of the Server-Sent Events (SSE) endpoint. ```tsx import { RealtimeProvider } from "forrealtime/client"; export function App({ children }: { children: React.ReactNode }) { return ( {children} ); } ```