From cf2dec44ed19a861737220ecc16b3faad827ed05 Mon Sep 17 00:00:00 2001 From: reverse Date: Sat, 20 Jun 2026 08:38:52 +0000 Subject: [PATCH 1/6] Plugins: document topbar/sidebar slots, message decorators, SRI --- docs/plugins.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/plugins.md b/docs/plugins.md index c7bba70..4fc9e58 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -21,7 +21,14 @@ Add script URLs to `plugins` in [`config.json`](https://orbit.tchatou.fr/docs/co ``` They load in order, after the app boots. Host them anywhere the page can reach -(same-origin recommended). +(same-origin recommended). For a third-party origin, pin the file with +Subresource Integrity by giving an object instead of a URL: + +```json +{ "plugins": [{ "url": "https://cdn.example/x.js", "integrity": "sha384-…" }] } +``` + +(`crossorigin` defaults to `anonymous` when an `integrity` hash is set.) ## A quick plugin @@ -75,6 +82,7 @@ instead. See **[Compiled plugins](https://orbit.tchatou.fr/docs/compiled-plugins | `orbit.storage.get(key, def)/set(key, val)` | namespaced persistence | | `orbit.addUi(slot, render)` | add UI to a slot (returns a remover) | | `orbit.addSettingsSection({label, icon?, render})` | add a whole Settings section | +| `orbit.addMessageDecorator(m => …)` | append UI to every message; `m` = `{id, nick, text, kind, ts, mine}` | | `orbit.h / orbit.html` | render helpers | | `log(…)` | namespaced console logger | @@ -89,10 +97,14 @@ instead. See **[Compiled plugins](https://orbit.tchatou.fr/docs/compiled-plugins | Slot | Where | |---|---| | `composer_button` | a button in the message composer toolbar | +| `topbar_item` | an item in the channel topbar action row (next to search / notifications) | +| `sidebar_item` | an item in the conversation sidebar header (next to the compose button) | | `settings_section` | a whole section in Settings (own nav entry + pane) — use `orbit.addSettingsSection()` | -More slots (message decorators, side panels) will be added as the core grows -stable homes for them. +Message decorators are added with `orbit.addMessageDecorator(m => …)` rather than +a slot — the callback runs for every rendered message. Every contributed slot and +decorator renders inside its own error boundary, so a crashing plugin renders +nothing instead of taking down the app. ## Trust & security From e6ea864ae1ed70a0b9af4a110f9cd94bbf70cb8b Mon Sep 17 00:00:00 2001 From: reverse Date: Sat, 20 Jun 2026 09:05:34 +0000 Subject: [PATCH 2/6] Plugins: document addMessageAction (toolbar buttons) --- docs/plugins.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/plugins.md b/docs/plugins.md index 4fc9e58..1633966 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -82,7 +82,8 @@ instead. See **[Compiled plugins](https://orbit.tchatou.fr/docs/compiled-plugins | `orbit.storage.get(key, def)/set(key, val)` | namespaced persistence | | `orbit.addUi(slot, render)` | add UI to a slot (returns a remover) | | `orbit.addSettingsSection({label, icon?, render})` | add a whole Settings section | -| `orbit.addMessageDecorator(m => …)` | append UI to every message; `m` = `{id, nick, text, kind, ts, mine}` | +| `orbit.addMessageDecorator(m => …)` | inline UI after every message's text; `m` = `{id, nick, text, kind, ts, mine}` | +| `orbit.addMessageAction(m => …)` | a button in every message's hover action toolbar (next to reply/react) | | `orbit.h / orbit.html` | render helpers | | `log(…)` | namespaced console logger | @@ -101,10 +102,12 @@ instead. See **[Compiled plugins](https://orbit.tchatou.fr/docs/compiled-plugins | `sidebar_item` | an item in the conversation sidebar header (next to the compose button) | | `settings_section` | a whole section in Settings (own nav entry + pane) — use `orbit.addSettingsSection()` | -Message decorators are added with `orbit.addMessageDecorator(m => …)` rather than -a slot — the callback runs for every rendered message. Every contributed slot and -decorator renders inside its own error boundary, so a crashing plugin renders -nothing instead of taking down the app. +Two per-message hooks run for every rendered message: +`orbit.addMessageDecorator(m => …)` appends inline UI after the text, and +`orbit.addMessageAction(m => …)` adds a button to the hover action toolbar next +to reply/react. Every contributed slot, action and decorator renders inside its +own error boundary, so a crashing plugin renders nothing instead of taking down +the app. ## Trust & security From 78990d66b58d4f1551e24e9f95b936dba82e2d6e Mon Sep 17 00:00:00 2001 From: reverse Date: Sat, 20 Jun 2026 09:13:12 +0000 Subject: [PATCH 3/6] Plugins: note message text is formatting-stripped, raw available --- docs/plugins.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plugins.md b/docs/plugins.md index 1633966..72349bb 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -82,8 +82,8 @@ instead. See **[Compiled plugins](https://orbit.tchatou.fr/docs/compiled-plugins | `orbit.storage.get(key, def)/set(key, val)` | namespaced persistence | | `orbit.addUi(slot, render)` | add UI to a slot (returns a remover) | | `orbit.addSettingsSection({label, icon?, render})` | add a whole Settings section | -| `orbit.addMessageDecorator(m => …)` | inline UI after every message's text; `m` = `{id, nick, text, kind, ts, mine}` | -| `orbit.addMessageAction(m => …)` | a button in every message's hover action toolbar (next to reply/react) | +| `orbit.addMessageDecorator(m => …)` | inline UI after every message's text; `m` = `{id, nick, text, raw, kind, ts, mine}` (`text` is formatting-stripped, `raw` keeps mIRC codes) | +| `orbit.addMessageAction(m => …)` | a button in every message's hover action toolbar (next to reply/react); same `m` | | `orbit.h / orbit.html` | render helpers | | `log(…)` | namespaced console logger | From bcd2b8b1ff2a2773faf656066abf9b3d55815cf6 Mon Sep 17 00:00:00 2001 From: reverse Date: Sat, 20 Jun 2026 15:46:04 +0000 Subject: [PATCH 4/6] docs: fix the no-signup contradiction; 25 caps; honest guest/account wording --- docs/branding.md | 2 +- docs/overview.md | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/branding.md b/docs/branding.md index 8598f2d..1848681 100644 --- a/docs/branding.md +++ b/docs/branding.md @@ -16,7 +16,7 @@ Everything that ties Orbit to a particular network or brand lives in "url": "https://example.org", "tagline": "Chat with", "taglineEm": "everyone.", - "subtitle": "Public rooms, private messages, no signup required." + "subtitle": "Public rooms, private messages, and moderation that works." } } ``` diff --git a/docs/overview.md b/docs/overview.md index 5dbc628..f96d68c 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -4,15 +4,17 @@ Order: 10 # Overview **Orbit** is a modern web client for **IRC** — the open chat protocol that has quietly run -communities for decades. It runs entirely in the browser: pick a nick and you're talking, with -**no install and no signup**. +communities for decades. It runs entirely in the browser — nothing to install — and handles +everything from a quick guest nick to a full account (SASL login and in-app registration). +Whether a deployment lets people in as guests or asks them to register is its own choice, not +the client's. It powers [tchatou.fr](https://tchatou.fr/app/), and is built to be **re-pointed at any IRCv3 network** and **rebranded** from a single `config.json` — without recompiling. ## What makes it different -- **Full IRCv3.** Orbit negotiates 24 capabilities — SASL, message-tags, reactions, typing +- **Full IRCv3.** Orbit negotiates 25 capabilities — SASL, message-tags, reactions, typing indicators, read-markers, multi-line messages, server-side history, account registration, and Web Push. See [IRCv3 capabilities](https://orbit.tchatou.fr/docs/ircv3/). - **Pluggable at runtime.** A static `config.json` is fetched on startup and sets the server, From c728d32977fc545d9da9980d290dc9b54f4d32fd Mon Sep 17 00:00:00 2001 From: reverse Date: Sat, 20 Jun 2026 16:29:06 +0000 Subject: [PATCH 5/6] docs: document defaults.lang (pin default UI language) --- docs/config.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/config.md b/docs/config.md index 5f22c34..8597585 100644 --- a/docs/config.md +++ b/docs/config.md @@ -28,6 +28,7 @@ Merge rules: objects merge key-by-key; **arrays and scalars replace** wholesale. | `report.target` | string | Channel that user reports are sent to. | | `defaults.theme` | string | `light` · `dark` · `yomirc` · `yomirc-dark`. | | `defaults.compact` / `sound` / `hideJoinQuit` / `clock24` | bool | Preset new-user prefs. | +| `defaults.lang` | string | Pin a default UI language (e.g. `en`, `fr`, `de`). Overrides browser detection for users who haven't picked one. Omit to auto-detect. | | `features.push` / `imageUpload` / `register` | bool | Turn whole features on/off. | > `defaults.*` only seed a user's preferences the **first** time — once someone changes a setting, From 641d58e84cfb8c6a3f73e28d4f139739c2cce76f Mon Sep 17 00:00:00 2001 From: reverse Date: Sat, 20 Jun 2026 19:28:28 +0000 Subject: [PATCH 6/6] overview: reword, drop em-dashes --- docs/overview.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/overview.md b/docs/overview.md index f96d68c..af0b529 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -3,18 +3,18 @@ Order: 10 # Overview -**Orbit** is a modern web client for **IRC** — the open chat protocol that has quietly run -communities for decades. It runs entirely in the browser — nothing to install — and handles +**Orbit** is a modern web client for **IRC**, the open chat protocol that has quietly run +communities for decades. It runs entirely in the browser, with nothing to install, and handles everything from a quick guest nick to a full account (SASL login and in-app registration). Whether a deployment lets people in as guests or asks them to register is its own choice, not the client's. It powers [tchatou.fr](https://tchatou.fr/app/), and is built to be **re-pointed at any IRCv3 -network** and **rebranded** from a single `config.json` — without recompiling. +network** and **rebranded** from a single `config.json`, without recompiling. ## What makes it different -- **Full IRCv3.** Orbit negotiates 25 capabilities — SASL, message-tags, reactions, typing +- **Full IRCv3.** Orbit negotiates 25 capabilities: SASL, message-tags, reactions, typing indicators, read-markers, multi-line messages, server-side history, account registration, and Web Push. See [IRCv3 capabilities](https://orbit.tchatou.fr/docs/ircv3/). - **Pluggable at runtime.** A static `config.json` is fetched on startup and sets the server, @@ -24,11 +24,11 @@ network** and **rebranded** from a single `config.json` — without recompiling. closed. - **Self-hostable.** A static build behind any web server. The project even runs its own git server with [push-to-deploy](https://orbit.tchatou.fr/docs/push-to-deploy/). -- **Free software.** AGPL-3.0 — use it, modify it, self-host it. +- **Free software.** AGPL-3.0: use it, modify it, self-host it. ## Tech -React 19 · TypeScript · Vite · zustand. Tested with Vitest, linted, and built in CI. The codebase -is a clean modular tree — see [Architecture](https://orbit.tchatou.fr/docs/architecture/). +React 19, TypeScript, Vite and zustand. Tested with Vitest, linted, and built in CI. The codebase +is a clean modular tree; see [Architecture](https://orbit.tchatou.fr/docs/architecture/). -> New here? Jump to the [Quick start](https://orbit.tchatou.fr/docs/quick-start/) to run your own in a minute. +> New here? Jump to the [Quick start](https://orbit.tchatou.fr/docs/quick-start/) to run your own.