Sandbox/Version demo: Difference between revisions
More languages
More actions
OHC identity seed |
OHC identity seed |
||
| (One intermediate revision by the same user not shown) | |||
| Line 4: | Line 4: | ||
|title=Version Demo |
|title=Version Demo |
||
|order=999 |
|order=999 |
||
|introduced= |
|introduced=4.0 |
||
}} |
}} |
||
{{Info|title=Sandbox demonstration|1=This page demonstrates the wiki's '''copy-on-write versioning + Cargo/SMW stack''' as a replacement for Docusaurus's versioned documentation model. Use the '''version dropdown''' in the badge strip above to navigate between versions — or read on for the full comparison.}} |
|||
This is a '''sandbox page''' demonstrating the wiki's copy-on-write versioning system. It is not real documentation. |
|||
== The problem with Docusaurus versioning == |
|||
== How it works == |
|||
When you run <code>npm run docusaurus docs:version 3.1</code>, Docusaurus copies the '''entire''' <code>docs/</code> tree into <code>versioned_docs/version-3.1/</code>. For the CARE documentation: |
|||
{{Info|title=Version history|1=This page was "introduced in 2.0". A frozen fork exists at [[Sandbox/Version demo/1.0]] representing the old v1.0 content. The version-switcher pills below the title are auto-generated from that subpage via a Cargo query.}} |
|||
* 98 pages per version |
|||
The versioning model: |
|||
* 2 versions (3.0, 3.1) = '''196 files''' committed to git |
|||
* Actual content difference between 3.0 and 3.1: '''zero bytes''' |
|||
Every edit to the "latest" docs must be manually backported (or not) to older versions. There's no query for "what changed" — you <code>diff</code> two directories. Navigation is hard-coded in <code>sidebars.js</code> files that must also be duplicated. |
|||
# '''Canonical page = latest.''' You are reading it now. |
|||
# '''Fork only on divergence.''' When content changes between releases, the old text is snapshotted to a subpage (<code>Page/1.0</code>) and marked <code>status=frozen</code>. |
|||
# '''Version switcher''' (rendered by <code><nowiki>{{Version switcher}}</nowiki></code>) queries Cargo for frozen subpages and shows clickable pills. |
|||
# '''Frozen banner''' on the old page links readers back here. |
|||
== |
== How this wiki solves it == |
||
=== Copy-on-write: fork only what diverges === |
|||
* '''On this page:''' look for the "Older versions: …" pill strip linking to <code>/1.0</code>. |
|||
* '''On the [[Sandbox/Version demo/1.0|frozen fork]]:''' look for the blue banner saying "You are viewing documentation frozen at …". |
|||
{| class="wikitable" |
|||
== Cleanup == |
|||
! Principle !! Implementation |
|||
|- |
|||
| '''Canonical = latest''' || You're reading it. One page, no prefixes, no duplication. |
|||
|- |
|||
| '''Fork on divergence''' || When content changes between releases, the old text is snapshotted to a subpage (<code>Page/3.0</code>) marked <code>status=frozen</code>. |
|||
|- |
|||
| '''Implicit version spanning''' || A page with <code>IntroducedIn=3.0</code> and empty <code>DeprecatedIn</code> is valid for 3.0, 3.1, 3.2, … — it doesn't need to be copied. |
|||
|- |
|||
| '''__NOINDEX__ on forks''' || Search engines only see the latest. No duplicate-content penalties. |
|||
|} |
|||
=== Global version dropdown (like Docusaurus navbar) === |
|||
This page and its subpage can be deleted once the demonstration is no longer needed. They are excluded from search via <code>__NOINDEX__</code> on the frozen fork and categorized under [[Category:Sandbox]]. |
|||
The dropdown in the badge strip above is injected by <code>MediaWiki:Common.js</code> on every page with <code><nowiki>{{Doc header}}</nowiki></code>. It: |
|||
# '''Persists''' your version choice in <code>localStorage</code> |
|||
# '''Auto-redirects''' on page load: if you've selected "3.0" and you navigate to a page that has a <code>/3.0</code> fork, you land there automatically |
|||
# '''Stays''' on the canonical page with a toast notification when no fork exists (because the content is unchanged) |
|||
# '''Works across the entire wiki''' — one global context, same as Docusaurus's URL-prefix approach |
|||
=== Cargo: structured version metadata === |
|||
Every page declares its version range in machine-readable Cargo fields. This enables: |
|||
'''Live query — all versions of this demo page:''' |
|||
{{#cargo_query:tables=Docs |
|||
|fields=_pageName=Page,IntroducedIn=Since,DeprecatedIn=Until,Status |
|||
|where=_pageName LIKE 'Sandbox/Version demo%' |
|||
|order by=IntroducedIn |
|||
|format=table |
|||
}} |
|||
'''What would "what's new in 4.0?" look like?''' |
|||
{{#cargo_query:tables=Docs |
|||
|fields=_pageName=Page,DocType=Type,Domain |
|||
|where=IntroducedIn='4.0' AND Status='current' |
|||
|format=table |
|||
|default=''(No real CARE pages are tagged 4.0 — this query would populate automatically when 4.0 ships.)'' |
|||
}} |
|||
In Docusaurus, answering "what changed in 3.1" requires diffing two directories of 98 files. Here it's one Cargo query. |
|||
=== SMW: automatic relationship graphs === |
|||
The <code><nowiki>{{Related}}</nowiki></code> template at the bottom of every doc page uses Semantic MediaWiki inverse queries. If page A declares <code>reference=Page B</code>, then page B's Related section '''automatically''' lists page A — no manual maintenance, no stale cross-references. Docusaurus has <code>onBrokenLinks: throw</code> at build time; we have '''live bidirectional links''' that never go stale because they're computed at render time. |
|||
== Head-to-head comparison == |
|||
{| class="wikitable" |
|||
! Dimension !! Docusaurus !! This wiki |
|||
|- |
|||
| '''Storage per version''' || Full tree copy (O(n × versions)) || Fork only diverged pages (O(changed)) |
|||
|- |
|||
| '''4 versions, 100 pages, 5 changes per version''' || '''400 files''' || '''115 pages''' (100 canonical + 15 forks) |
|||
|- |
|||
| '''Our actual case''' (98 pages, 3.0 ≡ 3.1) || 196 files (all identical) || '''98 pages''' (zero forks needed) |
|||
|- |
|||
| '''Global version dropdown''' || Built-in (navbar) || ✅ <code>MediaWiki:Common.js</code> (localStorage + auto-redirect) |
|||
|- |
|||
| '''Version persistence''' || URL path prefix (<code>/3.0/docs/...</code>) || localStorage (survives navigation, no URL noise) |
|||
|- |
|||
| '''"What changed in X?"''' || <code>diff -r</code> two directories || One Cargo query: <code>WHERE IntroducedIn='X'</code> |
|||
|- |
|||
| '''Cross-references''' || Relative paths; break silently without CI || SMW inverse queries; always current, never stale |
|||
|- |
|||
| '''Navigation/sidebar''' || Hand-maintained <code>sidebars.js</code> (duplicated per version) || Cargo query: <code>WHERE DocType='concept' ORDER BY Domain, SidebarOrder</code> |
|||
|- |
|||
| '''Broken link detection''' || Build-time (<code>onBrokenLinks: throw</code>) || '''Impossible by design''' — links are queries, not hard paths |
|||
|- |
|||
| '''Searchability of metadata''' || None (frontmatter is build-only) || Full: <code>Special:CargoTables</code>, <code>Special:Ask</code>, API queries |
|||
|- |
|||
| '''Edit workflow''' || PR → merge → rebuild → deploy || Edit in browser (or push.py) → live in seconds |
|||
|- |
|||
| '''i18n''' || Separate <code>i18n/</code> tree per locale || Translate extension: per-paragraph, tracks staleness |
|||
|- |
|||
| '''Release process''' || <code>npm run docs:version X</code> (copies everything) || Fork only changed pages + update one JS line |
|||
|- |
|||
| '''Structured field data''' || Markdown tables (not queryable) || Cargo <code>ModelField</code> table: 500 fields across 35 models, queryable |
|||
|- |
|||
| '''Glossary''' || None || Lingo extension: hover-definitions site-wide from one page |
|||
|} |
|||
== The version demo in action == |
|||
This page has '''three frozen forks''' showing progressive evolution: |
|||
* [[Sandbox/Version demo/1.0]] — email only, sync, 2 config variables |
|||
* [[Sandbox/Version demo/2.0]] — async + multi-channel + preferences |
|||
* [[Sandbox/Version demo/3.0]] — templates + tracking + push + batching + live Cargo table |
|||
Each fork only stores '''its own content''' — not copies of every other page in the wiki. The version dropdown lets you navigate between them exactly like Docusaurus's version picker, but without the storage explosion. |
|||
== Storage comparison (this demo) == |
|||
{| class="wikitable" |
|||
! Versions !! Docusaurus model !! Wiki model !! Savings |
|||
|- |
|||
| 1.0 || 1 full copy || 1 page (canonical at the time) || — |
|||
|- |
|||
| 2.0 || 2 full copies || 1 canonical + 1 fork || 50% |
|||
|- |
|||
| 3.0 || 3 full copies || 1 canonical + 2 forks || 67% |
|||
|- |
|||
| 4.0 || 4 full copies || 1 canonical + 3 forks || 75% |
|||
|- |
|||
! colspan="2" | At scale: 100 pages × 10 versions !! !! |
|||
|- |
|||
| (assuming 10% changes per release) || '''1000 files''' || '''190 pages''' (100 + 90 forks) || '''81%''' |
|||
|} |
|||
== Release checklist (vs Docusaurus) == |
|||
=== Docusaurus === |
|||
<syntaxhighlight lang="bash"> |
|||
# 1. Copy entire tree (even unchanged pages) |
|||
npm run docusaurus docs:version 4.1 |
|||
# 2. Update versions.json |
|||
# 3. Duplicate sidebars.js |
|||
# 4. Rebuild and deploy |
|||
npm run build && npm run deploy |
|||
# Total: hundreds of files touched, full CI/CD cycle |
|||
</syntaxhighlight> |
|||
=== This wiki === |
|||
<syntaxhighlight lang="bash"> |
|||
# 1. For each page that ACTUALLY CHANGED: |
|||
# - Copy current content to Page/4.0 subpage (mark frozen) |
|||
# - Update canonical page with new content |
|||
# 2. Update one line in MediaWiki:Common.js: |
|||
# KNOWN_VERSIONS = [ '4.1', '4.0', '3.1', ... ]; |
|||
# 3. Done. No build step. No deploy. Live immediately. |
|||
</syntaxhighlight> |
|||
== Try it yourself == |
|||
# '''Use the dropdown above''' — select "3.0" and you'll be taken to [[Sandbox/Version demo/3.0|the frozen 3.0 page]]. |
|||
# '''Navigate to another page''' (e.g. [[Concepts/Patient]]) — the dropdown shows your stored preference. Since Patient has no fork, you see a toast: "This page is unchanged in CARE 3.0". |
|||
# '''Select "4.0 (latest)"''' to return to the canonical view everywhere. |
|||
[[Category:Sandbox]] |
[[Category:Sandbox]] |
||
Latest revision as of 04:32, 5 July 2026
The problem with Docusaurus versioning
When you run npm run docusaurus docs:version 3.1, Docusaurus copies the entire docs/ tree into versioned_docs/version-3.1/. For the CARE documentation:
- 98 pages per version
- 2 versions (3.0, 3.1) = 196 files committed to git
- Actual content difference between 3.0 and 3.1: zero bytes
Every edit to the "latest" docs must be manually backported (or not) to older versions. There's no query for "what changed" — you diff two directories. Navigation is hard-coded in sidebars.js files that must also be duplicated.
How this wiki solves it
Copy-on-write: fork only what diverges
| Principle | Implementation |
|---|---|
| Canonical = latest | You're reading it. One page, no prefixes, no duplication. |
| Fork on divergence | When content changes between releases, the old text is snapshotted to a subpage (Page/3.0) marked status=frozen.
|
| Implicit version spanning | A page with IntroducedIn=3.0 and empty DeprecatedIn is valid for 3.0, 3.1, 3.2, … — it doesn't need to be copied.
|
| on forks | Search engines only see the latest. No duplicate-content penalties. |
Global version dropdown (like Docusaurus navbar)
The dropdown in the badge strip above is injected by MediaWiki:Common.js on every page with {{Doc header}}. It:
- Persists your version choice in
localStorage - Auto-redirects on page load: if you've selected "3.0" and you navigate to a page that has a
/3.0fork, you land there automatically - Stays on the canonical page with a toast notification when no fork exists (because the content is unchanged)
- Works across the entire wiki — one global context, same as Docusaurus's URL-prefix approach
Cargo: structured version metadata
Every page declares its version range in machine-readable Cargo fields. This enables:
Live query — all versions of this demo page:
| Page | Since | Until | Status |
|---|---|---|---|
| Sandbox/Version demo/1.0 | 1.0 | 2.0 | frozen |
| Sandbox/Version demo/2.0 | 2.0 | 3.0 | frozen |
| Sandbox/Version demo/3.0 | 3.0 | 4.0 | frozen |
| Sandbox/Version demo | 4.0 | current |
What would "what's new in 4.0?" look like?
| Page | Type | Domain |
|---|---|---|
| Sandbox/Version demo | guide | platform |
In Docusaurus, answering "what changed in 3.1" requires diffing two directories of 98 files. Here it's one Cargo query.
SMW: automatic relationship graphs
The {{Related}} template at the bottom of every doc page uses Semantic MediaWiki inverse queries. If page A declares reference=Page B, then page B's Related section automatically lists page A — no manual maintenance, no stale cross-references. Docusaurus has onBrokenLinks: throw at build time; we have live bidirectional links that never go stale because they're computed at render time.
Head-to-head comparison
| Dimension | Docusaurus | This wiki |
|---|---|---|
| Storage per version | Full tree copy (O(n × versions)) | Fork only diverged pages (O(changed)) |
| 4 versions, 100 pages, 5 changes per version | 400 files | 115 pages (100 canonical + 15 forks) |
| Our actual case (98 pages, 3.0 ≡ 3.1) | 196 files (all identical) | 98 pages (zero forks needed) |
| Global version dropdown | Built-in (navbar) | ✅ MediaWiki:Common.js (localStorage + auto-redirect)
|
| Version persistence | URL path prefix (/3.0/docs/...) |
localStorage (survives navigation, no URL noise) |
| "What changed in X?" | diff -r two directories |
One Cargo query: WHERE IntroducedIn='X'
|
| Cross-references | Relative paths; break silently without CI | SMW inverse queries; always current, never stale |
| Navigation/sidebar | Hand-maintained sidebars.js (duplicated per version) |
Cargo query: WHERE DocType='concept' ORDER BY Domain, SidebarOrder
|
| Broken link detection | Build-time (onBrokenLinks: throw) |
Impossible by design — links are queries, not hard paths |
| Searchability of metadata | None (frontmatter is build-only) | Full: Special:CargoTables, Special:Ask, API queries
|
| Edit workflow | PR → merge → rebuild → deploy | Edit in browser (or push.py) → live in seconds |
| i18n | Separate i18n/ tree per locale |
Translate extension: per-paragraph, tracks staleness |
| Release process | npm run docs:version X (copies everything) |
Fork only changed pages + update one JS line |
| Structured field data | Markdown tables (not queryable) | Cargo ModelField table: 500 fields across 35 models, queryable
|
| Glossary | None | Lingo extension: hover-definitions site-wide from one page |
The version demo in action
This page has three frozen forks showing progressive evolution:
- Sandbox/Version demo/1.0 — email only, sync, 2 config variables
- Sandbox/Version demo/2.0 — async + multi-channel + preferences
- Sandbox/Version demo/3.0 — templates + tracking + push + batching + live Cargo table
Each fork only stores its own content — not copies of every other page in the wiki. The version dropdown lets you navigate between them exactly like Docusaurus's version picker, but without the storage explosion.
Storage comparison (this demo)
| Versions | Docusaurus model | Wiki model | Savings |
|---|---|---|---|
| 1.0 | 1 full copy | 1 page (canonical at the time) | — |
| 2.0 | 2 full copies | 1 canonical + 1 fork | 50% |
| 3.0 | 3 full copies | 1 canonical + 2 forks | 67% |
| 4.0 | 4 full copies | 1 canonical + 3 forks | 75% |
| At scale: 100 pages × 10 versions | |||
| (assuming 10% changes per release) | 1000 files | 190 pages (100 + 90 forks) | 81% |
Release checklist (vs Docusaurus)
Docusaurus
# 1. Copy entire tree (even unchanged pages)
npm run docusaurus docs:version 4.1
# 2. Update versions.json
# 3. Duplicate sidebars.js
# 4. Rebuild and deploy
npm run build && npm run deploy
# Total: hundreds of files touched, full CI/CD cycle
This wiki
# 1. For each page that ACTUALLY CHANGED:
# - Copy current content to Page/4.0 subpage (mark frozen)
# - Update canonical page with new content
# 2. Update one line in MediaWiki:Common.js:
# KNOWN_VERSIONS = [ '4.1', '4.0', '3.1', ... ];
# 3. Done. No build step. No deploy. Live immediately.
Try it yourself
- Use the dropdown above — select "3.0" and you'll be taken to the frozen 3.0 page.
- Navigate to another page (e.g. Concepts/Patient) — the dropdown shows your stored preference. Since Patient has no fork, you see a toast: "This page is unchanged in CARE 3.0".
- Select "4.0 (latest)" to return to the canonical view everywhere.