A Bun-powered real-time WebSocket server implementing the Pusher protocol - a TypeScript port of Laravel Reverb.
Revurb is a complete TypeScript port of Laravel Reverb, designed to run on Bun runtime. It provides a high-performance WebSocket server that implements the Pusher protocol, enabling real-time communication for your applications.
- β WebSocket Server - Native Bun WebSocket support with TLS/SSL
- β Pusher Protocol - Full Pusher protocol implementation
- β Channel Management - Public, private, and presence channels
- β HTTP API - RESTful API for server management and event triggering
- β Redis Pub/Sub - Production-ready Redis integration using ioredis for multi-server deployments
- β Authentication - Application key/secret validation
- β Event System - Comprehensive event dispatching
- β Connection Management - Lifecycle management and pruning
- β CLI Interface - Full command-line interface
- β Health Checks - Built-in health monitoring
- Bun >= 1.3.2
- Node.js 18+ (for Bun)
# Clone the repository
git clone https://github.com/tomnagengast/revurb
cd revurb
# Install dependencies
bun install
# Build the project
bun run build# Development mode with watch
bun run dev
# Production mode
bun run start
# Or directly
bun run packages/revurb/src/cli.ts start --host=127.0.0.1 --port=8080Create a configuration file or use environment variables:
// reverb.config.ts
export default {
default: "reverb",
servers: {
reverb: {
host: "127.0.0.1",
port: 8080,
path: "",
},
},
apps: {
provider: "config",
apps: [
{
app_id: "your-app-id",
key: "your-app-key",
secret: "your-app-secret",
allowed_origins: ["*"],
ping_interval: 60,
activity_timeout: 30,
},
],
},
};REVERB_SERVER_HOST- Server host (default: 127.0.0.1)REVERB_SERVER_PORT- Server port (default: 8080)REVERB_SERVER_PATH- WebSocket pathREVERB_APP_ID- Application IDREVERB_APP_KEY- Application keyREVERB_APP_SECRET- Application secretREVERB_ALLOWED_ORIGINS- Allowed origins (comma-separated)
Revurb can be embedded in your application using the createServer function:
import { createServer } from 'revurb';
// Create server with inline config
const { server, shutdown } = await createServer({
config: {
default: "reverb",
servers: {
reverb: {
host: "127.0.0.1",
port: 8080,
},
},
apps: {
provider: "config",
apps: [{
app_id: "my-app-id",
key: "my-app-key",
secret: "my-app-secret",
}],
},
},
});
console.log(`Server running on port ${server.port}`);
// Gracefully shutdown when done
await shutdown();Options:
config- Config object (takes precedence over configPath)configPath- Path to config file to loadserverName- Server name to use (overrides config.default)host- Host overrideport- Port override (string or number)path- Path prefix overridehostname- Hostname overridemaxRequestSize- Max request size overrideenableEventLogging- Enable debug event logging (default: false)enableJobs- Enable periodic jobs for ping/prune (default: false)enableSignals- Enable signal handlers for graceful shutdown (default: false)
Load config from file:
const { server, shutdown } = await createServer({
configPath: './reverb.config.ts',
enableJobs: true,
enableSignals: true,
});Override configuration:
const { server, shutdown } = await createServer({
configPath: './reverb.config.ts',
host: '0.0.0.0',
port: 9090,
path: '/ws',
});Multiple isolated servers:
Each call to createServer followed by shutdown resets internal state, allowing you to create multiple isolated server instances:
// First server
const server1 = await createServer({ config: config1 });
await server1.shutdown();
// Second server with different config
const server2 = await createServer({ config: config2 });
await server2.shutdown();Revurb includes a complete example chat application demonstrating real-time WebSocket communication. The example shows how to:
- Programmatically embed Revurb using
createServer - Connect to the Revurb WebSocket server
- Subscribe to channels
- Send and receive client events
- Handle ping/pong heartbeats
- Switch between channels
The example embeds Revurb directly in the same process as the frontend dev server, demonstrating how to use the createServer API programmatically.
To run the example:
cd apps/demo
bun install
bun run devThis single command starts both:
- Revurb WebSocket server on
ws://0.0.0.0:8080with app keymy-app-key - Frontend dev server with hot module reloading
The example app will be available at the URL shown in the console output (typically http://localhost:3000). Both servers run in the same process and shut down together gracefully.
# Run all tests
bun test
# Run tests in watch mode
bun test:watch
# Type check
bun run typecheckRevurb includes Autobahn WebSocket Testsuite integration to validate protocol compliance:
# Run Autobahn spec tests
docker run -it --rm \
--platform linux/amd64 \
--network host \
-v "${PWD}/tests/spec:/config" \
-v "${PWD}/tests/spec/reports:/mnt/autobahn/reports" \
crossbario/autobahn-testsuite \
wstest -m fuzzingclient -s /config/client-spec.jsonThe spec tests validate WebSocket protocol compliance including frame handling, UTF-8 validation, and binary message support.
revurb/
βββ apps/
β βββ demo/ # Example chat application
βββ packages/
β βββ echo/ # @revurb/echo package (Pusher client)
β βββ revurb/ # @revurb/revurb package (WebSocket server)
β βββ src/
β β βββ protocols/ # Pusher protocol implementation
β β βββ servers/ # Server factory and HTTP handling
β β βββ events/ # Event system
β β βββ loggers/ # Logging implementations
β β βββ contracts/ # TypeScript interfaces
β β βββ cli.ts # CLI entry point
β βββ tests/
β β βββ e2e/ # End-to-end tests
β β βββ feature/ # Feature tests
β β βββ spec/ # WebSocket protocol spec tests
β β βββ unit/ # Unit tests
β βββ dist/ # Compiled output
GET /up- Health checkPOST /apps/{appId}/events- Trigger single eventPOST /apps/{appId}/batch_events- Trigger batch eventsGET /apps/{appId}/channels- List channelsGET /apps/{appId}/channels/{channel}- Channel infoGET /apps/{appId}/channels/{channel}/users- Channel users (presence)GET /apps/{appId}/connections- List connectionsPOST /apps/{appId}/users/{userId}/terminate_connections- Terminate user connections
Revurb implements the Pusher WebSocket protocol. Connect using:
wss://your-server:8080/app/your-app-key?protocol=7&client=js&version=8.4.0
# Format code
bun run format
# Lint code
bun run lint
# Fix linting issues
bun run lint:fix
# Clean build artifacts
bun run cleanRevurb includes comprehensive automated testing through GitHub Actions:
- Unit/Feature/E2E Tests - Full test suite runs on every push with Redis service for integration testing
- WebSocket Protocol Compliance - Autobahn Testsuite validates protocol conformance against Pusher spec
- Example Integration - Smoke tests ensure
createServerAPI and example app work end-to-end - Static Analysis - TypeScript checking and linting on all branches
- Code Formatting - Automatic formatting fixes on main branch
All workflows run on push to main and on pull requests, ensuring every change is validated before merge.
This is a complete TypeScript port of Laravel Reverb. All core functionality has been ported and tested:
- β 89 tests passing (100%)
- β 0 TypeScript compilation errors
- β All core features implemented
- β Production ready for multi-server deployments
- β Redis Pub/Sub: Full production-ready Redis integration using ioredis with TLS support, automatic reconnection, and event queueing
The following Laravel framework-specific components were intentionally not ported:
- Service Providers (Laravel DI container)
- Laravel Artisan Commands
- Laravel Pulse Integration
- Livewire Components
MIT License - see LICENSE.md for details.
Port of Laravel Reverb to TypeScript/Bun.