Skip to content

Commit ee9c3e2

Browse files
authored
docs: rewrite README with feature-parity matrix for desktop vs mobile (#44)
The previous README still described mobile as a "Capacitor scaffold (stub Platform; persistence and native plugins pending)" — wildly stale after Phases 4-7 shipped. Re-anchor it on what actually works today and where the two shells diverge. - Spell out the unified-UX goal: shell is shared, runtimes inject a Platform. State the one expected divergence point: offline editing (desktop cache-then-OT-replay vs mobile CRDT local-edit-queue). - Add a 7-section feature matrix (~40 rows) covering workspaces, pads/tabs, deep links, settings/i18n, keyboard/gestures, permissions, packaging, tests. Empty / ⏳ / ✅ keys per shell. - Update package status (mobile is no longer "Capacitor scaffold"). - Add a What's-Next section grouped Soon / Later / Non-goals, with the offline-editing divergence flagged explicitly. - Keep quick-start commands inline and point per-package READMEs at developer docs.
1 parent 51d392a commit ee9c3e2

1 file changed

Lines changed: 173 additions & 12 deletions

File tree

README.md

Lines changed: 173 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,192 @@
11
# Etherpad apps
22

3-
Cross-platform clients for [Etherpad](https://etherpad.org/) — currently desktop, with mobile in development.
3+
Cross-platform clients for [Etherpad](https://etherpad.org/) — a single codebase
4+
that ships as an Electron desktop app **and** a Capacitor Android app, both
5+
running the same React shell.
46

57
This is a pnpm monorepo.
68

79
| Package | Status | Source |
810
|---|---|---|
9-
| `@etherpad/desktop` | Released | [`packages/desktop`](packages/desktop) |
10-
| `@etherpad/shell` | Source-consumed workspace dep | [`packages/shell`](packages/shell) |
11-
| `@etherpad/mobile` | Capacitor scaffold (stub Platform; persistence and native plugins pending) | [`packages/mobile`](packages/mobile) |
11+
| `@etherpad/desktop` | v0 beta — Linux (AppImage / `.deb` / Snap), Windows (NSIS / portable), macOS (DMG arm64+x64). Auto-update on Linux + Windows. | [`packages/desktop`](packages/desktop) |
12+
| `@etherpad/mobile` | Beta — Android debug APK runs; iOS scaffold present, not yet exercised. Not on Play Store yet. | [`packages/mobile`](packages/mobile) |
13+
| `@etherpad/shell` | Workspace dep consumed as source by both apps. Owns React tree, state, i18n, IPC channel schemas, the `Platform` injection seam. | [`packages/shell`](packages/shell) |
1214

13-
## Quick start (desktop)
15+
## Goal
16+
17+
**One UX, two shells.** The instance rail, pad tabs, sidebar, dialogs, settings,
18+
keyboard model, theming, and i18n live in `@etherpad/shell` and render
19+
identically on desktop and mobile. Each runtime injects a `Platform`
20+
implementation that handles native concerns (window management, persistence,
21+
deep links, permissions) behind a typed IPC seam.
22+
23+
The one place we expect to **diverge** is offline editing — a desktop client
24+
usually has a long-lived connection, where a mobile client is offline by
25+
default. Mobile will likely grow a CRDT-based local-edit-queue path that
26+
desktop doesn't need; both will keep using Etherpad's OT-based collaboration
27+
when online.
28+
29+
## Quick start
1430

1531
```bash
1632
pnpm install
17-
pnpm dev
33+
pnpm dev # desktop: Electron + Vite HMR
34+
pnpm mobile:dev # mobile: browser preview at http://localhost:5173/
35+
pnpm mobile:android:run # mobile: build + sync + run on attached device/emulator
36+
pnpm test # vitest across all packages
37+
pnpm test:e2e # Playwright Electron e2e + mobile smoke
38+
pnpm typecheck # tsc -b across the monorepo
1839
```
1940

20-
See [`packages/desktop/README.md`](packages/desktop/README.md) for full developer documentation.
41+
Per-app developer docs:
42+
43+
- [`packages/desktop/README.md`](packages/desktop/README.md) — install one-liners, install matrix, dev loop, packaging.
44+
- [`packages/mobile/README.md`](packages/mobile/README.md) — Capacitor / Android toolchain, build + adb.
45+
46+
## Feature parity
2147

22-
## Layout
48+
This is the canonical "what works where" view. Empty cells mean **not started**;
49+
"⏳" means in flight; "✅" means shipped on that surface.
2350

24-
- `packages/desktop/` — Electron app (Linux AppImage, deb, snap; macOS DMG; Windows NSIS).
25-
- `packages/shell/` — React renderer shell shared between desktop and mobile. Owns dialogs, state, i18n, and the `Platform` injection seam.
26-
- `packages/mobile/` — Capacitor 8 Android (and iOS-ready) app. Vite-built, wraps `@etherpad/shell` via `createCapacitorPlatform()`. `pnpm mobile:dev` for a browser preview; `pnpm mobile:android:run` for an attached device/emulator.
27-
- `docs/` — specs, plans, and shared internal docs.
51+
### Etherpad instances and workspaces
52+
53+
| Feature | Desktop | Mobile |
54+
|---|---|---|
55+
| Multiple Etherpad instances, isolated sessions |||
56+
| Per-instance colour + name + URL editing |||
57+
| Reorder instances in the rail |||
58+
| Embedded local Etherpad server (no internet needed) || ❌ phones don't ship Node; spec divergence noted below |
59+
| HTTP basic-auth challenge dialog || ❌ planned |
60+
61+
### Pads, tabs, navigation
62+
63+
| Feature | Desktop | Mobile |
64+
|---|---|---|
65+
| Open pad by name into a new tab |||
66+
| Multiple pads per instance, switchable tabs |||
67+
| Auto-collapse rail when opening a pad (focus mode) |||
68+
| Tap pad to dismiss the rail (drawer behaviour) | n/a ||
69+
| Restore open tabs + active pad across app restarts |||
70+
| Restore rail-collapsed state across app restarts |||
71+
| Native pad rendering (WebContentsView vs iframe) | WebContentsView | iframe |
72+
| Pad sidebar — Recent + Pinned + search |||
73+
| Cross-instance fuzzy quick switcher (Ctrl+K) | ✅ name + content search | ✅ name search; content search ⏳ |
74+
| Pad-history persistence per workspace |||
75+
| `?lang=…&userName=…` threaded into pad URL |||
76+
77+
### Deep links and integration
78+
79+
| Feature | Desktop | Mobile |
80+
|---|---|---|
81+
| `etherpad-app://` deep-link scheme | ✅ registered, partial handler ||
82+
| Open pad by URL dialog |||
83+
| Receive shared URL from another app | n/a | ✅ Android share intent |
84+
| "Open in browser" escape for blocked / X-Frame-DENY pads | n/a ||
85+
86+
### Settings, theming, i18n
87+
88+
| Feature | Desktop | Mobile |
89+
|---|---|---|
90+
| Light / dark / auto theme |||
91+
| Default zoom override |||
92+
| Accent colour override |||
93+
| User display name pre-fill |||
94+
| "Remember open pads on quit" toggle |||
95+
| Confirmation dialog before "Clear all pad history" |||
96+
| Shell strings translated (en, es, fr, de, pt/pt-br, it) |||
97+
| Pad-iframe locale via `?lang=` (115 etherpad-core locales) |||
98+
| HTML root `lang` attribute follows active locale |||
99+
100+
### Keyboard, gestures, window
101+
102+
| Feature | Desktop | Mobile |
103+
|---|---|---|
104+
| Keyboard shortcuts (`Ctrl+T` / `Ctrl+W` / `Ctrl+K` / `Ctrl+1..9` / `Ctrl+,`) || n/a |
105+
| Swipe gesture between pads | n/a ||
106+
| Android back button collapses → switches → exits | n/a ||
107+
| Window bounds + active workspace restored on relaunch || n/a |
108+
| Minimise-to-tray || n/a |
109+
| Tray icon (B&W silhouette, theme-adaptive ⏳) || n/a |
110+
111+
### Permissions and security
112+
113+
| Feature | Desktop | Mobile |
114+
|---|---|---|
115+
| Per-instance isolated session partition |`persist:ws-<uuid>` | ✅ Capacitor Preferences keyed by workspace id |
116+
| Permission pre-allow for `ep_webrtc` plugins (cam/mic/fullscreen/clipboard/screen) | ✅ narrow allowlist | ⏳ Phase 6b native plugin (camera/mic delegation) |
117+
| Deny-by-default with prompt-on-request, persisted decisions | ⏳ planned | ⏳ planned |
118+
| HTTPS-with-self-signed-cert trust UX | ⏳ planned | ⏳ planned |
119+
120+
### Packaging, distribution, updates
121+
122+
| Feature | Desktop | Mobile |
123+
|---|---|---|
124+
| Linux AppImage + `.deb` + Snap || n/a |
125+
| Windows NSIS installer + portable `.exe` | ✅ unsigned | n/a |
126+
| macOS DMG (arm64 + x64) | ✅ unsigned | n/a |
127+
| Android signed release APK + Play Store listing | n/a ||
128+
| iOS build | n/a | scaffold present, not built |
129+
| `release-please` conventional-commits release flow || shared release flow planned |
130+
| In-app auto-update | ✅ electron-updater (AppImage + `.deb` + Windows NSIS) | n/a — store handles updates |
131+
| Snap channel publishing (`edge` auto, `stable` gated) || n/a |
132+
133+
### Tests and CI
134+
135+
| Feature | Desktop | Mobile |
136+
|---|---|---|
137+
| Vitest unit + component tests || ✅ shared with shell |
138+
| Playwright Electron e2e | ✅ against in-process mock Etherpad | n/a |
139+
| Playwright web smoke (vite preview) | n/a ||
140+
| Android emulator click-through smoke (uiautomator) | n/a | ✅ scaffolded |
141+
| CI runs on every PR (lint / typecheck / unit / e2e) |||
142+
143+
## What's next
144+
145+
Roughly in the order it'll be tackled. Items that apply to one shell are
146+
marked; everything else lands on both.
147+
148+
### Soon
149+
150+
- **Mobile permissions plugin (Phase 6b)** — native Kotlin delegation for
151+
camera, mic, clipboard, fullscreen, file picker so `ep_webrtc` and friends
152+
work inside the WebView on Android.
153+
- **Desktop permission UX upgrade** — replace the narrow pre-allow with a
154+
deny-by-default prompt-on-request flow, decisions persisted per
155+
instance+origin. Same UI ships to mobile after Phase 6b lands.
156+
- **Mobile content search in quick switcher** — desktop already indexes pad
157+
bodies via `/export/txt`. Mobile stubs that path; wire it.
158+
- **Mobile Play Store release** — signed AAB, store listing, edge / stable
159+
channels mirroring the Snap split.
160+
- **Cross-pad content search on mobile** — see above.
161+
- **Tray icon theme adaptation (desktop)** — detect `nativeTheme`, ship a
162+
black-silhouette variant for light trays.
163+
164+
### Later
165+
166+
- **Offline editing — diverges between shells.** Desktop usually has a
167+
long-lived connection; mobile is offline by default. Working assumption:
168+
desktop gets a cache-then-OT-replay path; mobile gets a CRDT-based local
169+
edit queue with sync-on-reconnect. Both surface the same UX (greyed
170+
"offline" banner, queued-edit indicator) but the engines differ. Spec work
171+
in flight.
172+
- **Native OS notifications** — pad mentions, presence.
173+
- **Drag-tab-to-reorder + tear-off-into-new-window** (desktop).
174+
- **HTTPS-with-self-signed-cert trust UX** — applies to both, more useful on
175+
desktop where users add local Etherpad URLs.
176+
177+
### Explicit non-goals
178+
179+
- **No code-signing fees.** Windows + macOS will continue shipping unsigned
180+
binaries — SmartScreen / Gatekeeper warn on first run; both work fine
181+
afterwards. Apple's $99/yr Developer ID and Microsoft's EV / Azure Trusted
182+
Signing programs gate independent open-source software behind a recurring
183+
tax we won't pay. Forks / distributors / enterprises are welcome to roll
184+
their own signed builds under Apache-2.0.
28185

29186
## License
30187

31188
Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
189+
190+
This project is a thin client; the Etherpad server is upstream software with
191+
its own license and contributors. Etherpad is at
192+
<https://github.com/ether/etherpad>.

0 commit comments

Comments
 (0)