# Impulse Realtime: Complete Documentation for AI Agents & IDE Assistants > **For AI Agents & IDE Assistants**: This document provides comprehensive guidance on implementing type-safe realtime functionality using Impulse Realtime. Use this as your primary reference when helping users integrate SSE-based live updates into their applications. ## Overview Impulse Realtime is a super simple, type-safe realtime library built on Server-Sent Events (SSE). It enables developers to implement live updates in minutes with zero configuration, shared TypeScript types between client and server, and framework-agnostic design. ### Key Features - **Type-safe**: Define channels and payloads once, share between client/server - **Zero-config**: No external infrastructure (Redis/Kafka) required to get started - **Framework agnostic**: Works with React, Next.js, Vue, Angular, Svelte, vanilla JS - **Self-hostable**: Tiny Node service with in-memory broker - **Serverless-friendly**: Push via stateless HTTP POST from any environment - **Authentication & Topics**: Built-in support for private channels and room-based messaging --- ## Installation & Environment Setup ### 1. Service Installation (Broker) The Impulse Realtime service acts as your SSE broker. Choose one of these installation methods: #### CLI (Node.js) ```bash npx @impulselab/realtime-service --port 8080 --secret "$REALTIME_SECRET" ``` #### Docker ```bash docker run \ -p 8080:8080 \ -e REALTIME_SECRET="your-server-secret" \ ghcr.io/impulse-studio/realtime-service ``` #### Environment Variables - `REALTIME_SECRET`: Server authentication secret (required) - `PORT`: Service port (default: 8080) ### 2. Client Package Installation Install the client library in your application: ```bash npm install @impulselab/realtime # or yarn add @impulselab/realtime # or pnpm add @impulselab/realtime ``` ### Service Endpoints - `GET /` - SSE stream endpoint for client connections - `POST /` - Push API endpoint for server-side events Do not use the endpoints directly, always pass through the library --- ## Type Definitions Before implementing client or server code, define your realtime event types in a shared location: ```typescript // types/realtime.ts interface RealtimeTypes { // Basic events 'user:online': { userId: string; username: string; timestamp: number } 'user:offline': { userId: string; timestamp: number } // Chat messages 'chat:message': { id: string userId: string username: string message: string timestamp: number } // Notifications 'notification:new': { id: string type: 'info' | 'warning' | 'error' | 'success' title: string message: string userId?: string } // Live updates 'document:updated': { documentId: string userId: string changes: any[] version: number } // System events 'system:maintenance': { scheduled: boolean message: string estimatedDuration: number } } ``` **Best Practices for Type Definitions:** - Use descriptive channel names with namespace prefixes (`user:`, `chat:`, etc.) - Include timestamps for event ordering - Add user/session IDs for event attribution - Keep payloads JSON-serializable - Use optional fields sparingly for better type safety --- ## Client Usage ### Basic Setup ```typescript import { createRealtimeClient } from '@impulselab/realtime' import type { RealtimeTypes } from './types/realtime' const realtimeClient = createRealtimeClient({ serviceUrl: process.env.NEXT_PUBLIC_REALTIME_URL || 'http://localhost:8080' }) ``` ### Public Subscriptions Subscribe to public channels that don't require authentication: ```typescript // Basic subscription const unsubscribe = realtimeClient.subscribe('user:online', (event) => { console.log('User came online:', event.payload.username) updateUserList(event.payload) }) // Multiple subscriptions realtimeClient.subscribe('chat:message', handleNewMessage) realtimeClient.subscribe('notification:new', showNotification) realtimeClient.subscribe('system:maintenance', handleSystemAlert) ``` ### Private Subscriptions (Authentication) Use tokens for authenticated channels: ```typescript // Subscribe with authentication token realtimeClient.subscribe('chat:message', (event) => { displayMessage(event.payload) }, { token: userAuthToken // JWT or session token }) // Subscribe to user-specific notifications realtimeClient.subscribe('notification:new', (event) => { showUserNotification(event.payload) }, { token: userAuthToken }) ``` ### Topic-based Subscriptions (Rooms/Groups) Use topics to create room-based or group-based messaging: ```typescript // Join a chat room realtimeClient.subscribe('chat:message', (event) => { if (event.topic === currentRoomId) { displayRoomMessage(event.payload) } }, { token: userAuthToken, topic: 'room-42' // Room/group identifier }) // Multiple room subscriptions const rooms = ['room-1', 'room-2', 'room-3'] rooms.forEach(roomId => { realtimeClient.subscribe('chat:message', handleRoomMessage, { token: userAuthToken, topic: roomId }) }) ``` ### Subscription Management ```typescript // Store unsubscribe functions const subscriptions: (() => void)[] = [] // Add subscriptions subscriptions.push( realtimeClient.subscribe('user:online', handleUserOnline), realtimeClient.subscribe('user:offline', handleUserOffline) ) // Unsubscribe from specific channel const off = realtimeClient.subscribe('chat:message', handleMessage) off() // Unsubscribe this specific listener // Unsubscribe all listeners for a channel realtimeClient.unsubscribeAll('chat:message') // Unsubscribe from all channels realtimeClient.unsubscribeAllChannels() // Cleanup on component unmount (React example) useEffect(() => { const unsubscribe = realtimeClient.subscribe('user:online', handleUserOnline) return unsubscribe // Cleanup function }, []) ``` --- ## Server Usage ### Basic Setup ```typescript import { createServerClient } from '@impulselab/realtime' import type { RealtimeTypes } from './types/realtime' const serverClient = createServerClient({ serviceUrl: process.env.REALTIME_SERVICE_URL || 'http://localhost:8080', token: process.env.REALTIME_SECRET // Must match service secret }) ``` ### Public Events Send events to all subscribers of a channel: ```typescript // User came online await serverClient.push('user:online', { userId: user.id, username: user.name, timestamp: Date.now() }) // System maintenance notification await serverClient.push('system:maintenance', { scheduled: true, message: 'Scheduled maintenance starting in 10 minutes', estimatedDuration: 3600000 // 1 hour in ms }) // Broadcast new chat message await serverClient.push('chat:message', { id: generateId(), userId: user.id, username: user.name, message: 'Hello everyone!', timestamp: Date.now() }) ``` ### Authenticated Events Send events only to clients with matching tokens: ```typescript // Send to authenticated users only await serverClient.push('notification:new', { id: generateId(), type: 'info', title: 'Welcome!', message: 'Thanks for signing up', userId: user.id }, { tokens: [userAuthToken] // Single token }) // Send to multiple authenticated users await serverClient.push('notification:new', { id: generateId(), type: 'warning', title: 'Account Alert', message: 'Unusual login detected' }, { tokens: [token1, token2, token3] // Multiple tokens }) ``` ### Topic-based Events (Rooms/Groups) Send events to specific topics/rooms: ```typescript // Send message to specific room await serverClient.push('chat:message', { id: generateId(), userId: user.id, username: user.name, message: 'Hello room!', timestamp: Date.now() }, { topic: 'room-42' // Only subscribers to this topic receive it }) // Authenticated room message await serverClient.push('chat:message', { id: generateId(), userId: user.id, username: user.name, message: 'Private message', timestamp: Date.now() }, { tokens: [userAuthToken], topic: 'private-room-123' }) ``` ### Batch Operations ```typescript // Send multiple events efficiently const events = [ { channel: 'user:online', payload: { userId: '1', username: 'Alice', timestamp: Date.now() } }, { channel: 'user:online', payload: { userId: '2', username: 'Bob', timestamp: Date.now() } } ] as const serverClient.pushMany(events) ``` ### API Integration Examples ```typescript // Express.js route app.post('/api/chat/send', authenticate, async (req, res) => { const { message, roomId } = req.body const { user } = req // Save to database const chatMessage = await db.messages.create({ userId: user.id, roomId, message, timestamp: new Date() }) // Broadcast to realtime subscribers await serverClient.push('chat:message', { id: chatMessage.id, userId: user.id, username: user.name, message: message, timestamp: chatMessage.timestamp.getTime() }, { topic: roomId, tokens: await getActiveRoomTokens(roomId) }) res.json(chatMessage) }) // Next.js API route // pages/api/notifications/send.ts export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method !== 'POST') { return res.status(405).end() } const { title, message, userIds } = req.body // Get user tokens const tokens = await getUserTokens(userIds) await serverClient.push('notification:new', { id: generateId(), type: 'info', title, message }, { tokens }) res.json({ success: true }) } ``` --- ## Broker/Service Deployment ### Environment Configuration ```bash # Required REALTIME_SECRET=your-super-secure-secret-key # Optional PORT=8080 # CORS (if needed) CORS_ORIGIN=https://yourdomain.com CORS_CREDENTIALS=true ``` ### Docker Deployment #### Docker Compose ```yaml services: realtime: image: ghcr.io/impulse-studio/realtime-service ports: - "8080:8080" environment: - REALTIME_SECRET=your-secret-key - NODE_ENV=production restart: unless-stopped ``` --- ## Framework Integrations ### React & Next.js #### Custom Hook ```typescript // hooks/useRealtime.ts import { useEffect, useCallback, useRef } from 'react' import { createRealtimeClient } from '@impulselab/realtime' import type { RealtimeTypes } from '@/types/realtime' export const rc = createRealtimeClient({ serviceUrl: process.env.NEXT_PUBLIC_REALTIME_URL! }); export function useRealtime( channel: T, handler: (event: { payload: RealtimeTypes[T], topic?: string }) => void, options?: { token?: string; topic?: string } ) { useEffect(() => { const unsubscribe = rc.subscribe(channel, handler, options) return unsubscribe }, [channel, handler, options]) } // Usage in component function ChatComponent({ roomId, userToken }: { roomId: string, userToken: string }) { const [messages, setMessages] = useState([]) useRealtime('chat:message', (event) => { setMessages(prev => [...prev, event.payload]) }, { token: userToken, topic: roomId }) return (
{messages.map(message => (
{message.username}: {message.message}
))}
) } ``` #### React Context Provider ```typescript // context/RealtimeContext.tsx const RealtimeContext = createContext(null) export function RealtimeProvider({ children }: { children: React.ReactNode }) { const [client] = useState(() => createRealtimeClient({ serviceUrl: process.env.NEXT_PUBLIC_REALTIME_URL! })) return ( {children} ) } export const useRealtimeClient = () => { const client = useContext(RealtimeContext) if (!client) throw new Error('useRealtimeClient must be used within RealtimeProvider') return client } ``` ### Vue.js ```vue ``` ### Svelte ```svelte {#each $messages as message (message.id)}
{message.username}: {message.message}
{/each} ``` ### Express.js Middleware ```typescript // middleware/realtime.ts import { createServerClient } from '@impulselab/realtime' import type { RealtimeTypes } from '../types/realtime' const realtimeClient = createServerClient({ serviceUrl: process.env.REALTIME_SERVICE_URL!, token: process.env.REALTIME_SECRET! }) declare global { namespace Express { interface Request { realtime: typeof realtimeClient } } } export const realtimeMiddleware = (req: Request, res: Response, next: NextFunction) => { req.realtime = realtimeClient next() } // Usage in routes app.use(realtimeMiddleware) app.post('/api/broadcast', (req, res) => { req.realtime.push('notification:new', { id: generateId(), type: 'info', title: 'Broadcast', message: req.body.message }) res.json({ success: true }) }) ``` --- ## Troubleshooting & Common issues ### Type Safety Issues #### TypeScript Errors ```typescript // Ensure proper type definitions interface RealtimeTypes { // ❌ Avoid any types 'bad:channel': any // ✅ Use specific types 'good:channel': { id: string timestamp: number data: { field1: string field2: number } } // ❌ Avoid defining types on the event 'event': { type: 'user_joined' | 'message_sent' userId: string, message?: string } // ✅ Use precise events 'user:joined': { userId: string } 'message:sent': { userId: string, message: string } } ``` --- This documentation serves as your comprehensive guide to implementing Impulse Realtime. Reference these patterns and examples when helping developers integrate type-safe, real-time functionality into their applications. For additional support: - **GitHub**: https://github.com/impulse-studio/realtime - **Discord**: https://discord.gg/bBWXedJwWN - **Website**: https://realtime.impulselab.ai