Skip to content

Commit 3bd8aeb

Browse files
JohnMcLearclaude
andauthored
refactor: convert repo to pnpm monorepo (packages/desktop) — Phase 1 recovery (#30)
* docs(spec): add Etherpad mobile (Android first, iOS-ready) design Capacitor + React app sharing the desktop's renderer/state/i18n via a new @etherpad/shell package in a pnpm monorepo restructure of this repo. iframe-per-tab pad rendering, custom WebView permissions plugin for ep_webrtc-style needs, F-Droid as the primary distribution channel. Embedded local server and push notifications are v2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(plan): add phase-1 workspace-conversion implementation plan Phase 1 of the mobile rollout (spec §11.1): convert this repo into a pnpm workspace with all current desktop source under packages/desktop/, add a thin proxy root package.json, and update CI / release / snap / release-please workflows for the new paths. Zero behavioural change to the desktop app. Subsequent phases (extract @etherpad/shell, bootstrap @etherpad/mobile, PadIframeStack, permissions, deep links, responsiveness, F-Droid) will get their own plans once this one lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(monorepo): bootstrap pnpm workspace skeleton First step of monorepo conversion (spec §3 phase 1). Adds the empty packages/ directory and pnpm-workspace.yaml. No file moves yet — the existing single-package layout still works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(monorepo): move desktop into packages/desktop Moves all source, tests, scripts, build dir, config files, and the desktop-specific docs (AGENTS.md, CHANGELOG.md, README.md) into packages/desktop/. Renames the package to @etherpad/desktop and adds a thin root package.json that proxies every script via `pnpm --filter @etherpad/desktop`. The pnpm.onlyBuiltDependencies config is moved to the workspace root (packages/desktop/ is not a workspace root, so the field had no effect there per pnpm's rules). The pnpm lockfile stays at the workspace root (canonical pnpm layout). LICENSE, NOTICE, and CLAUDE.md remain at the repo root because they apply to the whole repo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(root): add monorepo README pointing at packages/desktop Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(claude): update CLAUDE.md paths for packages/desktop layout Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(monorepo): point playwright + report paths at packages/desktop/ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(release): prefix release artefact paths with packages/desktop/ electron-builder runs via `pnpm --filter @etherpad/desktop exec` so the binary resolves against the desktop workspace; upload-artifact paths reach into packages/desktop/release/ for the produced binaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(snap): prefix snap artefact paths with packages/desktop/ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(release-please): switch to monorepo manifest mode Desktop is now the only managed package; manifest mode lets us add mobile/shell later as additional components without further migration. Tag format unchanged (v<version>) via include-component-in-tag: false + include-v-in-tag: true, so release.yml and snap-publish.yml triggers fire on the same shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 01670e2 commit 3bd8aeb

201 files changed

Lines changed: 540 additions & 466 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
node-version: 22
3737
cache: pnpm
3838
- run: pnpm install --frozen-lockfile
39-
- run: pnpm exec playwright install --with-deps chromium
39+
- run: pnpm --filter @etherpad/desktop exec playwright install --with-deps chromium
4040
- run: pnpm build
4141
- run: pnpm test:e2e
4242
env:
@@ -45,5 +45,5 @@ jobs:
4545
if: failure()
4646
with:
4747
name: playwright-report
48-
path: playwright-report/
48+
path: packages/desktop/playwright-report/
4949
retention-days: 7

