### 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}
);
}
```