LogoRobo.js

Server API

Direct server-side state manipulation with SyncServer.

Access and manipulate sync state from the server side. SyncServer provides zone handles for reading/writing state, overriding hosts, and sending messages -- useful in API routes, bot events, cron jobs, or any server-side code.

SyncServer

Import from @robojs/sync/server:

import { SyncServer } from '@robojs/sync/server'
import { SyncServer } from '@robojs/sync/server'
MethodDescription
start()Start the WebSocket server (called automatically on Robo startup)
getSocketServer()Get the underlying ws.WebSocketServer instance
getZone(key)Get a zone handle for direct state manipulation

Server zones

Get a zone handle to read and write state from the server.

const zone = SyncServer.getZone<GameState>(['game', 'room1'])
const zone = SyncServer.getZone(['game', 'room1'])
MethodSignatureDescription
getState()() => T | undefinedGet current state
setState(data)(data: T) => voidSet state and broadcast to all subscribers
setHost(clientId)(clientId: string | null) => voidOverride host (null clears)
getHost()() => string | undefinedGet current host ID
getClients()() => Client[]Get all subscribed clients
broadcast(payload)(payload: unknown) => voidBroadcast to all subscribers
send(clientId, payload)(clientId: string, payload: unknown) => voidSend to specific client

Reading state

const zone = SyncServer.getZone(['game', 'room1'])
const state = zone.getState()
const host = zone.getHost()
const clients = zone.getClients()

console.log('State:', state)
console.log('Host:', host)
console.log('Players:', clients.length)
const zone = SyncServer.getZone(['game', 'room1'])
const state = zone.getState()
const host = zone.getHost()
const clients = zone.getClients()

console.log('State:', state)
console.log('Host:', host)
console.log('Players:', clients.length)

Writing state

Updates broadcast automatically to all subscribed clients.

const zone = SyncServer.getZone(['game', 'room1'])

zone.setState({
	phase: 'playing',
	round: 2,
	startedAt: Date.now()
})
const zone = SyncServer.getZone(['game', 'room1'])

zone.setState({
	phase: 'playing',
	round: 2,
	startedAt: Date.now()
})

Host management

Override or clear the host. Useful for admin actions or automated game management.

const zone = SyncServer.getZone(['game', 'room1'])

// Assign host
zone.setHost('client-abc')

// Clear host
zone.setHost(null)
const zone = SyncServer.getZone(['game', 'room1'])

// Assign host
zone.setHost('client-abc')

// Clear host
zone.setHost(null)

setHost verifies the target client is subscribed to the key. If the client isn't subscribed, the operation is silently ignored with a warning log.

Sending messages

Server broadcasts arrive on the client with client.id === '__server__'.

const zone = SyncServer.getZone(['game', 'room1'])

// Broadcast to all subscribers
zone.broadcast({ event: 'countdown', seconds: 5 })

// Send to specific client
zone.send('client-abc', { message: 'You win' })
const zone = SyncServer.getZone(['game', 'room1'])

// Broadcast to all subscribers
zone.broadcast({ event: 'countdown', seconds: 5 })

// Send to specific client
zone.send('client-abc', { message: 'You win' })

Client-side handling:

useSyncBroadcast((payload, { client }) => {
	if (client.id === '__server__') {
		console.log('Server says:', payload)
	}
}, ['game', 'room1'])
useSyncBroadcast((payload, { client }) => {
	if (client.id === '__server__') {
		console.log('Server says:', payload)
	}
}, ['game', 'room1'])

Use cases

API route integration

src/api/game/reset.ts
import { SyncServer } from '@robojs/sync/server'

export default function handler(req, res) {
	const zone = SyncServer.getZone(['game', req.query.roomId])
	zone.setState({ score: 0, phase: 'lobby' })
	zone.broadcast({ type: 'game_reset' })
	return { success: true }
}
src/api/game/reset.js
import { SyncServer } from '@robojs/sync/server'

export default function handler(req, res) {
	const zone = SyncServer.getZone(['game', req.query.roomId])
	zone.setState({ score: 0, phase: 'lobby' })
	zone.broadcast({ type: 'game_reset' })
	return { success: true }
}

Cron job

src/robo/start.ts
import { SyncServer } from '@robojs/sync/server'

export default () => {
	setInterval(() => {
		const zone = SyncServer.getZone(['dashboard', 'stats'])
		zone.setState({
			serverTime: Date.now(),
			uptime: process.uptime()
		})
	}, 5000)
}
src/robo/start.js
import { SyncServer } from '@robojs/sync/server'

export default () => {
	setInterval(() => {
		const zone = SyncServer.getZone(['dashboard', 'stats'])
		zone.setState({
			serverTime: Date.now(),
			uptime: process.uptime()
		})
	}, 5000)
}

Raw WebSocket access

For advanced scenarios, access the underlying ws.WebSocketServer:

const wss = SyncServer.getSocketServer()
if (wss) {
	console.log('Connected clients:', wss.clients.size)
}
const wss = SyncServer.getSocketServer()
if (wss) {
	console.log('Connected clients:', wss.clients.size)
}

Next Steps

On this page