diff --git a/README.md b/README.md index 8cec8a4..94a2cb4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ pnpm install pnpm dev ``` -This starts the app at `http://localhost:1430`. By default it connects to the public STUN server included below, so peer-to-peer collaboration works out of the box; run your own [signaling worker](./signaling) if you want to self-host that piece too. +This starts the app at `http://localhost:1430`. By default it connects to public y-webrtc signaling relays and the public STUN server included below, so peer-to-peer collaboration works out of the box; run your own [signaling worker](./signaling) if you want to self-host that piece too. ### Scripts @@ -43,7 +43,7 @@ Copy `app/.env.example` to `app/.env.local` and adjust as needed: | Variable | Purpose | Default | | --- | --- | --- | | `VITE_HOMEPAGE` | Where the wordmark links | `https://subscript.to` | -| `VITE_SIGNALING_URL` | WebRTC signaling endpoint | `ws://localhost:8787` (local `wrangler dev`) | +| `VITE_SIGNALING_URL` | WebRTC signaling endpoints, comma-separated | `wss://y-webrtc-signaling.fly.dev,wss://y-webrtc.fly.dev` | | `VITE_STUN_URL` | STUN server for NAT traversal | `stun:stun.l.google.com:19302` | | `VITE_TURN_URL` / `VITE_TURN_USERNAME` / `VITE_TURN_CREDENTIAL` | Optional TURN relay for peers behind restrictive NATs | unset | diff --git a/app/.env.example b/app/.env.example index 9be715e..90ed56a 100644 --- a/app/.env.example +++ b/app/.env.example @@ -1,10 +1,11 @@ # Homepage link behind the wordmark. Defaults to https://subscript.to when unset. VITE_HOMEPAGE=https://subscript.to -# WebRTC signaling endpoint. Defaults to the public y-webrtc relay so Write -# works out of the box. Point this at your own deployed Cloudflare Worker -# (see ../signaling) or `wrangler dev`'s local URL if you'd rather self-host. -VITE_SIGNALING_URL=wss://y-webrtc-eu.fly.dev +# WebRTC signaling endpoints, comma-separated. Defaults to two public y-webrtc +# relays so Write works out of the box; peers connect to every listed relay. +# Point this at your own deployed Cloudflare Worker (see ../signaling) or +# `wrangler dev`'s local URL if you'd rather self-host. +VITE_SIGNALING_URL=wss://y-webrtc-signaling.fly.dev,wss://y-webrtc.fly.dev # STUN is used to discover a public IP for direct peer connections. The Google # STUN server below is free and requires no setup; swap in your own if you'd diff --git a/app/src/lib/config.test.ts b/app/src/lib/config.test.ts new file mode 100644 index 0000000..22bc4d9 --- /dev/null +++ b/app/src/lib/config.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from "vitest"; +import { defaultConfig, mergeConfig, signalingUrls } from "./config"; + +describe("signaling configuration", () => { + it("defaults to the reachable public y-webrtc relays", () => { + expect(signalingUrls(defaultConfig.signalingUrl)).toEqual([ + "wss://y-webrtc-signaling.fly.dev", + "wss://y-webrtc.fly.dev", + ]); + }); + + it("no longer defaults to the offline y-webrtc-eu relay", () => { + expect(defaultConfig.signalingUrl).not.toContain("y-webrtc-eu.fly.dev"); + }); + + it("splits comma-separated overrides and drops blanks", () => { + const config = mergeConfig({ signalingUrl: " wss://a.example , ,wss://b.example " }); + expect(signalingUrls(config.signalingUrl)).toEqual(["wss://a.example", "wss://b.example"]); + }); +}); diff --git a/app/src/lib/config.ts b/app/src/lib/config.ts index 18fa992..ed37217 100644 --- a/app/src/lib/config.ts +++ b/app/src/lib/config.ts @@ -11,11 +11,17 @@ export type WriteConfig = { export const defaultConfig: WriteConfig = { homepage: "https://subscript.to", - signalingUrl: "wss://y-webrtc-eu.fly.dev", + signalingUrl: "wss://y-webrtc-signaling.fly.dev,wss://y-webrtc.fly.dev", stunUrl: "stun:stun.l.google.com:19302", subscriptEnabled: false, }; +export const signalingUrls = (value: string) => + value + .split(",") + .map((url) => url.trim()) + .filter(Boolean); + export const mergeConfig = (overrides?: Partial): WriteConfig => { const defined = Object.fromEntries( Object.entries(overrides ?? {}).filter(([, value]) => value !== undefined), diff --git a/app/src/lib/project.ts b/app/src/lib/project.ts index a46ba0a..f29cb7a 100644 --- a/app/src/lib/project.ts +++ b/app/src/lib/project.ts @@ -2,7 +2,7 @@ import { IndexeddbPersistence } from "y-indexeddb"; import { WebrtcProvider } from "y-webrtc"; import * as Y from "yjs"; import { transformAnnotations } from "./annotation_ranges"; -import type { WriteConfig } from "./config"; +import { signalingUrls, type WriteConfig } from "./config"; import type { ScreenplayParagraph } from "./fdx"; import { blankParagraph } from "./fdx"; import type { DeviceIdentity, Signed } from "./identity"; @@ -800,10 +800,7 @@ export class LocalProject { connect(room: string) { this.provider?.destroy(); - const signaling = this.config.signalingUrl - .split(",") - .map((url) => url.trim()) - .filter(Boolean); + const signaling = signalingUrls(this.config.signalingUrl); const iceServers: RTCIceServer[] = [{ urls: this.config.stunUrl }]; if (this.config.turnUrl) { iceServers.push({ diff --git a/signaling/README.md b/signaling/README.md index d747018..20a0e28 100644 --- a/signaling/README.md +++ b/signaling/README.md @@ -38,6 +38,6 @@ Use that URL as `VITE_SIGNALING_URL` when building the app. ## Do you need to self-host this? -No. By default `VITE_SIGNALING_URL` points at the public `wss://y-webrtc-eu.fly.dev` relay, so Write works out of the box without deploying anything. +No. By default `VITE_SIGNALING_URL` points at the public `wss://y-webrtc-signaling.fly.dev` and `wss://y-webrtc.fly.dev` relays, so Write works out of the box without deploying anything. These are community-run relays with no uptime guarantee; for production, deploy your own worker. -Write is local-first: your script never leaves your browser except peer-to-peer over WebRTC. This worker (or the public relay) only helps two browsers find each other; it never sees document content. If you'd rather not depend on a third-party relay, deploy your own copy with the steps above and point `VITE_SIGNALING_URL` at it. +Write is local-first: your script never leaves your browser except peer-to-peer over WebRTC. This worker (or the public relays) only helps two browsers find each other; it never sees document content. If you'd rather not depend on a third-party relay, deploy your own copy with the steps above and point `VITE_SIGNALING_URL` at it.