### Initialize Realtime Instance
Source: https://context7.com/upstash/realtime/llms.txt
Configure the Realtime instance with Redis, Zod schemas for type safety, and optional history settings.
```typescript
import { Realtime } from "@upstash/realtime";
import { Redis } from "@upstash/redis";
import { z } from "zod";
// Define your event schema with Zod for type-safe events
const schema = {
message: z.object({
text: z.string(),
userId: z.string(),
}),
notification: z.object({
title: z.string(),
body: z.string(),
}),
// Nested schemas for organizing events
user: {
joined: z.object({ userId: z.string(), name: z.string() }),
left: z.object({ userId: z.string() }),
},
};
// Create the Realtime instance
const realtime = new Realtime({
redis: Redis.fromEnv(),
schema,
maxDurationSecs: 300, // Connection timeout (default: 300s for Vercel)
verbose: true, // Enable logging
history: {
maxLength: 1000, // Maximum messages to retain per channel
expireAfterSecs: 86400, // Expire history after 24 hours
},
});
export { realtime };
```
--------------------------------
### Set Up RealtimeProvider in React Layout
Source: https://context7.com/upstash/realtime/llms.txt
Wrap your React application with `RealtimeProvider` to enable realtime subscriptions globally. Configure the SSE endpoint URL and connection options like `withCredentials` and `maxReconnectAttempts`.
```tsx
// app/layout.tsx or _app.tsx
"use client";
import { RealtimeProvider } from "@upstash/realtime/client";
export default function RootLayout({
children,
}: { children: React.ReactNode }) {
return (
{children}
);
}
```
--------------------------------
### Create a Typed Realtime Client with Event Schema
Source: https://context7.com/upstash/realtime/llms.txt
Define a shared event schema using `createRealtime` to ensure type safety across your application. This factory creates a `useRealtime` hook with inferred types for events and data.
```typescript
// lib/realtime-client.ts
"use client";
import { createRealtime } from "@upstash/realtime/client";
// Define your event schema (should match server-side schema)
type RealtimeEvents = {
message: { text: string; userId: string };
notification: { title: string; body: string };
user: {
joined: { userId: string; name: string };
left: { userId: string };
};
};
export const { useRealtime } = createRealtime();
// Usage in components with full type inference
// components/NotificationBell.tsx
"use client";
import { useRealtime } from "@/lib/realtime-client";
export function NotificationBell() {
const { status } = useRealtime({
channels: ["notifications"],
events: ["notification"] as const,
onData: (event) => {
// event.data is typed as { title: string; body: string }
showToast(event.data.title, event.data.body);
},
});
return ;
}
```
--------------------------------
### Create SSE Request Handler with Middleware
Source: https://context7.com/upstash/realtime/llms.txt
Implement an HTTP endpoint for SSE connections with optional authentication and authorization middleware. The middleware validates tokens and checks channel permissions before allowing a connection.
```typescript
// app/api/realtime/route.ts (Next.js App Router)
import { handle } from "@upstash/realtime";
import { realtime } from "@/lib/realtime";
const handler = handle({
realtime,
// Optional authentication middleware
middleware: async ({ request, channels }) => {
const authHeader = request.headers.get("authorization");
if (!authHeader) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
// Validate token and check channel permissions
const userId = await validateToken(authHeader);
const allowedChannels = await getUserChannels(userId);
for (const channel of channels) {
if (!allowedChannels.includes(channel)) {
return new Response(JSON.stringify({ error: "Forbidden" }), {
status: 403,
headers: { "Content-Type": "application/json" },
});
}
}
// Return undefined to allow the connection
return undefined;
},
});
export async function GET(request: Request) {
return handler(request);
}
```
--------------------------------
### Subscribe to Events
Source: https://context7.com/upstash/realtime/llms.txt
Listen for specific events on a channel and optionally replay historical messages upon subscription.
```typescript
import { realtime } from "./realtime";
// Subscribe to specific events on a channel
const unsubscribe = await realtime.channel("chat-room-1").subscribe({
events: ["message", "user.joined"] as const,
onData: (event) => {
console.log(`Received ${event.event}:`, event.data);
// event.event is typed as "message" | "user.joined"
// event.data is typed based on the schema
},
// Optionally replay history on subscribe
history: {
limit: 100, // Get last 100 messages
},
});
// Unsubscribe when done
unsubscribe();
```
--------------------------------
### Subscribe to Events
Source: https://context7.com/upstash/realtime/llms.txt
Subscribe to specific events on a channel to receive real-time updates or replay historical messages.
```APIDOC
## POST /subscribe
### Description
Registers a listener for specific events on a channel. Supports optional history replay upon subscription.
### Parameters
#### Request Body
- **events** (array) - Required - List of event names to subscribe to.
- **onData** (function) - Required - Callback function executed when an event is received.
- **history** (object) - Optional - Configuration for replaying past messages.
- **limit** (number) - Optional - Number of historical messages to retrieve.
### Request Example
{
"events": ["message", "user.joined"],
"history": {
"limit": 100
}
}
```
--------------------------------
### Emit Realtime Events
Source: https://context7.com/upstash/realtime/llms.txt
Send type-safe events to default or specific channels using the emit method.
```typescript
import { realtime } from "./realtime";
// Emit to default channel
await realtime.emit("message", {
text: "Hello, World!",
userId: "user-123",
});
// Emit to a specific channel
await realtime.channel("chat-room-1").emit("message", {
text: "Welcome to the chat!",
userId: "admin",
});
// Emit nested events
await realtime.channel("lobby").emit("user.joined", {
userId: "user-456",
name: "Alice",
});
```
--------------------------------
### Emit Events
Source: https://context7.com/upstash/realtime/llms.txt
The emit method sends type-safe events to channels, persisting them to Redis Streams and broadcasting to subscribers.
```APIDOC
## POST /emit
### Description
Sends a type-safe event to a specified channel or the default channel. Events are persisted to Redis Streams.
### Parameters
#### Request Body
- **event** (string) - Required - The name of the event defined in the schema.
- **data** (object) - Required - The payload matching the schema definition for the event.
### Request Example
{
"event": "message",
"data": {
"text": "Hello, World!",
"userId": "user-123"
}
}
```
--------------------------------
### Access Realtime Context Directly with useRealtimeContext
Source: https://context7.com/upstash/realtime/llms.txt
Use `useRealtimeContext` to access the realtime connection status directly within any component. This is useful for displaying connection indicators or managing subscriptions manually.
```tsx
"use client";
import { useRealtimeContext } from "@upstash/realtime/client";
export function ConnectionIndicator() {
const { status } = useRealtimeContext();
return (
{status}
);
}
```
--------------------------------
### Subscribe to Realtime Events with useRealtime Hook
Source: https://context7.com/upstash/realtime/llms.txt
Use the `useRealtime` hook within React components to subscribe to specific channels and events. It provides connection status and handles incoming data with automatic connection management.
```tsx
"use client";
import { useRealtime } from "@upstash/realtime/client";
import { useState } from "react";
type Message = {
text: string;
userId: string;
};
export function ChatRoom({ roomId }: { roomId: string }) {
const [messages, setMessages] = useState([]);
const { status } = useRealtime<{
message: Message;
"user.joined": { userId: string; name: string };
}>({
channels: [roomId], // Subscribe to specific channel
events: ["message", "user.joined"] as const,
enabled: true, // Can be toggled to enable/disable
onData: (event) => {
if (event.event === "message") {
setMessages((prev) => [...prev, event.data]);
} else if (event.event === "user.joined") {
console.log(`${event.data.name} joined the chat`);
}
},
});
return (
Connection Status: {status}
{/* status: "connected" | "connecting" | "disconnected" | "error" */}
{messages.map((msg, i) => (
- {msg.text}
))}
);
}
```
--------------------------------
### Retrieve Message History
Source: https://context7.com/upstash/realtime/llms.txt
Fetch historical messages from Redis Streams, supporting filtering by time range and result limits.
```typescript
import { realtime } from "./realtime";
// Get history from default channel
const messages = await realtime.history({
limit: 50, // Max 1000
});
// Get history from specific channel with time range
const channelHistory = await realtime.channel("chat-room-1").history({
start: Date.now() - 3600000, // 1 hour ago
end: Date.now(),
limit: 100,
});
// Each message includes: id, event, channel, data
messages.forEach((msg) => {
console.log(`[${msg.id}] ${msg.event}: ${JSON.stringify(msg.data)}`);
});
```
--------------------------------
### Retrieve Message History
Source: https://context7.com/upstash/realtime/llms.txt
Fetch historical messages from Redis Streams for a specific channel or the default channel.
```APIDOC
## GET /history
### Description
Retrieves historical messages from Redis Streams with optional filtering by time range and limit.
### Parameters
#### Query Parameters
- **start** (number) - Optional - Start timestamp for history retrieval.
- **end** (number) - Optional - End timestamp for history retrieval.
- **limit** (number) - Optional - Maximum number of messages to return (max 1000).
### Response
#### Success Response (200)
- **messages** (array) - List of message objects containing id, event, channel, and data.
#### Response Example
[
{
"id": "1715678900000-0",
"event": "message",
"channel": "chat-room-1",
"data": { "text": "Hello", "userId": "user-1" }
}
]
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.