Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Sandbox/Version demo: Difference between revisions

From OHC Network Wiki
Content deleted Content added
OHC identity seed
OHC identity seed
 
Line 7: Line 7:
}}
}}


{{Info|title=Sandbox page|1=This page demonstrates the wiki's '''copy-on-write versioning system'''. It is not real documentation. The frozen forks below show how content evolves across releases without duplicating the entire tree.}}
{{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.}}


== The problem with Docusaurus versioning ==
== Notification system (v4.0 — current) ==


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:
The notification system handles all outbound communication from the platform to users, providers, and external systems.


* 98 pages per version
=== Channels ===
* 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.

== How this wiki solves it ==

=== Copy-on-write: fork only what diverges ===


{| class="wikitable"
{| class="wikitable"
! Principle !! Implementation
! Channel !! Added in !! v4.0 changes
|-
| Email || 1.0 || MJML templates + AMP for interactive emails
|-
|-
| '''Canonical = latest''' || You're reading it. One page, no prefixes, no duplication.
| In-app || 2.0 || Unified inbox with thread grouping
|-
|-
| '''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>.
| SMS || 2.0 || Smart routing (cost-optimized per region)
|-
|-
| '''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.
| Push (mobile) || 3.0 || Rich media attachments, action buttons
|-
|-
| '''__NOINDEX__ on forks''' || Search engines only see the latest. No duplicate-content penalties.
| Webhook || 3.0 || Now supports HMAC signing + retry policies
|-
| WhatsApp || '''4.0''' || Via official Business API
|-
| Slack/Teams || '''4.0''' || Org-configurable bot integrations
|}
|}


=== Global version dropdown (like Docusaurus navbar) ===
=== Scheduling & orchestration ===


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:
New in v4.0 — notifications can be scheduled, cancelled, and A/B tested:


# '''Persists''' your version choice in <code>localStorage</code>
<syntaxhighlight lang="json">
# '''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)
"template": "appointment_reminder",
# '''Works across the entire wiki''' — one global context, same as Docusaurus's URL-prefix approach
"recipients": ["patient:uuid-123"],

"channels": ["email", "whatsapp"],
=== Cargo: structured version metadata ===
"schedule": {

"send_at": "2026-07-10T08:00:00Z",
Every page declares its version range in machine-readable Cargo fields. This enables:
"cancel_if": "appointment.status == 'cancelled'"

},
'''Live query — all versions of this demo page:'''
"variants": {

"control": { "subject": "Appointment tomorrow" },
{{#cargo_query:tables=Docs
"test_a": { "subject": "See you tomorrow, {{patient.first_name}}!" }
|fields=_pageName=Page,IntroducedIn=Since,DeprecatedIn=Until,Status
}
|where=_pageName LIKE 'Sandbox/Version demo%'
}
|order by=IntroducedIn
</syntaxhighlight>
|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.
=== Per-organization configuration ===


== Head-to-head comparison ==
Organizations can now override global channel settings:


{| class="wikitable"
{| class="wikitable"
! Setting !! Scope !! Description
! Dimension !! Docusaurus !! This wiki
|-
|-
| '''Storage per version''' || Full tree copy (O(n × versions)) || Fork only diverged pages (O(changed))
| Enabled channels || Per org || Which channels are active
|-
|-
| '''4 versions, 100 pages, 5 changes per version''' || '''400 files''' || '''115 pages''' (100 canonical + 15 forks)
| Sender identity || Per org || From address, WhatsApp number, bot name
|-
|-
| '''Our actual case''' (98 pages, 3.0 ≡ 3.1) || 196 files (all identical) || '''98 pages''' (zero forks needed)
| Quiet hours || Per org || Suppress non-urgent sends during configured windows
|-
|-
| '''Global version dropdown''' || Built-in (navbar) || ✅ <code>MediaWiki:Common.js</code> (localStorage + auto-redirect)
| Fallback chain || Per org || e.g. try Push → SMS → Email in order
|-
| '''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 ==
=== Architecture (v4.0) ===


This page has '''three frozen forks''' showing progressive evolution:
<syntaxhighlight lang="text">

Action / Scheduler / API
* [[Sandbox/Version demo/1.0]] — email only, sync, 2 config variables
* [[Sandbox/Version demo/2.0]] — async + multi-channel + preferences
Orchestrator (evaluates schedule, cancel_if, variant selection)
* [[Sandbox/Version demo/3.0]] — templates + tracking + push + batching + live Cargo table

Fan-out (per recipient × channel, respects fallback chain)
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.
Queue (Redis Streams, partitioned by priority)
Workers (channel-specific adapters, batch-aware)
Delivery tracker (status, attempts, receipts, analytics)
</syntaxhighlight>


== Storage comparison (this demo) ==
== Evolution summary ==


{| class="wikitable"
{| class="wikitable"
! Version !! Key additions !! Pages in Docusaurus model !! Pages in wiki model
! Versions !! Docusaurus model !! Wiki model !! Savings
|-
|-
| 1.0 || Email only, sync || 1 page × 1 version = '''1''' || [[Sandbox/Version demo/1.0|1 frozen fork]]
| 1.0 || 1 full copy || 1 page (canonical at the time) ||
|-
|-
| 2.0 || 2 full copies || 1 canonical + 1 fork || 50%
| 2.0 || Async, SMS, in-app, preferences || copy entire tree = '''2''' total || [[Sandbox/Version demo/2.0|1 frozen fork]]
|-
|-
| 3.0 || 3 full copies || 1 canonical + 2 forks || 67%
| 3.0 || Templates, push, webhooks, tracking, batching || copy entire tree = '''3''' total || [[Sandbox/Version demo/3.0|1 frozen fork]]
|-
|-
| 4.0 || 4 full copies || 1 canonical + 3 forks || 75%
| 4.0 || WhatsApp, Slack, scheduling, A/B, per-org config || copy entire tree = '''4''' total || '''1 canonical page''' (you're reading it)
|-
|-
! colspan="2" | '''Total file/page count''' !! '''4 full copies''' !! '''4 pages''' (1 current + 3 forks)
! 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) ==
{{Note|1=In a real doc site with 100 pages, Docusaurus would store '''400 files''' for 4 versions (most identical). This wiki stores '''103 pages''' — the 100 canonical pages plus only the 3 that actually diverged.}}


=== Docusaurus ===
== How the versioning works ==


<syntaxhighlight lang="bash">
# '''Canonical page = latest.''' You are reading it.
# 1. Copy entire tree (even unchanged pages)
# '''Fork only when content changes.''' Unchanged pages span all versions implicitly (their <code>IntroducedIn</code> field covers the full range).
npm run docusaurus docs:version 4.1
# '''Version switcher''' (the pill strip below the title ↑) is auto-generated: <code><nowiki>{{Version switcher}}</nowiki></code> queries Cargo for subpages with <code>Status=frozen</code>.
# '''Frozen banner''' on old pages links readers back to this canonical page.
# '''"What changed in version X?"''' is a single Cargo query: <code><nowiki>{{#cargo_query: tables=Docs | where=IntroducedIn='4.0'}}</nowiki></code>


== Live query: all versions of this page ==
# 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
{{#cargo_query:tables=Docs
</syntaxhighlight>
|fields=_pageName=Page,IntroducedIn=Introduced,DeprecatedIn=Deprecated,Status

|where=_pageName LIKE 'Sandbox/Version demo%'
=== This wiki ===
|order by=IntroducedIn

|format=table
<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

guideplatformCARE 4.0+
ℹ️ Sandbox demonstration
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.

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:

  1. Persists your version choice in localStorage
  2. Auto-redirects on page load: if you've selected "3.0" and you navigate to a page that has a /3.0 fork, you land there automatically
  3. Stays on the canonical page with a toast notification when no fork exists (because the content is unchanged)
  4. 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:

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

  1. Use the dropdown above — select "3.0" and you'll be taken to the frozen 3.0 page.
  2. 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".
  3. Select "4.0 (latest)" to return to the canonical view everywhere.