diff --git a/.github/workflows/site-sync.yml b/.github/workflows/site-sync.yml
new file mode 100644
index 0000000..3d55883
--- /dev/null
+++ b/.github/workflows/site-sync.yml
@@ -0,0 +1,49 @@
+name: Site Sync
+
+on:
+ push:
+ branches: [main]
+ paths:
+ - "data/site.json"
+ - "index.html"
+ - "scripts/sync-site.py"
+ - ".github/workflows/site-sync.yml"
+ pull_request:
+ paths:
+ - "data/site.json"
+ - "index.html"
+ - "scripts/sync-site.py"
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ sync:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Verify (pull requests)
+ if: github.event_name == 'pull_request'
+ run: |
+ python3 scripts/test_sync_site.py
+ python3 scripts/sync-site.py --check
+
+ - name: Sync, test, and commit (push / manual)
+ if: github.event_name != 'pull_request'
+ run: |
+ # Sync first so the in-sync guard test passes on the exact drift it repairs.
+ python3 scripts/sync-site.py
+ python3 scripts/test_sync_site.py
+ if ! git diff --quiet index.html; then
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git add index.html
+ git commit -m "chore: sync landing page from data/site.json [skip ci]"
+ git push
+ fi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7a60b85
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+__pycache__/
+*.pyc
diff --git a/data/site.json b/data/site.json
new file mode 100644
index 0000000..5cab01f
--- /dev/null
+++ b/data/site.json
@@ -0,0 +1,17 @@
+{
+ "_comment": "Single source of truth for the landing page's dynamic data. Run scripts/sync-site.py (or the site-sync workflow) to inject these into index.html. Edit values here, never inline in index.html.",
+ "values": {
+ "synced": "2026-05-24"
+ },
+ "organs": [
+ { "label": "ORGAN-I (Theoria)", "url": "https://organvm-i-theoria.github.io/" },
+ { "label": "ORGAN-II (Poiesis)", "url": "https://organvm-ii-poiesis.github.io/" },
+ { "label": "ORGAN-III (Ergon)", "url": "https://organvm-iii-ergon.github.io/" },
+ { "label": "ORGAN-IV (Taxis)", "url": "https://organvm-iv-taxis.github.io/" },
+ { "label": "ORGAN-V (Logos)", "url": "https://organvm-v-logos.github.io/" },
+ { "label": "ORGAN-VI (Koinonia)", "url": "https://organvm-vi-koinonia.github.io/" },
+ { "label": "ORGAN-VII (Kerygma)", "url": "https://organvm-vii-kerygma.github.io/" },
+ { "label": "META-ORGANVM", "url": "https://meta-organvm.github.io/" },
+ { "label": "Personal Profile", "url": "https://4444j99.github.io/", "active": true }
+ ]
+}
diff --git a/index.html b/index.html
index ceb97dc..3a18d7c 100644
--- a/index.html
+++ b/index.html
@@ -31,6 +31,7 @@
@@ -90,7 +92,7 @@ Personal Profile