A high-performance, real-time, anonymous proximity chat backend designed to connect users in nearby geographic locations. This backend is built to power the CHATRAT frontend (e.g., chatrat.html) and is designed to run with zero-cost hosting on Cloudflare's serverless stack.
- Anonymous Sessions: Handle-only sessions without the friction of a formal login.
- Proximity-Based Chat Rooms: Interactive chat rooms created around geographic coordinates (defaulting to a 10km radius) with a automatic 4-hour room expiry.
- Real-Time Communication: Bi-directional real-time messaging, join/leave events, and live typing indicators powered by WebSockets.
- Zero-Cost Friendly Stack: Built on top of Cloudflare Workers, Durable Objects, and Cloudflare D1 (SQLite).
- Cloudflare Workers: Serverless compute platform hosting the REST API endpoints.
- Durable Objects: State-maintaining serverless actors, maintaining one dedicated WebSocket "room server" per active chat room to coordinate real-time connections.
- Cloudflare D1 (SQLite): Serverless SQL database managing room listings and historical message logs.
- TypeScript: Fully typed codebase for server stability and clear data contract modeling.
/v1
Create or resume an anonymous, handle-only session.
- Path:
POST /session - Request Body:
{ "handle": "streetrat_99", "deviceId": "optional-stable-id" } - Response (Success):
{ "ok": true, "data": { "token": "string", "tokenExpiresAt": "string (ISO Timestamp)", "userId": "string", "handle": "streetrat_99" } }
Query chat rooms within a specific geographic range.
- Path:
GET /rooms/nearby - Query Parameters:
lat(float, required) — Latitude of the userlng(float, required) — Longitude of the userradiusKm(integer, optional) — Search radius (default is10km)
- Response (Success):
{ "ok": true, "data": [ { "id": "string", "name": "Chai Gang ☕", "topic": "Morning vibes", "distanceKm": 1.2, "liveCount": 5 } ] }
Create a new localized chat room. Authentication Required.
- Path:
POST /rooms - Headers:
Authorization: Bearer <token> - Request Body:
{ "name": "Chai Gang ☕", "topic": "Morning vibes", "lat": 29.15, "lng": 75.72 }
Retrieve historical messages from a room before a specific timeline cursor.
- Path:
GET /rooms/:roomId/messages - Query Parameters:
limit(integer, optional) — Number of messages to fetch (default/max:50)before(string, ISO Timestamp, required) — Cursor timestamp for fetching older messages
Retrieve new messages since a specific timeline cursor (used as a backup to WebSockets).
- Path:
GET /rooms/:roomId/messages - Query Parameters:
limit(integer, optional) — Number of messages to fetch (default/max:50)after(string, ISO Timestamp, required) — Cursor timestamp for fetching newer messages
To establish a live connection to a room, initiate a WebSocket connection to:
wss://<your-domain>/v1/rooms/<roomId>/ws?token=<token>
Clients can transmit JSON-formatted events over the WebSocket connection:
{
"type": "typing",
"isTyping": true
}{
"type": "message",
"body": "hello"
}The server pushes structured real-time events to connected clients. Detailed interfaces can be verified in src/types.ts.
room_state— Sent immediately upon connection to sync current room detailsmember_joined— Broadcasted when a new user joins the roommember_left— Broadcasted when a user disconnects or leaves the roomtyping— Informs clients of user typing status changesmessage— Relays a newly posted chat messagesystem— System-generated notificationserror— Informational or connection errors
- Node.js (LTS version recommended)
- npm package manager
-
Clone and Install Dependencies:
npm install
-
Configure Environment Variables: Copy the example environment file:
cp .dev.vars.example .dev.vars
Open
.dev.varsand set theSESSION_SECRETvariable to any secure string of your choice. -
Database Initialization: Initialize your local Cloudflare D1 SQLite database instance:
npx wrangler d1 create chatrat-db
Run the local database migrations to set up the database schema:
npm run db:migrate:local
Copy the printed
database_idfrom the output and update yourwrangler.tomlconfiguration file under the[[d1_databases]]section. -
Start the Development Server: Launch the local wrangler server:
npm run dev
To deploy the backend to Cloudflare's serverless infrastructure:
- Sign Up/In: Ensure you have a free Cloudflare account.
- Authenticate Wrangler: Login using the CLI tool:
npx wrangler login
- Provision Production D1 Database:
npx wrangler d1 create chatrat-db
- Configure Database ID: Update your production
wrangler.tomlfile under the[[d1_databases]]section with the printeddatabase_id. - Apply Remote Migrations: Build and migrate the production SQLite tables:
npm run db:migrate:remote
- Set Production Secrets: Securely inject the
SESSION_SECRETtoken:npx wrangler secret put SESSION_SECRET
- Deploy: Compile and publish your serverless worker live to Cloudflare:
npm run deploy
The backend enforces basic defensive safety boundaries at the edge:
- REST Endpoints: Geographic IP-based rate limiting on
/sessionand/roomscreation. - WebSocket Gateway: Connection limits per-IP, message frequency rate limits per-user, and enforced maximum message lengths.
If automated spam becomes a threat:
- Integrate a Turnstile widget onto your frontend to obtain a
turnstileToken. - Send the token inside the payload of your
POST /v1/roomsrequests and/or verify it during the WebSocket messaging handshakes. - The backend validates the integrity of the token against Cloudflare's verification API before allowing writes.
Created by ojalrathee.