Backend/Web/2026

Daystar

Open-source meeting space that plays like a game: everyone is a glowing star or planet orbiting a shared sun, moving and chatting in real time.

Daystar — project hero image

Overview

Daystar is a small meeting app that plays like a game. Each person picks a star, planet or ringed planet and moves around a 10,000 px disc of space around a shared sun, chatting with whoever is nearby. The whole world is drawn in code with PixiJS, with no image assets. You share a room link to invite people.

Under the hood it's a real-time multiplayer server in Bun. Every frame on the wire is binary and schema-encoded, and the server scales out as a cluster: an agent places rooms on game servers, rooms can span servers, and overloaded servers hand players off to other servers without the other players noticing. Voice rides the same WebSocket: the host picks up to 8 speakers, and Opus audio (WebCodecs) is relayed inside the 20 Hz snapshot only while someone is talking.

The problem

Video-call grids are a poor fit for casual group hangouts: everyone talks to everyone, and there's no sense of space or of drifting between conversations. Daystar gives a meeting a shared world you can move around in. That requires a real-time server that stays responsive with many people moving at once, and that can grow past one process without splitting a room across machines.

Architecture

The client (PixiJS v8 + Vite) moves the player locally for instant response and sends its position at 20 Hz. It draws everyone else 100 ms in the past, interpolated between snapshots. Game servers run on Bun's native WebSockets and topic pub/sub. They validate speed and world bounds, send a correction when a move is invalid, and broadcast binary delta snapshots at 20 Hz. Positions are UInt16 in 1/20 px steps, so each player costs 7 bytes per snapshot. In cluster mode an agent serves the client and places each room on a server by load. It issues HMAC-signed join tickets and tells overloaded servers to migrate players. Game servers keep a direct WebSocket mesh with each other, so a room that spans servers stays in sync.

PixiJS client → agent (/api/join, signed ticket) → Bun game servers ⇄ server mesh
PixiJS client → agent (/api/join, signed ticket) → Bun game servers ⇄ server meshOpen interactive diagram ↗

Highlights

  • —Binary protocol end to end Every frame is an opcode plus a body laid out by a shared schema encoder, so a player costs 7 bytes per snapshot and the client and server can't drift apart.
  • —Rooms that span servers An agent places rooms by load. When a room outgrows one server, servers sync it directly over a mesh, and cross-server visibility adds at most one tick.
  • —Seamless player migration An overloaded server hands players to another. The client reconnects with a new ticket before closing its old socket, and nobody else in the room sees a leave or join.
  • —Built-in load testing A load-test tool ramps up bots that walk and chat, and reports CPU, event-loop delay, move latency and bandwidth for each step. On a development machine, one server process held about 5,000 players (rooms of 1,000, 20% walking) with delays under 50 ms.

Screenshots

Daystar — screenshot 1 of 2Daystar — screenshot 2 of 2
Next project
Real-time Game Server Platform →
All projects