A real-time collaborative map application built with a WebSocket backend (Bun + TypeScript) and a React frontend (Vite + TypeScript + Mapbox GL).
This repository contains two projects:
socketMapsBackend→ WebSocket server that manages connected clients and broadcasts live position updates.socketMapsFrontend→ Web UI that connects to the socket server and renders users as markers on a Mapbox map.
Socket Maps lets multiple users connect to the same map session and see each other in real time.
Main flow:
- A user enters a name and color in the frontend.
- The frontend stores that info in cookies and opens a WebSocket connection.
- The backend reads user info from cookies during the socket upgrade.
- On connect, the backend:
- registers the client,
- sends a
WELCOMEmessage to that client, - sends current
CLIENT_STATE, - broadcasts
CLIENT_JOINto others.
- While dragging a marker, the frontend sends
CLIENT_MOVEmessages. - The backend broadcasts movement and disconnection events (
CLIENT_MOVE,CLIENT_LEFT).
socketMapsBackend/- Bun WebSocket server
- Validation with Zod
- In-memory client store (Map)
socketMapsFrontend/- React 19 + Vite 7 + TypeScript
- Map rendering with
mapbox-gl - WebSocket context/provider for realtime communication
- Runtime: Bun
- Language: TypeScript
- Transport: Native WebSocket support via
Bun.serve - Validation: Zod
- Architecture: handlers + services + store
- Framework: React 19
- Bundler/Dev Server: Vite 7
- Language: TypeScript
- Maps: Mapbox GL JS
- State/Realtime: React Context + WebSocket API
- Cookies: js-cookie
- Bun installed (used by both projects in this repo)
- Node.js (optional but useful for tooling compatibility)
- A Mapbox token for the frontend (
VITE_MAPS_KEY)
The backend README indicates an .env should be created from .env.template.
Based on the code, these are used:
PORT(default:3000if missing)DEFAULT_CHANNEL(default:default-channelif missing)
Note: the frontend currently connects to
ws://localhost:3200, so set backendPORT=3200(or update frontend URL).
VITE_MAPS_KEY=your_mapbox_public_token
Open two terminals from the repository root.
cd socketMapsBackend
bun install
bun run dev
Recommended .env example:
PORT=3200
DEFAULT_CHANNEL=default-channel
cd socketMapsFrontend
bun install
bun run dev
Then open the local URL printed by Vite (usually http://localhost:5173).
bun run dev→ run server with hot reloadbun run start→ run server normally
bun run dev→ start Vite dev serverbun run build→ type-check + production buildbun run preview→ preview production buildbun run lint→ run ESLint
GET_CLIENTSCLIENT_REGISTERCLIENT_MOVECLIENT_LEFT
WELCOMECLIENT_STATECLIENT_JOINCLIENT_MOVECLIENT_LEFTERROR
- Client state is currently stored in memory on the backend (no database).
- Authentication is not implemented.
- Cookies (
name,color,coords) are required by the backend during WebSocket upgrade. - There is a small port mismatch by default (
backenddefaults to 3000,frontendpoints to 3200), so align them before running.
Socket Maps permite que varios usuarios se conecten a un mismo mapa y vean posiciones en tiempo real.
Flujo principal:
- El usuario completa nombre y color en el frontend.
- El frontend guarda esos datos en cookies y abre una conexión WebSocket.
- El backend lee las cookies durante el upgrade del socket.
- Al conectar, el backend:
- registra al cliente,
- envía
WELCOMEal cliente nuevo, - envía
CLIENT_STATEcon el estado actual, - publica
CLIENT_JOINal resto.
- Mientras se arrastra el marcador, el frontend envía
CLIENT_MOVE. - El backend publica movimientos y salidas (
CLIENT_MOVE,CLIENT_LEFT).
socketMapsBackend/- Servidor WebSocket con Bun
- Validación con Zod
- Store en memoria con
Map
socketMapsFrontend/- React 19 + Vite 7 + TypeScript
- Mapa con
mapbox-gl - Contexto WebSocket para comunicación en tiempo real
- Runtime: Bun
- Lenguaje: TypeScript
- WebSocket:
Bun.serve - Validación: Zod
- Patrón: handlers + services + store
- Framework: React 19
- Build/Dev server: Vite 7
- Lenguaje: TypeScript
- Mapas: Mapbox GL JS
- Tiempo real: React Context + WebSocket nativo
- Cookies: js-cookie
- Bun instalado
- Node.js (opcional, recomendado para tooling)
- Token de Mapbox para el frontend (
VITE_MAPS_KEY)
Según el proyecto, se crea desde .env.template.
Variables usadas por el código:
PORT(por defecto:3000)DEFAULT_CHANNEL(por defecto:default-channel)
Importante: el frontend apunta a
ws://localhost:3200, por lo que conviene usarPORT=3200o cambiar esa URL en frontend.
VITE_MAPS_KEY=tu_token_publico_de_mapbox
Abrí dos terminales en la raíz del repo.
cd socketMapsBackend
bun install
bun run dev
Ejemplo recomendado de .env:
PORT=3200
DEFAULT_CHANNEL=default-channel
cd socketMapsFrontend
bun install
bun run dev
Después abrí la URL local que imprime Vite (normalmente http://localhost:5173).
bun run dev→ servidor con hot reloadbun run start→ ejecución normal
bun run dev→ servidor de desarrollobun run build→ type-check + build de producciónbun run preview→ previsualizar buildbun run lint→ ejecutar ESLint
GET_CLIENTSCLIENT_REGISTERCLIENT_MOVECLIENT_LEFT
WELCOMECLIENT_STATECLIENT_JOINCLIENT_MOVECLIENT_LEFTERROR
- El estado de clientes está en memoria (sin base de datos).
- No hay autenticación implementada.
- Las cookies (
name,color,coords) son necesarias para conectar. - Hay un desajuste de puerto por defecto (backend 3000 vs frontend 3200): alinearlo antes de correr.