Quick Start Configuration HTTP API SDKs

Getting Started

Get Relay running and publishing your first real-time event in under 5 minutes.

Prerequisites

You'll need Docker (recommended) or Go 1.22+ to run the server, a backend framework (Laravel, Node.js, Rails, or Django), and a browser-based frontend for the JS client.

1 Run the Server

Docker (recommended)

bash
docker run -d -p 6001:6001 \
  -e RELAY_APP_KEY=my-key \
  -e RELAY_APP_SECRET=my-secret \
  relayhq/relay:latest

Download the binary

Download the latest release for your platform from the releases page, then run:

bash
RELAY_APP_KEY=my-key RELAY_APP_SECRET=my-secret ./relay

Build from source

bash
git clone https://github.com/DarkNautica/Relay.git
cd Relay/relay-server
go build -o relay ./main.go
RELAY_APP_KEY=my-key RELAY_APP_SECRET=my-secret ./relay

The server starts on port 6001 by default. The built-in dashboard is at http://localhost:6001/dashboard.

2 Connect the JavaScript Client

bash
npm install @relayhq/relay-js
js
import Relay from '@relayhq/relay-js'

const relay = new Relay('my-key', {
  host: 'localhost',
  port: 6001,
  logToConsole: true,  // helpful during development
})

// Monitor connection state
relay.connection.bind('connected', () => {
  console.log('Connected! Socket ID:', relay.connection.socket_id)
})

// Subscribe to a channel and listen for events
const channel = relay.subscribe('chat')

channel.bind('new-message', (data) => {
  console.log('New message:', data.text)
})

// Debug: log all events on this channel
channel.bindAll(({ event, data }) => {
  console.log(`Event: ${event}`, data)
})

3 Publish from Your Backend

Choose your framework:

bash
composer require relayhq/relay-php
php
// config/broadcasting.php
'default' => 'relay',
'connections' => [
    'relay' => [
        'driver'  => 'relay',
        'host'    => env('RELAY_HOST', '127.0.0.1'),
        'port'    => env('RELAY_PORT', 6001),
        'key'     => env('RELAY_APP_KEY'),
        'secret'  => env('RELAY_APP_SECRET'),
        'app_id'  => env('RELAY_APP_ID'),
    ],
],
php
// Publish an event
broadcast(new MessageSent($message));
bash
npm install @relayhq/relay-node
js
import { RelayClient } from '@relayhq/relay-node'

const relay = new RelayClient({
  host: '127.0.0.1',
  port: 6001,
  appId: 'my-app',
  key: 'my-key',
  secret: 'my-secret',
})

await relay.publish('chat', 'new-message', { text: 'Hello!' })
ruby
# Gemfile
gem 'relay-ruby'
yaml
# config/cable.yml
production:
  adapter: relay
  host: 127.0.0.1
  port: 6001
  app_id: my-app
  key: my-key
  secret: my-secret
ruby
# Publish
ActionCable.server.broadcast('chat', { text: 'Hello!' })
bash
pip install relay-python
python
from relay import RelayClient

relay = RelayClient(
    host='127.0.0.1',
    port=6001,
    app_id='my-app',
    key='my-key',
    secret='my-secret',
)

relay.publish('chat', 'new-message', {'text': 'Hello!'})

4 Private Channels

Private channels require server-side authentication. The channel name must start with private-.

js
// Client side — subscribe to a private channel
const orders = relay.subscribe('private-orders.42')
orders.bind('update', (data) => console.log('Order update:', data))

The JS client will automatically POST to your auth endpoint (/broadcasting/auth by default). Your backend verifies the user and returns a signed token.

5 Presence Channels

Presence channels track which users are online. The channel name must start with presence-.

js
const room = relay.subscribe('presence-room.1')

// Fires when subscription succeeds with the initial member list
room.bind('relay:subscription_succeeded', (data) => {
  console.log('Members online:', data.presence.count)
})

// Fires when a new member joins
room.bind('relay:member_added', (member) => {
  console.log(`${member.info.name} joined`)
})

// Fires when a member leaves
room.bind('relay:member_removed', (member) => {
  console.log(`${member.info.name} left`)
})

Your auth endpoint must return channel_data containing the user's ID and info for presence channels. All server SDKs handle this automatically.

Common Issues

1. BROADCAST_CONNECTION vs BROADCAST_DRIVER

Laravel 11+ renamed the environment variable from BROADCAST_DRIVER to BROADCAST_CONNECTION. Make sure you set the correct one in your .env:

env
# Laravel 11+
BROADCAST_CONNECTION=relay

# Laravel 10 and below
BROADCAST_DRIVER=relay

2. CSRF Exemption for /broadcasting/auth

The /broadcasting/auth endpoint must be excluded from CSRF verification. Without this, private and presence channel authentication will fail with a 419 status code.

Laravel 11+ — in bootstrap/app.php:

php
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'broadcasting/auth',
    ]);
})

Laravel 10 and below — in app/Http/Middleware/VerifyCsrfToken.php:

php
protected $except = [
    'broadcasting/auth',
];

3. Event Name Prefixes

The Relay JS client uses relay: prefixed internal events (e.g. relay:subscription_succeeded, relay:member_added). If you are migrating from Pusher, note that the client automatically handles both relay: and pusher: prefixed events, so no changes are needed in your event listeners.

When binding to channel events in your frontend code, use the relay: prefix:

js
channel.bind('relay:subscription_succeeded', (data) => { /* ... */ })
channel.bind('relay:member_added', (member) => { /* ... */ })
channel.bind('relay:member_removed', (member) => { /* ... */ })