Super simple, type‑safe realtime via Server‑Sent Events (SSE).
CLI (Node):
npx @impulselab/realtime-service --port 8080 --secret "$REALTIME_SECRET"Docker:
docker run \
-p 8080:8080 \
-e REALTIME_SECRET="your-server-secret" \
ghcr.io/impulse-studio/realtime-serviceEndpoints: GET / (SSE stream), POST / (push).
Define your channel → payload map once, share it on client and server:
interface RealtimeTypes {
'this:is:a:channel': { key: string }
}import { createRealtimeClient } from '@impulselab/realtime'
const rc = createRealtimeClient<RealtimeTypes>({
serviceUrl: process.env.SERVICE_URL!
})
// Public subscribe
rc.subscribe('this:is:a:channel', (event) => {
console.log(event.payload.key)
})
// Private subscribe (token) or group (topic)
rc.subscribe('this:is:a:channel', (event) => {
console.log(event.payload.key)
}, { token: 'secret', topic: 'room-42' })
// Unsubscribe helpers
const off = rc.subscribe('this:is:a:channel', () => {})
off()
rc.unsubscribeAll('this:is:a:channel')
rc.unsubscribeAllChannels()import { createServerClient } from '@impulselab/realtime'
const sc = createServerClient<RealtimeTypes>({
serviceUrl: process.env.SERVICE_URL!,
token: process.env.TOKEN!
})
// Public push
await sc.push('this:is:a:channel', { key: 'value' })
// Authenticated push (token)
await sc.push('this:is:a:channel', { key: 'value' }, { tokens: 'secret' })
// Target a topic (room/group)
await sc.push('this:is:a:channel', { key: 'value' }, { topic: 'room-42' })
// Auth + topic together
await sc.push('this:is:a:channel', { key: 'value' }, { tokens: ['secret','other'], topic: 'room-42' })