.github/workflows/release-please.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ jobs:
3535
steps:
3636
- uses: googleapis/release-please-action@v5
3737
with:
38-
# `node` mode keeps package.json's version field as the source
39-
# of truth and writes a top-level CHANGELOG.md.
40-
release-type: node
41-
# Use the default GitHub token; release-please opens PRs and
42-
# creates tags on the same repo it runs in.
38+
# Manifest mode for the monorepo. Configuration lives in
39+
# release-please-config.json; current versions in
40+
# .release-please-manifest.json. The desktop package is the
41+
# only released package today; mobile/shell will be added
42+
# as separate components in later phases.
43+
config-file: release-please-config.json
44+
manifest-file: .release-please-manifest.json
4345
token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/release.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ jobs:
2626
# electron-builder reads the linux.target array in the YAML —
2727
# which includes snap — and tries to publish a snap to the Snap
2828
# Store from this job, which doesn't have the credentials.
29-
run: pnpm exec electron-builder --linux AppImage deb --config build/electron-builder.yml --publish always
29+
run: pnpm --filter @etherpad/desktop exec electron-builder --linux AppImage deb --config build/electron-builder.yml --publish always
3030
env:
3131
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3232
- uses: actions/upload-artifact@v7
3333
with:
3434
name: linux-artifacts
3535
path: |
36-
release/*.AppImage
37-
release/*.deb
38-
release/latest-linux.yml
36+
packages/desktop/release/*.AppImage
37+
packages/desktop/release/*.deb
38+
packages/desktop/release/latest-linux.yml
3939
retention-days: 14
4040

4141
release-macos:
@@ -59,17 +59,17 @@ jobs:
5959
# --mac builds DMG + ZIP for both arm64 and x64. CSC_IDENTITY_AUTO_DISCOVERY=false
6060
# tells electron-builder NOT to sniff the keychain for a signing
6161
# identity (we don't have one for the beta).
62-
run: pnpm exec electron-builder --mac --config build/electron-builder.yml --publish always
62+
run: pnpm --filter @etherpad/desktop exec electron-builder --mac --config build/electron-builder.yml --publish always
6363
env:
6464
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6565
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
6666
- uses: actions/upload-artifact@v7
6767
with:
6868
name: macos-artifacts
6969
path: |
70-
release/*.dmg
71-
release/*-mac.zip
72-
release/latest-mac.yml
70+
packages/desktop/release/*.dmg
71+
packages/desktop/release/*-mac.zip
72+
packages/desktop/release/latest-mac.yml
7373
retention-days: 14
7474

7575
release-windows:
@@ -92,13 +92,13 @@ jobs:
9292
- name: Build
9393
run: pnpm build
9494
- name: Package
95-
run: pnpm exec electron-builder --win --config build/electron-builder.yml --publish always
95+
run: pnpm --filter @etherpad/desktop exec electron-builder --win --config build/electron-builder.yml --publish always
9696
env:
9797
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9898
- uses: actions/upload-artifact@v7
9999
with:
100100
name: windows-artifacts
101101
path: |
102-
release/*.exe
103-
release/latest.yml
102+
packages/desktop/release/*.exe
103+
packages/desktop/release/latest.yml
104104
retention-days: 14

.github/workflows/snap-publish.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
# SNAPCRAFT_STORE_CREDENTIALS is only available in the publish-*
6767
# jobs below. Disable implicit publish; the dedicated job uses
6868
# snapcore/action-publish with the credentials properly scoped.
69-
run: pnpm exec electron-builder --linux snap --config build/electron-builder.yml --publish never
69+
run: pnpm --filter @etherpad/desktop exec electron-builder --linux snap --config build/electron-builder.yml --publish never
7070

7171
- name: Locate snap file
7272
id: find
@@ -77,14 +77,14 @@ jobs:
7777
# both the build job (after `cd release` is implicit) and the publish
7878
# job (after artifact download).
7979
run: |
80-
file=$(ls release/*.snap | head -n1)
80+
file=$(ls packages/desktop/release/*.snap | head -n1)
8181
echo "path=$(basename "$file")" >> "$GITHUB_OUTPUT"
8282
8383
- name: Upload snap artifact
8484
uses: actions/upload-artifact@v7
8585
with:
8686
name: etherpad-desktop-snap
87-
path: release/*.snap
87+
path: packages/desktop/release/*.snap
8888
if-no-files-found: error
8989
retention-days: 7
9090

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"packages/desktop": "0.3.2"
3+
}

CLAUDE.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
# Claude Code instructions
22

3-
**The canonical AI guide for this repo is `AGENTS.md`** — read it first. This file
3+
**The canonical AI guide for this repo is `packages/desktop/AGENTS.md`** — read it first. This file
44
adds Claude-specific notes and project gotchas that other agents share too.
55

6+
## Monorepo layout (read this first)
7+
8+
This repo is a pnpm workspace as of 2026-05. The desktop app lives in `packages/desktop`. Run every `pnpm` command from the repo root — the root `package.json` proxies every script via `pnpm --filter @etherpad/desktop`. Don't `cd` into `packages/desktop` for normal dev — it works but breaks IDE assumptions about where the workspace is.
9+
10+
Mobile (`packages/mobile`) and shell (`packages/shell`) are coming in subsequent phases; today there is only `packages/desktop`.
11+
612
## Read first
713

8-
- `AGENTS.md` — full project overview: stack, dev loop, IPC patterns, how
14+
- `packages/desktop/AGENTS.md` — full project overview: stack, dev loop, IPC patterns, how
915
WebContentsViews are positioned, how tests are structured, and the
1016
house rules. Everything below assumes you've read it.
1117
- `docs/superpowers/specs/2026-05-03-etherpad-desktop-linux-mvp-design.md`
@@ -23,7 +29,7 @@ These bite people who don't know them. Don't relearn the hard way.
2329
Earlier code (and the v1 spec) assumed `npx etherpad-lite@latest`
2430
works; it 404s. The embedded-server flow is currently disabled in the
2531
UI for this reason. The E2E fixture is now an in-process mock
26-
(`tests/e2e/fixtures/etherpad.ts`) that returns the JSON shape the
32+
(`packages/desktop/tests/e2e/fixtures/etherpad.ts`) that returns the JSON shape the
2733
shell probes for.
2834
- **Never use the name "etherpad-lite" in new packaging, docs, or
2935
configs.** Legacy paths in code (`ep_etherpad-lite/...`) can stay
@@ -38,14 +44,14 @@ These bite people who don't know them. Don't relearn the hard way.
3844
the holding process; only `*.lock` files are safe to remove.
3945
- **WebContentsViews are painted above the renderer.** When the rail
4046
collapses we leave a gutter on the left (`COLLAPSED_LEFT_GUTTER` in
41-
`src/main/windows/app-window.ts`) so the DOM-rendered expand handle
47+
`packages/desktop/src/main/windows/app-window.ts`) so the DOM-rendered expand handle
4248
isn't covered by the native pad view. The CSS handle position and
4349
the gutter constant must agree — there's a regression test pinning
44-
this in `tests/main/windows/app-window-layout.spec.ts`.
50+
this in `packages/desktop/tests/main/windows/app-window-layout.spec.ts`.
4551
- **All user-facing strings go through i18n.** `t.<section>.<key>` from
46-
`src/renderer/i18n/`. No hardcoded English in JSX, aria-labels, or
52+
`packages/desktop/src/renderer/i18n/`. No hardcoded English in JSX, aria-labels, or
4753
titles — use `fmt()` for placeholder substitution. The shape contract
48-
is pinned in `tests/renderer/i18n/i18n.spec.ts`.
54+
is pinned in `packages/desktop/tests/renderer/i18n/i18n.spec.ts`.
4955

5056
## Working style for this repo
5157

0 commit comments

Comments
 (0)