- TypeScript 67.5%
- JavaScript 30.8%
- Shell 1.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| .githooks | ||
| client | ||
| templates | ||
| worker | ||
| .env.example | ||
| .gitignore | ||
| block_render.test.ts | ||
| block_render.ts | ||
| collabora.plugin.json | ||
| collabora.test.ts | ||
| collabora.ts | ||
| collabora_block_editor.tsx | ||
| collabora_block_preview_client.tsx | ||
| collabora_editor_tool.test.ts | ||
| collabora_editor_tool.tsx | ||
| collabora_embed.test.ts | ||
| collabora_office_dialog.css | ||
| collabora_office_dialog.tsx | ||
| collabora_open_editor.tsx | ||
| compose.dev.yml | ||
| config.test.ts | ||
| config.ts | ||
| deploy.json | ||
| disabled_reason.test.ts | ||
| disabled_reason.ts | ||
| doc_types.ts | ||
| embed_asset_patterns.ts | ||
| filename.ts | ||
| launch_errors.test.ts | ||
| launch_errors.ts | ||
| limedoc.project.json | ||
| office_access.test.ts | ||
| office_access.ts | ||
| office_blocks.test.ts | ||
| office_blocks.ts | ||
| office_capabilities.test.ts | ||
| office_capabilities.ts | ||
| office_directive.test.ts | ||
| office_directive.ts | ||
| office_preview.test.ts | ||
| office_preview.ts | ||
| office_scope.test.ts | ||
| office_scope.ts | ||
| office_templates.test.ts | ||
| public_origin.ts | ||
| README.md | ||
| register_provider.ts | ||
Collabora Online
Edit office documents via Collabora Online (WOPI).
Requirements
- Docker (or Podman with
DOCKER_CMD=podman) - That's it — everything else runs inside containers.
Quick start
# 1. Pull the dev image and set up .env
./ldcmd setup
# 2. Start the dev environment (app + Redis)
./ldcmd up
# 3. Open http://localhost:5173 in your browser
# 4. Edit plugin sources — HMR applies automatically
# 5. Run tests
./ldcmd test
# 6. Check types and import boundaries
./ldcmd check
Directory layout
collabora.plugin.json # Plugin manifest
collabora.ts # Server entry (defineLimedocPlugin)
collabora_editor_tool.tsx # Browser client (builds to client/*.js)
client/ # Pre-built browser bundles (committed)
limedoc.project.json # Store metadata (package download URLs)
compose.dev.yml # Dev compose (uses the published limedoc-dev image)
ldcmd # Bridge script — the only thing you run on your host
.env.example # Env var template — copy to .env and fill in OIDC values
ldcmd commands
| Command | What it does |
|---|---|
./ldcmd setup |
Pull limedoc-dev image, copy .env.example → .env |
./ldcmd up |
Start dev environment |
./ldcmd down |
Stop dev environment |
./ldcmd logs [service] |
Follow container logs |
./ldcmd sh [service] |
Open shell in container (default: app-dev) |
./ldcmd test |
Run plugin tests |
./ldcmd fmt |
Format sources |
./ldcmd lint |
Lint sources |
./ldcmd check |
Type-check + import boundary check |
./ldcmd pack |
Build zip + sha256 (CI also publishes sig.json) |
./ldcmd publish |
Pack and upload (needs .forgejo.env / PACKAGE_TOKEN) |
./ldcmd plugin install <id> |
Install a plugin dependency into the running env |
./ldcmd plugin ls |
List installed plugins |
Building client bundles
# Inside the container (run after editing .tsx files)
./ldcmd sh
deno task plugin:build -- /limedoc/plugins/collabora.plugin
Or directly:
./ldcmd check # runs build as part of the check
Production sidecar (host)
Pack Store / packs:install unpacks this plugin into the app only. The Docker
sidecar is not started by Limedoc (no Docker socket in the app). On the
deploy host:
ldcmd sidecar up collabora
# or: ldcmd up
Compose SoT: deploy.json + worker/docker-compose.yml (joins DOCKER_NETWORK_NAME).
Distroless + proof-key + HTTPS
collabora/code:latest is distroless (no shell / no coolconfig).
ldcmd sidecar configure / the setup wizard host-generate proof_key under
COLLABORA_COOLWSD_HOST_PATH and set COLLABORA_VALIDATE_PROOF_KEY=true when
keygen succeeds. Compose file-mounts proof_key and proof_key.pub into
/etc/coolwsd/ (do not bind-mount the whole directory — that hides
coolwsd.xml). After first keygen, recreate Collabora then the app. Verify
/hosting/discovery contains proof-key.
Behind a TLS reverse proxy keep COLLABORA_SSL_TERMINATION=true (default) so
the browser uses wss://. Set false only for plain-HTTP local bring-up.
Packing and publishing
# Build the installable zip + sha256 sidecar (local)
./ldcmd pack
# Publish (needs .forgejo.env with PACKAGE_TOKEN, PACKAGE_OWNER)
./ldcmd publish
CI (Forgejo Actions, .forgejo/workflows/publish.yml) on push to main publishes
zip + sha256 + sig.json to Packages and Releases. Pack CI signs the
content hash with OpenBao Transit (Forgejo Actions OIDC). Actions secret
PACKAGE_TOKEN only — PACKAGE_OWNER is in the workflow env.
Developing with plugin dependencies
Your plugin may depend on another plugin at runtime. Three ways to include it:
1. Install via ldcmd (easiest, needs the app running)
./ldcmd up
./ldcmd plugin install media # fetches from PACKAGE_STORE_URL in .env
Set PACKAGE_STORE_URL in .env to point at the Forgejo package registry:
PACKAGE_STORE_URL=https://git.belowtoxic.cloud/api/packages/limedoc-plugins
2. Local bind-mount (no running app needed)
Download the pack zip, unzip it next to this directory, then add a volume to compose.dev.yml:
app-dev:
volumes:
- .:/limedoc/plugins/collabora.plugin
# Add the dependency:
- ../other-plugin.plugin:/limedoc/plugins/other.plugin
Then ./ldcmd up — the app loads all *.plugin directories in plugins/.
3. Multi-repo development (two plugins at once)
Check out the other plugin repo next to this one:
cd ..
git clone git@git.belowtoxic.cloud:limedoc-plugins/other.git other.plugin
Then add it as a bind-mount in compose.dev.yml as shown above. Both plugins
are mounted into the same app instance. No special ldcmd support required —
the app discovers every *.plugin directory at startup.
Startup order: The app loads plugins alphabetically. If your plugin
requiresanother, the dependency must be present on disk for the load plan to resolve. The composedepends_onin the sidecar template ensures the worker sidecar is healthy before the app starts, but for plugin-to-plugin dependencies no extra compose configuration is needed.
CI / CD
Push to main → Forgejo Actions runs .forgejo/workflows/publish.yml:
- Tests pass inside the
limedoc-devcontainer - Client bundles built; boundary check passes
plugin:packproducescollabora-{version}.zip+.sha256- OpenBao signs the content hash →
collabora-{version}.sig.json - Zip, sha256, and sig.json uploaded to the generic package registry (store)
- Same artifacts attached to a Forgejo Release
v{version}(operators)
The app installs plugins from the generic package registry at PACKAGE_STORE_URL.
Using Podman instead of Docker
# In .env (or export before running):
DOCKER_CMD=podman
./ldcmd up
ldcmd detects podman compose automatically.