# ownCloud Docs — Monorepo Consolidation & Stack Modernization
**Status:** Proposed — awaiting consensus
**Date:** 2026-06-15
## Problem
The ownCloud documentation is spread across 9 repositories:
- `owncloud/docs` — orchestrator: `site.yml` aggregates content, holds the
Antora/AsciiDoc extensions, `global-attributes.yml`, and the CI that builds
and deploys to GitHub Pages (`doc.owncloud.com`).
- 7 content repos — `docs-main`, `docs-server`, `docs-ocis`, `docs-webui`,
`docs-client-desktop`, `docs-client-ios-app`, `docs-client-android`. Each is
an Antora component with multiple maintained version branches
(e.g. `master`, `10.16`, `10.15`).
- `owncloud/docs-ui` — a Gulp/Browserify/jQuery-built Antora UI theme published
as `ui-bundle.zip` and pulled in at build time.
Two pains drive this rework:
1. Repo and branch sprawl. A single fix can require cherry-picks (backports)
across N branches across several repos. Branch protection, commit signing,
conventional-commit titles, and CI all multiply per branch/repo.
2. The tech stack is up for genuine re-evaluation — not change for its own
sake, but an honest check of whether each piece still earns its place.
## Decisions
| Area | From | To |
|------|------|-----|
| Repos | 9 | 1 monorepo (`owncloud/docs`); others archived |
| Branches | `master` + N version branches per repo | `master` only |
| Versions | git branches + backporting | folders, real version numbers, `prerelease` marker |
| Search | Elasticsearch + custom index extension + CI secrets | Pagefind (static, build-time) |
| UI | custom Gulp/Browserify/jQuery theme + `ui-bundle.zip` release | stock default UI + small supplemental branding |
| Content sources | 7 remote GitHub repos × branches | local folders |
| Global attributes | fetched from GitHub at build | local file |
| Core stack | Antora + AsciiDoc | kept (with tabs / remote-include / Kroki / Mermaid extensions) |
### Why keep Antora + AsciiDoc
The pain is structural (repos/branches), not the authoring tool. Antora is
purpose-built for exactly this shape of problem:
- Native multi-version + multi-component support, version switcher,
cross-component xrefs, and `latest` URL handling — our exact use case.
- AsciiDoc is materially more capable than Markdown for technical docs:
includes/partials, conditional content (`ifdef`), attributes/variables,
admonitions, real tables, callouts. The content already leans on these.
- Stable, boring, low-churn tooling.
A migration to MkDocs Material or Astro Starlight would impose a large, lossy
AsciiDoc→Markdown conversion and weaker native versioning, to solve a problem
(contributor familiarity) that is smaller than the structural pain the
consolidation already removes.
## Design
### 1. Repository structure
docs/
├─ site.yml # Antora playbook (local content sources only)
├─ package.json # one toolchain: antora + asciidoctor + extensions
├─ antora-extensions/ # ex ext-antora/ (shared, no longer duplicated)
├─ asciidoc-extensions/ # ex ext-asciidoc/ (tabs, remote-include)
├─ global-attributes.yml # local file, not fetched from GitHub
├─ ui/
│ └─ supplemental/ # logo, colors, tabs CSS/JS, pagefind widget
├─ content/
│ ├─ main/ # landing pages (ROOT component)
│ ├─ server/ {11.0, 10.16, 10.15}/
│ ├─ ocis/ {8.1, 8.0, 7.3}/
│ ├─ webui/ {…}/
│ ├─ desktop/ {7.0, 6.0, 5.3}/
│ ├─ ios/ # single version (latest-only)
│ └─ android/ # single version (latest-only)
└─ .github/workflows/ci.yml
Each product is an Antora component; each version folder carries its own
`antora.yml` declaring `version:`. `master` is the only branch.
### 2. Versioning — real version numbers, no magic `next`
There is no `next` folder. Each in-development version uses its real,
known version number with Antora's `prerelease` key:
# content/ocis/8.1/antora.yml
name: ocis
version: '8.1'
prerelease: true # marks it unpublished / in development
display_version: '8.1 (dev)' # optional label in the version switcher
- Folder named for the actual upcoming version (`8.1`, `11.0`) — no indirection.
- `prerelease: true` keeps it out of the `latest` URL segment and shows a visible
marker in the version dropdown.
- On release: remove `prerelease: true` (and the `(dev)` label). No rename, no
branch cut, no content move — it becomes the latest released version.
- This removes the awkward `latest-server-version: 'next@'` soft-set attributes;
the version key is the source of truth.
Per-product version policy:
- Multi-version (folders): Server/classic, oCIS, desktop, webui.
- Latest-only (single folder): iOS and Android — the app stores carry only
one version, so the docs reflect that.
Backporting is replaced by "edit the folders it applies to." Day-to-day work
lands in the current prerelease folder (e.g. `ocis/8.1/`); a fix that also applies
to a shipped version is copied into that version's folder in the same PR. Shared
content drift is mitigated with AsciiDoc includes (a shared partial included into
each version folder).
### 3. Build & CI
A single `npm run antora` builds the whole site from local content (no remote
fetches), then Pagefind indexes the output, then it deploys.
on:
push: { branches: [master] }
pull_request:
jobs:
build:
steps:
- checkout
- setup-node (22)
- npm ci
- npm run antora # antora site.yml → public/
- npx pagefind --site public # inject static search index into public/
- if push to master → deploy public/ to gh-pages (CNAME doc.owncloud.com)
Changes vs. today:
- No remote content sources. `site.yml` `content.sources` becomes local
paths instead of seven GitHub URLs × multiple branches. Fully reproducible
offline; no network flakiness.
- `global-attributes.yml` is local — the GitHub-fetch path in
`load-global-site-attributes.js` is dropped (extension can be retired and
folded into `site.yml` `asciidoc.attributes`).
- No Elasticsearch secrets. `generate-index.js` and the four
`ELASTICSEARCH_*` CI secrets are deleted.
- No `ui-bundle.zip` release dependency. The cross-repo "publish UI release →
docs build pulls it" handshake disappears.
- PR builds validate the full site (and may run the broken-link check); only
`master` deploys.
Extensions that remain (they earn their keep) and move into
`antora-extensions/` / `asciidoc-extensions/`, no longer duplicated:
`tabs.js`, `remote-include-processor.js`, Kroki/Mermaid, `comp-version`,
`sitemap-cleanup`.
### 4. Search — Pagefind
- Build-time, post-Antora: `npx pagefind --site public` crawls the generated
HTML and writes a static, chunked index (`public/pagefind/`). No server, no
secrets, no index-generation extension.
- UI integration: wire Pagefind's JS API into the stock UI search box
(small JS + CSS in `ui/supplemental/`).
- Scoping: emit Antora attributes as `data-pagefind-filter` (component, version)
so search can be scoped to e.g. "oCIS 8.0" or run site-wide.
- Deleted: `@elastic/elasticsearch`, `generate-index.js`, `es-docker-compose.yml`,
and the four `ELASTICSEARCH_*` secrets.
### 5. UI — supplemental branding on the stock default UI
The custom `docs-ui` repo and its Gulp/Browserify/jQuery build are retired.
- Base: Antora's stock default UI bundle (maintained upstream, no build on
our side).
- Branding via `supplemental_files`: a small `ui/supplemental/` folder layered
on at build time — ownCloud logo/favicon, brand-color CSS override, footer text,
and the few behaviors not in the stock UI: tabs, copy-to-clipboard, and
the Pagefind search widget.
- Version switcher, mobile nav, breadcrumbs, on-this-page TOC, and anchor
scrolling are already in the stock UI — the custom JS files
(`01-nav` … `07-breadcrumbs`) are dropped.
- `site.yml` points `ui.bundle.url` at the stock default UI release and sets
`ui.supplemental_files: ./ui/supplemental`.
Trade-off: pixel-level theme control is reduced. Individual stock templates
can still be overridden via supplemental files; a full fork of the default UI
remains a fallback if a future design demands it. For a docs site this is almost
always sufficient.
## Out of scope
- Content rewriting / restructuring beyond moving into version folders.
- PDF generation (already dropped from the current build; can be re-added later).
- Any change to the published URL scheme (`doc.owncloud.com`) beyond what the
version-folder model implies.
## Migration outline (high level)
1. Create the monorepo skeleton (`content/`, `ui/supplemental/`, extensions).
2. Import each content repo's `master` into `content/<product>/<version>/`, and
each maintained version branch into its own version folder.
3. Localize `global-attributes.yml`; rewrite `site.yml` content sources to local
paths; set `prerelease` on in-development versions.
4. Swap search to Pagefind; delete the Elasticsearch extension and secrets.
5. Swap UI to stock default + `ui/supplemental/`; retire `docs-ui`.
6. Rewrite CI to the single build → Pagefind → deploy flow.
7. Verify the built site (version switcher, search, tabs, diagrams, redirects),
then archive the old repos.
Summary
This is an RFC to consolidate the 9 documentation repositories into a single monorepo and modernize parts of the build stack, while keeping Antora + AsciiDoc as the core authoring/build tooling.
No work has started. This issue exists to gather consensus before moving on. Please react / comment with agreement, concerns, or alternatives.
Current setup (the problem)
Documentation today spans 9 repos:
owncloud/docs— orchestrator:site.ymlaggregates content, holds the Antora/AsciiDoc extensions,global-attributes.yml, and the CI that builds + deploys to GitHub Pages (doc.owncloud.com).docs-main,docs-server,docs-ocis,docs-webui,docs-client-desktop,docs-client-ios-app,docs-client-android. Each is an Antora component with multiple maintained version branches (e.g.master,10.16,10.15).owncloud/docs-ui— a Gulp/Browserify/jQuery UI theme published asui-bundle.zipand pulled in at build time.Two pains drive this:
Proposed decisions
owncloud/docs); others archivedmaster+ N version branches per repomasteronlyprereleasemarkerui-bundle.zipreleaseWhy keep Antora + AsciiDoc
The pain is structural (repos/branches), not the authoring tool. Antora is purpose-built for multi-version, multi-component technical docs (version switcher, cross-component xrefs,
latestURL handling), and AsciiDoc is materially more capable than Markdown for our content (includes/partials, conditional content, attributes, admonitions, tables, callouts) — which our content already relies on. A migration to MkDocs/Astro would impose a large, lossy AsciiDoc→Markdown conversion and weaker native versioning to solve a smaller problem than consolidation already removes.Versioning — no magic
nextThere is no
nextfolder. Each in-development version uses its real version number with Antora'sprereleasekey:On release: drop
prerelease: true(and the(dev)label). No rename, no branch cut, no content move.Per-product policy:
Backporting is replaced by "edit the folders it applies to." Shared content drift is mitigated with AsciiDoc includes.
Full design spec
Click to expand the complete design document (
2026-06-15-owncloud-docs-monorepo-design.md)Open questions for reviewers
doc.owncloud.compaths (the static redirect facility should cover renames).Please weigh in. 🙏
🤖 Generated with Claude Code