World-Office: Building a Self-Hosted, Open-Source Document Editing Suite
· ~6 min readWhy Build Another Office Suite?
The modern enterprise runs on documents. Yet the two dominant document editing platforms — Microsoft 365 and Google Workspace — share fundamental problems:
- Vendor lock-in: Proprietary formats, closed protocols, and deep ecosystem integrations make migration prohibitively expensive
- Data sovereignty: Documents live on US-controlled infrastructure, subject to the CLOUD Act and foreign data access laws
- Recurring cost escalation: Subscription costs at hyperscaler rates compound annually — Microsoft 365 alone rose over 30% between 2020 and 2025
European institutions are increasingly aware of this. Germany's public sector has been migrating toward open-source alternatives like openDesk (by Open Code & Sovereign Cloud Stack). But the ecosystem remains fragmented: there is no single, self-hostable office suite that combines modern web editing with native desktop performance, comprehensive format support, and full protocol interoperability.
That gap is what World-Office aims to fill.
Architecture: Rust Core + TypeScript Frontend + Tauri Shell
World-Office is designed from the ground up as a modular, layered system. The key insight is that document editing involves three fundamentally different concerns — parsing, editing, and protocol handling — and each demands different technology choices.
┌────────────────────────────────────────────┐
│ Desktop App (Tauri) │
│ ┌──────────────────────────────────────┐ │
│ │ Web Editor (React / WYSIWYG) │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ Rust Backend (Tauri Commands) │ │
│ │ - Session/file management │ │
│ │ - Plugin system │ │
│ │ - Update mechanism │ │
│ │ - Window/tray management │ │
│ └──────────────────────────────────────┘ │
└────────────────────────────────────────────┘
┌────────────────────────────────────────────┐
│ Server (Rust + Tokio) │
│ ┌──────────────────────────────────────┐ │
│ │ 16 Format Crates (DOCX, ODT, XLSX, │ │
│ │ PDF, EPUB, Markdown, LaTeX, ...) │ │
│ │ Each implements FormatRoundtrip trait │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ 8 Microservices (Rust) + 1 Node.js │ │
│ │ - WOPI protocol bridge │ │
│ │ - Document conversion (DocBuilder) │ │
│ │ - WebDAV sync │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ Nextcloud Integration (PHP + Vue 3) │ │
│ └──────────────────────────────────────┘ │
└────────────────────────────────────────────┘
The Rust Core (26 Crates)
The server-side core is written entirely in Rust, organized as a workspace of 26 crates. The format layer is the crown jewel: 16 dedicated format crates, each implementing the FormatRoundtrip trait for parsing and serialization. Supported formats include:
- Office formats: DOCX, ODT, XLSX, ODS, PPTX, ODP
- Document formats: PDF, EPUB, Markdown, HTML, LaTeX, Plain Text
- Web formats: SRT (subtitles), JSON, XML, CSV
- Archive formats: ZIP (container-level operations)
Each format crate is independently testable and follows the same trait interface, making it straightforward to add new formats without touching existing code.
The service layer comprises 8 Rust microservices (plus one Node.js service for the DocBuilder CLI — the document conversion tool). A WOPI (Web Application Open Platform Interface) bridge enables interoperability with existing WOPI-compatible storage backends like Nextcloud, ownCloud, and Collabora.
The TypeScript Frontend
The web editor lives in a monorepo under apps/web/, structured as a Turborepo-managed TypeScript project. It provides a vanilla JS WYSIWYG editor layer with React wrappers, designed so the editing experience can be embedded either in a browser (via the web server) or in the desktop app (via Tauri's WebView).
The build pipeline produces a static dist that the Tauri desktop shell loads as its frontend — no separate web server required for the desktop variant.
The Tauri Desktop App
The desktop proof-of-concept wraps the web editor in a native Tauri 2 shell. It provides:
- Native file system access via Tauri's file dialogs and drag-and-drop
- File association handling (.docx, .odt, .pdf, etc.)
- Session management — remembers open documents across restarts
- System tray integration with quick-access menus
- Settings persistence (appearance, editor, network, plugin settings)
- Plugin system — JavaScript plugins are loaded from a plugin directory, sandboxed, and can extend editor functionality without recompiling
- Built-in update mechanism — checks for new releases, downloads, verifies SHA256 checksum, and installs platform-appropriately (dpkg on Linux, msiexec on Windows, hdiutil on macOS)
Why Tauri over Electron? The desktop app does not need Node.js runtime features — it is a pure document viewer/editor. The binary is under 20 MB compressed, memory usage is approximately half of an equivalent Electron app, and the attack surface is substantially smaller (no Node.js integration).
Format Roundtrip: The Core Engineering Challenge
The most technically demanding part of World-Office is the format roundtrip system. The constraint is deceptively simple: parsing a document and re-serializing it must produce a file that opens identically in the original application.
This is far harder than it sounds. DOCX files, for example, are ZIP archives containing a complex tree of XML files, with styles, numbering definitions, font tables, footnotes, endnotes, headers, footers, and relationships all spread across separate files. A parser must preserve:
- All XML namespaces and attributes, even unrecognized ones
- Relationship IDs between document parts
- Binary blobs (embedded images, OLE objects)
- ZIP archive structure — order of entries, compression method, extra fields
- Content types for every part
The FormatRoundtrip trait enforces this contract at compile time:
#[async_trait]
pub trait FormatRoundtrip: Send + Sync {
/// Parse raw bytes into the canonical document model
async fn parse(&self, data: &[u8]) -> Result<Box<dyn Document>>;
/// Re-serialize back to bytes
async fn serialize(&self, doc: &dyn Document) -> Result<Vec<u8>>;
/// Roundtrip: parse + serialize + byte-level comparison
async fn roundtrip(&self, data: &[u8]) -> Result<Vec<u8>> {
let doc = self.parse(data).await?;
self.serialize(&doc).await
}
}
Each format crate includes roundtrip tests that verify the parsing and serialization produce bitwise-identical output for a library of test documents.
CI/CD: Forgejo Actions on Codeberg
The entire project is hosted on Codeberg — a Europe-hosted, free-software Git platform. CI is powered by Forgejo Actions, Codeberg's built-in runner infrastructure.
The CI pipeline runs on shared codeberg-medium runners (4 CPU, 8 GB RAM) and covers:
- Rust: Linting (clippy + rustfmt), unit tests across all 26 crates (
--test-threads=1for filesystem isolation), build checks for all targets - TypeScript: Biome linting,
tsctype checking,pnpm buildacross the Turborepo monorepo - Release: Automated Tauri builds on tag push, producing .deb and AppImage artifacts, with the release published back to Codeberg
Release pipeline note: The initial release pipeline was blocked by
has_actions: False(Forgejo Actions must be explicitly enabled per repo) and workflows referencingdocker://node:20-bookwormimages (Codeberg shared runners only support their own labels). Both issues were resolved: Actions were enabled via the API, and all 7 workflow files were migrated tocodeberg-mediumrunners.
Desktop POC Status
The desktop proof-of-concept has reached a functional state. Key metrics:
| Metric | Value |
|---|---|
| Rust source files | 16 modules |
| Tauri commands registered | 68 |
| Rust unit tests | 8 (all passing) |
| Vitest integration tests | 17 passing, 1 skipped |
| Binary size | ~19 MB |
| Bundle size (.deb) | 5.9 MB |
| Build targets | deb, rpm, AppImage, msi (Windows), dmg (macOS) |
| Build system | Rust nightly + pnpm + Turborepo + Tauri 2 |
Cross-Platform Support
All Rust modules use platform-abstraction APIs (tokio::fs, std::path::Path, dirs crate, keyring crate). The only platform-specific code is in the update installer, which dispatches to the appropriate system tool:
- Linux:
pkexec dpkg -ifor .deb packages - Windows:
msiexec /ifor .msi installers - macOS:
hdiutil attach→ bundle copy →hdiutil detachfor .dmg disk images
The Road Ahead
World-Office is under active development. The immediate priorities are:
- Complete the format roundtrip test suite — achieving high-coverage, real-world document roundtrip verification across all 16 format crates
- Productionize the desktop app — window management, print support, offline mode, and the plugin ecosystem
- WOPI protocol maturity — enabling seamless integration with Nextcloud, ownCloud, and other OpenCloud storage backends
- Windows CI runner — self-hosted Windows runner to enable automated .msi builds
- GPG-signed .deb repository — once the signing key passphrase is recovered, automated publishing to
graphwiz-ai/debian-repo
The most important architectural decision was the language choice. Rust gives us memory safety without garbage collection, deterministic performance for document parsing, and a compiler that catches entire categories of bugs at build time. TypeScript on the frontend gives us fast iteration on the editing experience. Tauri bridges the two with a minimal native shell.
World-Office is free software (AGPL-3.0 for the server, MIT for artwork). The source code is at codeberg.org/World-Office/server. Contributions, bug reports, and discussions are welcome.
Never miss a deep-dive
Get notified when I publish new articles on AI infrastructure, DevOps, and XR development.