Newsletter
Join the Community
Subscribe to our newsletter for the latest news and updates
Realtime live cursors, presence, and emoji reactions over a WebSocket, built with Nitro v3, React, and shadcn/ui.
The Nitro + WebSockets Starter is a realtime boilerplate from the Vercel examples repository that demonstrates live presence, shared cursors, and emoji reactions over a single WebSocket connection, built with Nitro v3, React, and shadcn/ui.
This starter ships a minimal realtime app: a React single-page application (Vite) on the frontend and a Nitro v3 server with native WebSocket support, powered by crossws, on the backend. It takes a WebSocket connection at /api/ws and produces a live collaborative room where every client sees cursor movements, join/leave events, and emoji reactions. The realtime layer runs entirely on Vercel Functions using the WebSockets beta, with no environment variables and no external services. The project is published under the MIT license as part of the official Vercel examples repository.
defineWebSocketHandler in server/api/ws.ts works in local dev and production; on Vercel the preset's crossws/adapters/vercel bridge handles the upgrade, so there is no Vercel-specific code path.room topic, and events like cursor moves and reactions are broadcast with crossws's peer.publish — no external store and no client SDK.shared/types/realtime.ts defines ClientMessage, ServerMessage, and Peer types used by both client and server, keeping message handling in sync.welcome frame; a heartbeat (ping/pong) detects half-open connections and forces a reconnect.server/utils/identity.ts generates a name and color for each client, replaceable with an authenticated user for production.pnpm dlx shadcn@latest init -b base.npx giget@latest gh:vercel/examples/websockets/nitro my-realtime-app, then run pnpm install && pnpm dev.ClientMessage and ServerMessage variants to add custom realtime interactions such as chat or drawing.nitro/vite plugin serves the React SPA for unmatched routes while matching server routes like /api/ws first.server/api/ws.ts to build features like shared whiteboards or multi-user forms.A Vercel Function accepts a WebSocket upgrade and keeps the connection open. Nitro v3 enables the feature with one flag in vite.config.ts: nitro({ features: { websocket: true } }). The handler at server/api/ws.ts manages subscriptions, broadcasts with peer.publish, and sends a welcome frame containing the current roster when a client connects.
Yes. The source is part of the vercel/examples repository and is released under the MIT license. Deploying to Vercel uses the Vercel Functions WebSockets beta; there are no paid add-ons or API keys required for the realtime layer.
No. The frontend's use-realtime.ts hook opens a WebSocket directly to /api/ws and parses the custom message types. The only dependency for realtime is the browser's native WebSocket API.
The WebSocket connection closes. The client automatically reconnects with exponential backoff and rebuilds the roster from the welcome frame on each new connection, so the app recovers without manual refresh.
Yes. Replace the anonymous identity logic in server/utils/identity.ts with your authenticated user, and add any token checks you need in the WebSocket handler or upgrade step.
