Revise README for improved clarity and details

Updated README.md for clarity and accuracy regarding service architecture and configuration instructions.
This commit is contained in:
devin
2026-07-01 12:37:03 -04:00
committed by GitHub
parent 1f189226e9
commit 70aa33a27a
+72 -84
View File
@@ -3,7 +3,7 @@
RecFlare is an implementation of RecNet — the Rec Room backend — built on RecFlare is an implementation of RecNet — the Rec Room backend — built on
Cloudflare Workers. It implements the network services the Rec Room client talks Cloudflare Workers. It implements the network services the Rec Room client talks
to — accounts, auth, rooms, matchmaking, economy, chat, notifications, and more — to — accounts, auth, rooms, matchmaking, economy, chat, notifications, and more —
each as an independent Worker on its own subdomain. each as an independent Worker on their own subdomains, just how RecNet was.
> **Disclaimer:** This is an unofficial, fan-made project for preservation and > **Disclaimer:** This is an unofficial, fan-made project for preservation and
> experimentation. It is not affiliated with, endorsed by, or connected to Rec > experimentation. It is not affiliated with, endorsed by, or connected to Rec
@@ -14,7 +14,7 @@ each as an independent Worker on its own subdomain.
There are already so many multiplayer clones, why? There are already so many multiplayer clones, why?
1. None of them are fully open source (some had leaks of old code). 1. None of them are fully open source (some had leaks of old code).
2. None of them run on microservice architecture. 2. None of them run on microservice architecture, most on a single server.
3. None of them had unit tests. 3. None of them had unit tests.
4. "Upgrading the server" is not sustainable plan for growth. 4. "Upgrading the server" is not sustainable plan for growth.
5. This was fun (sort of). 5. This was fun (sort of).
@@ -35,7 +35,11 @@ RecFlare is compatible with the
Room with manifest `7859140924515540835`. Other client or game versions may expect Room with manifest `7859140924515540835`. Other client or game versions may expect
different endpoints and response shapes and are not supported. different endpoints and response shapes and are not supported.
See the project page for information on how to mod the game to connect to this server. Generally speaking any client that effectively rewrites the nameserver can be used
with this server.
See the above project page for information on how to mod the game to connect to this
server.
## How it works ## How it works
@@ -105,40 +109,54 @@ apex/`ns` host and isn't listed within it. Each implemented worker has its own
## Why Cloudflare? ## Why Cloudflare?
- **It's free to run a lot of services.** Cloudflare Workers' free tier is keyed - **Makes it easy to mirror RecNet**
to usage, not to the number of Workers — so whether you deploy 1 service or all Rec Room's backend is (was) a set of independent microservices, not one big monolith.
36, the baseline cost is the same. You only start paying once usage crosses the Modeling each service as its own isolated Worker keeps RecFlare's structure close to
free-tier limits. the real thing — services scale,
- **It mirrors RecNet's architecture.** Rec Room's backend is a set of
independent microservices, not one monolith. Modeling each service as its own
Worker keeps RecFlare's structure close to the real thing — services scale,
fail, and deploy independently — instead of collapsing everything into a single fail, and deploy independently — instead of collapsing everything into a single
giant server. giant server.
- **It's free/cheap to run a lot of service.**
Cloudflare Workers' free tier is keyed
to usage, not to the number of Workers — so whether you deploy 1 service or all
36, the baseline cost is the same. You only start paying once usage crosses the
free-tier limits. Additionally for development or maybe a private instance, the cost
is near zero when not in use.
- **Bundled Cloud CDN/Storage/SQL**
Cloudflare offers several cloud services we can rely on so the microservices can remain
stateless (effectively read-only). They are also scalable by default so we don't need to worry
about adding more disk space or upgrading services. If we start outgrowing the limits of these,
well, we'll cross that bridge when we get to it.
- D1 (a SQLite-compatible distributed database)
- R2 (service like S3 for mass file hosting)
- KV (service to distributed offer key/value stores)
- Durable Objects (for a notifications hub)
## Do I have to use Cloudflare? ## Do I have to use Cloudflare?
No. The services are plain [Hono](https://hono.dev) apps, so the request-handling Short answer, no. The services are plain [Hono](https://hono.dev) apps, so the request-handling
code isn't tied to Cloudflare and can be deployed to other hosting providers — code isn't tied to Cloudflare and can be deployed to other hosting providers —
AWS (Lambda), Vercel, Netlify, Fly.io, a plain Node/Bun server, and so on. AWS (Lambda), Vercel, Netlify, Fly.io, a plain Node/Bun server, and so on.
**However** Long answer: the catch is everything _around_ the code. RecFlare leans on Cloudflare for the
deployment (Wrangler) and infrastructure layer — custom-domain routing per service, plus the
The catch is everything _around_ the code. RecFlare leans on Cloudflare for the
deployment and infrastructure layer — custom-domain routing per service, plus the
storage bindings (D1, KV, R2, Durable Objects) the workers use. On another storage bindings (D1, KV, R2, Durable Objects) the workers use. On another
provider you'll need to provide equivalents (per-service routing, databases, provider you'll need to provide equivalents (per-service routing, databases,
object storage, a pub/sub or WebSocket layer) and wire up the deployment yourself. object storage, a pub/sub or WebSocket layer) and wire up the deployment yourself.
So for example if you wanted to run on Vercel, you'd have to swap out KV for Redis, which are very similar
services but would require small code changes.
## Prerequisites ## Prerequisites
- node (modern) - node (modern)
- pnpm - pnpm
- bun - bun
- jq - jq/awk/sed
- A Cloudflare account with a zone (domain) you control, for deploying - A Cloudflare account with a zone (domain) you control, for deploying.
Cloudflare's free plan is good enough for testing (100k requests/day) but the Cloudflare's free plan is good enough for testing (100k worker requests/day) but the
Rec Room client is pretty chatty. Frequent testing may exhaust that quota. Rec Room client is pretty chatty. Frequent testing may exhaust that quota. The $5/month
Worker plan includes 10M/month.
See https://developers.cloudflare.com/workers/platform/pricing/#workers See https://developers.cloudflare.com/workers/platform/pricing/#workers
@@ -152,97 +170,60 @@ just install
**Configure your custom domain:** **Configure your custom domain:**
Create a new .env file: Create a new .env file from the template:
```bash ```bash
cp .env.example .env cp .env.example .env
# edit .env and set RECFLARE_DOMAIN to your domain
``` ```
Or, export it: Edit `.env` and set `RECFLARE_DOMAIN` to your domain (or declare it with `export RECFLARE_DOMAIN=rec.example.com`)
```bash (Optional) - per-app subdomain overrides come from
export RECFLARE_DOMAIN=rec.example.com `RECFLARE_SUBDOMAINS` (a JSON object, e.g. `'{"playersettings":"settings"}'`). This would be used
``` if you wanted to merge two services together.
`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.
Per-app subdomain overrides come from
`RECFLARE_SUBDOMAINS` (a JSON object, e.g. `'{"playersettings":"settings"}'`).
**Create the storage resources:** **Create the storage resources:**
The workers bind Cloudflare storage primitives — one shared D1 database, two KV The workers bind Cloudflare storage primitive. Create them once against your
namespaces, two R2 buckets, and a Durable Object. Create them once against your Cloudflare account, then record the IDs in `.env`. The committed `wrangler.jsonc`
Cloudflare account, then record the ids in `.env`. The committed `wrangler.jsonc` files carry `"local"` placeholders; the real IDs are spliced in at deploy time, so
files carry `"local"` placeholders; the real ids are spliced in at deploy time, so
nothing in version control needs editing. Authenticate wrangler first nothing in version control needs editing. Authenticate wrangler first
(`wrangler login`). (`wrangler login`).
_D1 — one shared `recflare` database_ (bound by `api`, `accounts`, `auth`, `match`,
`rooms`):
```bash ```bash
wrangler d1 create recflare wrangler d1 create recflare
# copy the printed database_id into .env:
# RECFLARE_D1=<database_id>
```
Then apply the schema. The `rooms` and `auth` workers own the migrations under
their `apps/<worker>/migrations/` directories. `just migrate` applies them to the
remote database (splicing `RECFLARE_D1` into the `"local"` placeholder the same way
`just deploy` does, so you don't edit any config):
```bash
just migrate # migrate every worker that owns migrations
just migrate -F rooms # or scope to one worker
just migrate -- --local # target the local dev db instead of remote
```
This runs non-interactively (it sets `CI`), so wrangler's "database may be
unavailable during the migration" confirmation is auto-accepted — turbo can't
forward your answer to the task anyway. A backup is still captured.
_KV — two namespaces_ (`RECFLARE_MATCH_PRESENCE` for `match`/`auth`,
`RECFLARE_PLAYER_SETTINGS` for `playersettings`):
```bash
wrangler kv namespace create RECFLARE_MATCH_PRESENCE wrangler kv namespace create RECFLARE_MATCH_PRESENCE
wrangler kv namespace create RECFLARE_PLAYER_SETTINGS wrangler kv namespace create RECFLARE_PLAYER_SETTINGS
``` ```
Record both ids in `.env` as a single JSON object keyed by binding name (note the Take the IDs output from the commands and put them into `.env`. (or with CI: `RECFLARE_KV='{"RECFLARE_MATCH_PRESENCE":"<id>","RECFLARE_PLAYER_SETTINGS":"<id>"}'`)
surrounding single quotes — without them the shell strips the inner quotes):
Then apply the schema. `just migrate` will set up the database and populate it with data. This runs non-interactively, so be careful!
```bash ```bash
RECFLARE_KV='{"RECFLARE_MATCH_PRESENCE":"<id>","RECFLARE_PLAYER_SETTINGS":"<id>"}' just migrate # migrate every worker that owns migrations
just migrate -F rooms # or scope to one worker
``` ```
_R2 — two buckets_ (`recflare-cdn` for `cdn`, `recflare-img` for `api`/`img`): ### R2 and Durable Objects
You only have to create the buckets:
```bash ```bash
wrangler r2 bucket create recflare-cdn wrangler r2 bucket create recflare-cdn
wrangler r2 bucket create recflare-img wrangler r2 bucket create recflare-img
``` ```
R2 buckets are referenced by name in the committed `wrangler.jsonc`, so there is ### Durable Objects
nothing to add to `.env`. See [`apps/img/README.md`](apps/img/README.md) for
seeding the default avatar/profile images.
_Durable Objects — no manual setup_. The `notify` worker's `RECFLARE_NOTIFICATIONS_HUB` Nothing manual to do here. The object is created manually.
binding (class `NotificationsHub`) is provisioned automatically from the migration
declared in its `wrangler.jsonc` on first deploy — there is no id to create or set.
**Run the development microservices:** **Run the development microservices:**
> **Note:** This runs, but the name-server document still advertises the deployed > **Note:** This runs, but the name-server document still advertises the deployed
> hosts, not your local instances — so service discovery won't resolve locally. > hosts, not your local instances — so service discovery won't resolve locally.
> You can still call each service directly; each Wrangler instance runs on its own > You can still call each service directly; each Wrangler instance runs on its own
> port. > port. Maybe we can get this working somehow. @todo
```bash ```bash
just dev just dev
@@ -250,17 +231,20 @@ just dev
**Deploy all workers:** **Deploy all workers:**
```bash This will deploy all workers to respective endpoints (*.example.com)
just deploy
```
Deploying requires `wrangler` to be authenticated against your Cloudflare Deploying requires `wrangler` to be authenticated against your Cloudflare
account (`wrangler login`, or `CLOUDFLARE_API_TOKEN` / `CLOUDFLARE_ACCOUNT_ID` account (`wrangler login`, or `CLOUDFLARE_API_TOKEN` / `CLOUDFLARE_ACCOUNT_ID`
in the environment). It also requires the storage resources to exist and their in the environment).
ids to be set in `.env` — see **Create the storage resources** above. At deploy
time the deploy script splices `RECFLARE_D1` and `RECFLARE_KV` into the `"local"` It requires the storage to be set up above, otherwise, deployments may fail.
placeholders in each worker's `wrangler.jsonc`; a missing id fails the deploy with
a message naming the binding. You can always re-run it as often as you wish.
```bash
just deploy # for all services
just deploy -F rooms # for a single microservice
```
## Repository Structure ## Repository Structure
@@ -308,7 +292,11 @@ See "Run the development microservices" above. It may be possible later as Wrang
### Can I use this to make my own server? ### Can I use this to make my own server?
Yes, that's the point. Yes, that's the point. Just set your custom domain and deploy it.
### Is there an admin panel?
Not yet. But there could be.
### Can I copy this project and modify it? ### Can I copy this project and modify it?