Files
recflare/README.md
T
2026-06-29 23:48:29 -04:00

191 lines
11 KiB
Markdown

# RecFlare
RecFlare is an implementation of RecNet — the Rec Room backend — built on
Cloudflare Workers. It implements the network services the Rec Room client talks
to — accounts, auth, rooms, matchmaking, economy, chat, notifications, and more —
each as an independent Worker on its own subdomain.
> **Disclaimer:** This is an unofficial, fan-made project for preservation and
> experimentation. It is not affiliated with, endorsed by, or connected to Rec
> Room Inc. "Rec Room" is a trademark of its respective owner.
## Client
RecFlare is compatible with the
[CannedNet client](https://github.com/CannedNet/CannedNet) and the build of Rec
Room with manifest `7859140924515540835`. Other client or game versions expect
different endpoints and response shapes and are not supported.
## How it works
The Rec Room client discovers every service by fetching an _endpoints document_
from the name-server (`ns`) worker at the apex domain. That document maps each
service to a host like `https://api.<your-domain>`. Every service runs as a
separate Cloudflare Worker attached to its own subdomain, so the client's traffic
fans out across the workers in `apps/`.
Authentication is a Bearer-JWT flow: the `auth` worker issues tokens from
`/connect/token` and owns the shared `accounts` table; every other worker
validates that token on its auth-gated routes. New players are placed into the
Orientation room on first login.
State is persisted with Cloudflare's storage primitives — D1 (SQLite) for
accounts and rooms, KV for per-player settings and presence, R2 for images and
CDN binaries, and a Durable Object for the real-time notifications hub. Endpoints
that aren't backed by storage yet return sensible defaults and are marked
`TODO`.
## Services
These are every RecNet service the client discovers, taken from the
service-discovery map in [`apps/ns/src/endpoints.ts`](apps/ns/src/endpoints.ts).
Each is reached at `https://<subdomain>.<your-domain>`. Services with a worker in
`apps/` are implemented here; the rest are advertised in the endpoints document
but not yet backed by a Worker.
| Service | Subdomain | Worker | Notes |
| ----------------------- | ----------------------- | ------------------ | ----------------------------------------------------------------- |
| Accounts | `accounts` | `accounts` | Player accounts & profile reads/writes (D1) |
| AI | `ai` | — | Not yet implemented |
| API | `api` | `api` | Core Game API — config, social, avatar, rooms, image uploads (D1, R2) |
| Auth | `auth` | `auth` | OAuth token issuance (`/connect/token`); owns the accounts table (D1, KV) |
| BugReporting | `bugreporting` | — | Not yet implemented |
| Cards | `cards` | — | Not yet implemented |
| CDN | `cdn` | `cdn` | Binary CDN — signature blobs & room build data (R2) |
| Chat | `chat` | `chat` | Chat service |
| Clubs | `clubs` | `clubs` | Clubs |
| CMS | `cms` | — | Not yet implemented |
| Commerce | `commerce` | `commerce` | Store / purchase endpoints |
| Data | `data` | — | Not yet implemented |
| DataCollection | `datacollection` | `datacollection` | Client telemetry / analytics sink |
| Discovery | `discovery` | — | Not yet implemented |
| Econ | `econ` | `econ` | Economy & avatar endpoints (separate from `api`) |
| GameLogs | `gamelogs` | — | Not yet implemented |
| Geo | `geo` | — | Not yet implemented |
| Images | `img` | `img` | Image storage & signed delivery (R2) |
| Leaderboard | `leaderboard` | — | Not yet implemented |
| Link | `link` | — | Not yet implemented |
| Lists | `lists` | — | Not yet implemented |
| Matchmaking | `match` | `match` | Matchmaking & per-player presence (D1, KV) |
| Moderation | `api` | `api` | Served by the `api` worker (shares the API host) |
| Notifications | `notify` | `notify` | Real-time notifications over SignalR/WebSockets (Durable Object) |
| PlatformNotifications | `platformnotifications` | — | Not yet implemented |
| PlayerSettings | `playersettings` | `playersettings` | Per-player settings (KV) |
| RoomComments | `roomcomments` | — | Not yet implemented |
| RoomieIntegrations | `roomieintegrations` | — | Not yet implemented |
| Rooms | `rooms` | `rooms` | Room storage & queries; seeds the Dorm & Orientation rooms (D1) |
| Storage | `storage` | — | Not yet implemented |
| Strings | `strings` | — | Not yet implemented |
| StringsCDN | `strings-cdn` | — | Not yet implemented |
| Studio | `studio` | — | Not yet implemented |
| Thorn | `thorn` | — | Not yet implemented |
| Videos | `videos` | — | Not yet implemented |
| WWW | `www` | — | Website host (not a Worker) |
The `ns` worker itself serves this discovery document at the apex/`ns` host and
isn't listed within it. Each implemented worker has its own `README.md` under
`apps/<name>/` documenting its routes.
## Prerequisites
- node.js v22 or later
- pnpm v10 or later
- bun 1.2 or later
- A Cloudflare account with a zone (domain) you control, for deploying
- shfmt / rg (ripgrep) — optional, recommended for shell formatting
- mise — optional, recommended for tool management
## Getting Started
**Install dependencies:**
```bash
just install
```
**Configure your domain:**
`env.json` is the single source of truth for your base domain; it is gitignored,
so each clone needs its own copy.
```bash
cp env.example.json env.json
# edit env.json and set "domain" to your domain
```
`just deploy` resolves the base domain at deploy time and passes it to wrangler —
each worker is attached to its custom domain via `--domain <subdomain>.<domain>`,
and the base domain is injected as the `DOMAIN` var so the `ns` service-discovery
document and the api share-link base URL are built at runtime. Nothing in version
control is rewritten; committed `wrangler.jsonc` files have no routes.
The domain is read from the `RECFLARE_DOMAIN` environment variable if set,
otherwise from `env.json`. Per-app subdomain overrides come from
`RECFLARE_SUBDOMAINS` (a JSON object, e.g. `{"playersettings":"settings"}`) or
the `subdomains` key in `env.json`. For CI, set `RECFLARE_DOMAIN` as a secret and
skip `env.json` entirely:
```bash
RECFLARE_DOMAIN=rec.example.com just deploy
```
**Run the development server:**
```bash
just dev
```
**Deploy all workers:**
```bash
just deploy
```
Deploying requires `wrangler` to be authenticated against your Cloudflare
account (`wrangler login`, or `CLOUDFLARE_API_TOKEN` / `CLOUDFLARE_ACCOUNT_ID`
in the environment). Storage resources (D1 databases, KV namespaces, R2 buckets)
must be created and their ids set in each worker's `wrangler.jsonc` — see the
inline comments in those files for the exact `wrangler` commands.
## Repository Structure
- `apps/` - The service workers, one deployable Worker per subdirectory. Each has
its own `README.md`, `wrangler.jsonc`, `src/`, and tests.
- `packages/` - Shared libraries and configuration used across the workers.
- `@repo/hono-helpers` - Hono framework utilities (logging, error handling).
- `@repo/tools` - The `runx` CLI and the `bin/` scripts each worker's
package.json delegates to, so build/test/deploy stays consistent.
- `@repo/typescript-config`, `@repo/oxlint-config` - Shared TS and lint config.
- `turbo/generators/` - `turbo gen` templates for scaffolding new workers/packages.
- `Justfile` - Convenient aliases for common development tasks.
- `pnpm-workspace.yaml` - pnpm workspace definition.
- `turbo.jsonc` - Turborepo task graph and caching.
- `.syncpackrc.cjs` - Keeps dependency versions consistent across packages.
## Available Commands
This repository uses a `Justfile`. Run `just` (or `just --list`) to see every
command. Some key ones:
- `just install` - Install all dependencies.
- `just dev` - Start the dev server (context-aware: runs `bun runx dev`).
- `just build` - Build all workers.
- `just test` - Run tests (vitest).
- `just check` - Check code quality: deps, lint, types, format.
- `just fix` - Fix code issues: deps, lint, format, workers-types.
- `just deploy` - Deploy all workers to your domain.
- `just new-worker` (alias: `just gen`) - Scaffold a new service worker.
- `just new-package` - Scaffold a new shared package.
- `just cs` - Create a changeset for versioning.
- `just update deps` - Update dependencies across the monorepo with syncpack.
For a single worker, scope with turbo, e.g. `bun turbo -F api dev`,
`bun turbo -F api test`, or `bun turbo -F api deploy`.
## Why a monorepo?
The services share types, auth logic, and tooling, so keeping them in one repo
keeps those in sync: `pnpm` workspaces share dependencies, `@repo/` packages
share code, Turborepo runs build/test/lint with a single cached task graph, and
cross-service changes land in one atomic commit.