Documentation Index Fetch the complete documentation index at: https://mintlify.com/homarr-labs/homarr/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Homarr provides a WebSocket server for real-time updates and subscriptions. The WebSocket API uses tRPC over WebSocket, providing the same type-safe interface as the HTTP API.
Connection Details
WebSocket Server: ws://localhost:3001 (default)
Protocol: tRPC WebSocket adapter with SuperJSON serialization
Authentication: Session-based (via cookies) or API key
Architecture
The WebSocket server is a separate process that runs alongside the main Homarr application:
Homarr Web (Port 3000) ←→ WebSocket Server (Port 3001)
↓ ↓
Database ←→ Shared State ←→ Database
Key Features:
Persistent connections for real-time updates
Automatic reconnection on disconnect
Heartbeat/keepalive messages
Same authentication as HTTP API
Full tRPC query/mutation/subscription support
Connecting to WebSocket
Browser Client
import { createWSClient , wsLink } from '@trpc/client' ;
import { createTRPCProxyClient } from '@trpc/client' ;
import type { AppRouter } from '@homarr/api/websocket' ;
import superjson from 'superjson' ;
// Create WebSocket client
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
// Authentication via cookie is automatic in browsers
});
// Create tRPC client
const client = createTRPCProxyClient < AppRouter >({
transformer: superjson ,
links: [
wsLink ({
client: wsClient ,
}),
],
});
// Use the client
const subscription = await client . widget . weather . subscribeAtLocation . subscribe (
{ latitude: 40.7128 , longitude: - 74.0060 },
{
onData : ( data ) => {
console . log ( 'Weather update:' , data );
},
},
);
Node.js Client
import { WebSocket } from 'ws' ;
import { createWSClient , wsLink } from '@trpc/client' ;
import { createTRPCProxyClient } from '@trpc/client' ;
import superjson from 'superjson' ;
// Create WebSocket client with authentication
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
WebSocket: WebSocket ,
connectionParams : async () => {
return {
// Include session token in connection
sessionToken: 'your-session-token' ,
};
},
});
const client = createTRPCProxyClient ({
transformer: superjson ,
links: [ wsLink ({ client: wsClient })],
});
Connection Lifecycle
Connection Events
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
onOpen : () => {
console . log ( '✅ WebSocket connected' );
},
onClose : () => {
console . log ( '❌ WebSocket disconnected' );
},
});
Heartbeat
The server sends ping messages every 30 seconds to keep the connection alive:
Ping interval: 30,000ms
Pong timeout: 5,000ms
Connection terminated if pong not received
Automatic Reconnection
The tRPC WebSocket client automatically attempts to reconnect:
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
retryDelayMs : ( attemptCount ) => {
// Exponential backoff
return Math . min ( 1000 * Math . pow ( 2 , attemptCount ), 30000 );
},
});
Authentication
Cookie-Based (Browser)
In browsers, session cookies are automatically sent:
// No special authentication needed - cookies sent automatically
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
});
Manual Session Token (Node.js)
For server-side connections, include the session token:
import { parseCookies } from '@homarr/common' ;
const cookies = parseCookies ( cookieHeader );
const sessionToken = cookies [ 'next-auth.session-token' ];
const ws = new WebSocket ( 'ws://localhost:3001' , {
headers: {
Cookie: `next-auth.session-token= ${ sessionToken } ` ,
},
});
API Key Authentication
API keys are not directly supported over WebSocket. Use session-based authentication instead.
Error Handling
Connection Errors
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
onClose : ( cause ) => {
console . error ( 'Connection closed:' , cause );
// Handle reconnection or notify user
},
onError : ( error ) => {
console . error ( 'WebSocket error:' , error );
},
});
Subscription Errors
const subscription = client . widget . weather . subscribeAtLocation . subscribe (
{ latitude: 40.7128 , longitude: - 74.0060 },
{
onData : ( data ) => {
console . log ( 'Data:' , data );
},
onError : ( error ) => {
console . error ( 'Subscription error:' , error );
if ( error . code === 'UNAUTHORIZED' ) {
// Redirect to login
}
},
},
);
Connection Pooling
Reuse WebSocket connections across your application:
// Create a single WebSocket client
export const wsClient = createWSClient ({
url: WS_URL ,
});
// Create a single tRPC client
export const wsApi = createTRPCProxyClient ({
transformer: superjson ,
links: [ wsLink ({ client: wsClient })],
});
// Use throughout your app
import { wsApi } from './api' ;
Subscription Management
Unsubscribe when components unmount:
useEffect (() => {
const subscription = wsApi . widget . weather . subscribeAtLocation . subscribe (
{ latitude , longitude },
{
onData: setWeather ,
},
);
return () => {
subscription . unsubscribe ();
};
}, [ latitude , longitude ]);
Message Batching
tRPC automatically batches messages when possible to reduce overhead.
Debugging
Enable Debug Logging
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
onOpen : () => console . log ( 'Connection opened' ),
onClose : ( cause ) => console . log ( 'Connection closed:' , cause ),
});
Monitor Connection State
const [ connectionState , setConnectionState ] = useState < 'connecting' | 'connected' | 'disconnected' >( 'connecting' );
const wsClient = createWSClient ({
url: 'ws://localhost:3001' ,
onOpen : () => setConnectionState ( 'connected' ),
onClose : () => setConnectionState ( 'disconnected' ),
});
Server Logs
The WebSocket server logs connection events:
✅ WebSocket Server listening on ws://localhost:3001
➕ Connection (1) GET /
➖ Connection (0) 1000 Normal Closure
React Hooks Integration
Use tRPC React Query hooks with WebSocket subscriptions:
import { api } from '~/trpc/react' ;
function WeatherWidget () {
const [ weather , setWeather ] = useState ( null );
// Subscribe to weather updates
api . widget . weather . subscribeAtLocation . useSubscription (
{ latitude: 40.7128 , longitude: - 74.0060 },
{
onData : ( data ) => {
setWeather ( data );
},
},
);
return < div >{weather?. temperature }° </ div > ;
}
Next Steps
WebSocket Events Learn about available WebSocket events and subscriptions
Widget Subscriptions Real-time widget data subscriptions