Restructure SX docs nav into 4 top-level sections with nested routing

New hierarchy: Geography (Reactive Islands, Hypermedia Lakes, Marshes,
Isomorphism), Language (Docs, Specs, Bootstrappers, Testing),
Applications (CSSX, Protocols), Etc (Essays, Philosophy, Plans).

All routes updated to match: /reactive/* → /geography/reactive/*,
/docs/* → /language/docs/*, /essays/* → /etc/essays/*, etc.
Updates nav-data.sx, all defpage routes, API endpoints, internal links
across 43 files. Enhanced find-nav-match for nested group resolution.

Also includes: page-helpers-demo sf-total fix (reduce instead of set!),
rebootstrapped sx-browser.js and sx_ref.py, defensive slice/rest guards.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 18:50:31 +00:00
parent 0174fbfea3
commit 4d54be6b6b
43 changed files with 813 additions and 746 deletions

View File

@@ -13,20 +13,30 @@
:content (~sx-doc :path "/" (~sx-home-content)))
;; ---------------------------------------------------------------------------
;; Docs section
;; Language section (parent of Docs, Specs, Bootstrappers, Testing)
;; ---------------------------------------------------------------------------
(defpage language-index
:path "/language/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/language/"))
;; ---------------------------------------------------------------------------
;; Docs section (under Language)
;; ---------------------------------------------------------------------------
(defpage docs-index
:path "/docs/"
:path "/language/docs/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/docs/" (~docs-introduction-content)))
:content (~sx-doc :path "/language/docs/" (~docs-introduction-content)))
(defpage docs-page
:path "/docs/<slug>"
:path "/language/docs/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/docs/" slug)
:content (~sx-doc :path (str "/language/docs/" slug)
(case slug
"introduction" (~docs-introduction-content)
"getting-started" (~docs-getting-started-content)
@@ -44,23 +54,23 @@
;; ---------------------------------------------------------------------------
(defpage hypermedia-index
:path "/hypermedia/"
:path "/geography/hypermedia/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/hypermedia/"))
:content (~sx-doc :path "/geography/hypermedia/"))
(defpage reference-index
:path "/hypermedia/reference/"
:path "/geography/hypermedia/reference/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/hypermedia/reference/" (~reference-index-content)))
:content (~sx-doc :path "/geography/hypermedia/reference/" (~reference-index-content)))
(defpage reference-page
:path "/hypermedia/reference/<slug>"
:path "/geography/hypermedia/reference/<slug>"
:auth :public
:layout :sx-docs
:data (reference-data slug)
:content (~sx-doc :path (str "/hypermedia/reference/" slug)
:content (~sx-doc :path (str "/geography/hypermedia/reference/" slug)
(case slug
"attributes" (~reference-attrs-content
:req-table (~doc-attr-table-from-data :title "Request Attributes" :attrs req-attrs)
@@ -83,11 +93,11 @@
:uniq-table (~doc-attr-table-from-data :title "Unique to sx" :attrs uniq-attrs)))))
(defpage reference-attr-detail
:path "/hypermedia/reference/attributes/<slug>"
:path "/geography/hypermedia/reference/attributes/<slug>"
:auth :public
:layout :sx-docs
:data (attr-detail-data slug)
:content (~sx-doc :path "/hypermedia/reference/attributes"
:content (~sx-doc :path "/geography/hypermedia/reference/attributes"
(if attr-not-found
(~reference-attr-not-found :slug slug)
(~reference-attr-detail-content
@@ -99,11 +109,11 @@
:wire-placeholder-id attr-wire-id))))
(defpage reference-header-detail
:path "/hypermedia/reference/headers/<slug>"
:path "/geography/hypermedia/reference/headers/<slug>"
:auth :public
:layout :sx-docs
:data (header-detail-data slug)
:content (~sx-doc :path "/hypermedia/reference/headers"
:content (~sx-doc :path "/geography/hypermedia/reference/headers"
(if header-not-found
(~reference-attr-not-found :slug slug)
(~reference-header-detail-content
@@ -114,11 +124,11 @@
:demo header-demo))))
(defpage reference-event-detail
:path "/hypermedia/reference/events/<slug>"
:path "/geography/hypermedia/reference/events/<slug>"
:auth :public
:layout :sx-docs
:data (event-detail-data slug)
:content (~sx-doc :path "/hypermedia/reference/events"
:content (~sx-doc :path "/geography/hypermedia/reference/events"
(if event-not-found
(~reference-attr-not-found :slug slug)
(~reference-event-detail-content
@@ -128,20 +138,30 @@
:demo event-demo))))
;; ---------------------------------------------------------------------------
;; Protocols section
;; Applications section (parent of CSSX, Protocols)
;; ---------------------------------------------------------------------------
(defpage applications-index
:path "/applications/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/applications/"))
;; ---------------------------------------------------------------------------
;; Protocols section (under Applications)
;; ---------------------------------------------------------------------------
(defpage protocols-index
:path "/protocols/"
:path "/applications/protocols/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/protocols/" (~protocol-wire-format-content)))
:content (~sx-doc :path "/applications/protocols/" (~protocol-wire-format-content)))
(defpage protocol-page
:path "/protocols/<slug>"
:path "/applications/protocols/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/protocols/" slug)
:content (~sx-doc :path (str "/applications/protocols/" slug)
(case slug
"wire-format" (~protocol-wire-format-content)
"fragments" (~protocol-fragments-content)
@@ -156,16 +176,16 @@
;; ---------------------------------------------------------------------------
(defpage examples-index
:path "/hypermedia/examples/"
:path "/geography/hypermedia/examples/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/hypermedia/examples/"))
:content (~sx-doc :path "/geography/hypermedia/examples/"))
(defpage examples-page
:path "/hypermedia/examples/<slug>"
:path "/geography/hypermedia/examples/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/hypermedia/examples/" slug)
:content (~sx-doc :path (str "/geography/hypermedia/examples/" slug)
(case slug
"click-to-load" (~example-click-to-load)
"form-submission" (~example-form-submission)
@@ -197,20 +217,30 @@
:else (~example-click-to-load))))
;; ---------------------------------------------------------------------------
;; Essays section
;; Etc section (parent of Essays, Philosophy, Plans)
;; ---------------------------------------------------------------------------
(defpage etc-index
:path "/etc/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/etc/"))
;; ---------------------------------------------------------------------------
;; Essays section (under Etc)
;; ---------------------------------------------------------------------------
(defpage essays-index
:path "/essays/"
:path "/etc/essays/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/essays/" (~essays-index-content)))
:content (~sx-doc :path "/etc/essays/" (~essays-index-content)))
(defpage essay-page
:path "/essays/<slug>"
:path "/etc/essays/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/essays/" slug)
:content (~sx-doc :path (str "/etc/essays/" slug)
(case slug
"sx-sucks" (~essay-sx-sucks)
"why-sexps" (~essay-why-sexps)
@@ -235,16 +265,16 @@
;; ---------------------------------------------------------------------------
(defpage philosophy-index
:path "/philosophy/"
:path "/etc/philosophy/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/philosophy/" (~philosophy-index-content)))
:content (~sx-doc :path "/etc/philosophy/" (~philosophy-index-content)))
(defpage philosophy-page
:path "/philosophy/<slug>"
:path "/etc/philosophy/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/philosophy/" slug)
:content (~sx-doc :path (str "/etc/philosophy/" slug)
(case slug
"sx-manifesto" (~essay-sx-manifesto)
"godel-escher-bach" (~essay-godel-escher-bach)
@@ -258,16 +288,16 @@
;; ---------------------------------------------------------------------------
(defpage cssx-index
:path "/cssx/"
:path "/applications/cssx/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/cssx/" (~cssx-overview-content)))
:content (~sx-doc :path "/applications/cssx/" (~cssx-overview-content)))
(defpage cssx-page
:path "/cssx/<slug>"
:path "/applications/cssx/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/cssx/" slug)
:content (~sx-doc :path (str "/applications/cssx/" slug)
(case slug
"patterns" (~cssx-patterns-content)
"delivery" (~cssx-delivery-content)
@@ -282,23 +312,23 @@
;; ---------------------------------------------------------------------------
(defpage specs-index
:path "/specs/"
:path "/language/specs/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/specs/" (~spec-architecture-content)))
:content (~sx-doc :path "/language/specs/" (~spec-architecture-content)))
(defpage specs-page
:path "/specs/<slug>"
:path "/language/specs/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/specs/" slug)
:content (~sx-doc :path (str "/language/specs/" slug)
(case slug
"core" (~spec-overview-content
:spec-title "Core Language"
:spec-files (map (fn (item)
(dict :title (get item "title") :desc (get item "desc")
:prose (get item "prose")
:filename (get item "filename") :href (str "/specs/" (get item "slug"))
:filename (get item "filename") :href (str "/language/specs/" (get item "slug"))
:source (read-spec-file (get item "filename"))))
core-spec-items))
"adapters" (~spec-overview-content
@@ -306,7 +336,7 @@
:spec-files (map (fn (item)
(dict :title (get item "title") :desc (get item "desc")
:prose (get item "prose")
:filename (get item "filename") :href (str "/specs/" (get item "slug"))
:filename (get item "filename") :href (str "/language/specs/" (get item "slug"))
:source (read-spec-file (get item "filename"))))
adapter-spec-items))
"browser" (~spec-overview-content
@@ -314,7 +344,7 @@
:spec-files (map (fn (item)
(dict :title (get item "title") :desc (get item "desc")
:prose (get item "prose")
:filename (get item "filename") :href (str "/specs/" (get item "slug"))
:filename (get item "filename") :href (str "/language/specs/" (get item "slug"))
:source (read-spec-file (get item "filename"))))
browser-spec-items))
"extensions" (~spec-overview-content
@@ -322,7 +352,7 @@
:spec-files (map (fn (item)
(dict :title (get item "title") :desc (get item "desc")
:prose (get item "prose")
:filename (get item "filename") :href (str "/specs/" (get item "slug"))
:filename (get item "filename") :href (str "/language/specs/" (get item "slug"))
:source (read-spec-file (get item "filename"))))
extension-spec-items))
:else (let ((spec (find-spec slug)))
@@ -340,17 +370,17 @@
;; ---------------------------------------------------------------------------
(defpage bootstrappers-index
:path "/bootstrappers/"
:path "/language/bootstrappers/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/bootstrappers/" (~bootstrappers-index-content)))
:content (~sx-doc :path "/language/bootstrappers/" (~bootstrappers-index-content)))
(defpage bootstrapper-page
:path "/bootstrappers/<slug>"
:path "/language/bootstrappers/<slug>"
:auth :public
:layout :sx-docs
:data (bootstrapper-data slug)
:content (~sx-doc :path (str "/bootstrappers/" slug)
:content (~sx-doc :path (str "/language/bootstrappers/" slug)
(if bootstrapper-not-found
(~spec-not-found :slug slug)
(case slug
@@ -385,53 +415,53 @@
;; ---------------------------------------------------------------------------
(defpage isomorphism-index
:path "/isomorphism/"
:path "/geography/isomorphism/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/isomorphism/" (~plan-isomorphic-content)))
:content (~sx-doc :path "/geography/isomorphism/" (~plan-isomorphic-content)))
(defpage bundle-analyzer
:path "/isomorphism/bundle-analyzer"
:path "/geography/isomorphism/bundle-analyzer"
:auth :public
:layout :sx-docs
:data (bundle-analyzer-data)
:content (~sx-doc :path "/isomorphism/bundle-analyzer"
:content (~sx-doc :path "/geography/isomorphism/bundle-analyzer"
(~bundle-analyzer-content
:pages pages :total-components total-components :total-macros total-macros
:pure-count pure-count :io-count io-count)))
(defpage routing-analyzer
:path "/isomorphism/routing-analyzer"
:path "/geography/isomorphism/routing-analyzer"
:auth :public
:layout :sx-docs
:data (routing-analyzer-data)
:content (~sx-doc :path "/isomorphism/routing-analyzer"
:content (~sx-doc :path "/geography/isomorphism/routing-analyzer"
(~routing-analyzer-content
:pages pages :total-pages total-pages :client-count client-count
:server-count server-count :registry-sample registry-sample)))
(defpage data-test
:path "/isomorphism/data-test"
:path "/geography/isomorphism/data-test"
:auth :public
:layout :sx-docs
:data (data-test-data)
:content (~sx-doc :path "/isomorphism/data-test"
:content (~sx-doc :path "/geography/isomorphism/data-test"
(~data-test-content
:server-time server-time :items items
:phase phase :transport transport)))
(defpage async-io-demo
:path "/isomorphism/async-io"
:path "/geography/isomorphism/async-io"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/isomorphism/async-io" (~async-io-demo-content)))
:content (~sx-doc :path "/geography/isomorphism/async-io" (~async-io-demo-content)))
(defpage streaming-demo
:path "/isomorphism/streaming"
:path "/geography/isomorphism/streaming"
:auth :public
:stream true
:layout :sx-docs
:shell (~sx-doc :path "/isomorphism/streaming"
:shell (~sx-doc :path "/geography/isomorphism/streaming"
(~streaming-demo-layout
(~suspense :id "stream-fast" :fallback (~stream-skeleton))
(~suspense :id "stream-medium" :fallback (~stream-skeleton))
@@ -444,35 +474,35 @@
:stream-time stream-time))
(defpage affinity-demo
:path "/isomorphism/affinity"
:path "/geography/isomorphism/affinity"
:auth :public
:layout :sx-docs
:data (affinity-demo-data)
:content (~sx-doc :path "/isomorphism/affinity"
:content (~sx-doc :path "/geography/isomorphism/affinity"
(~affinity-demo-content :components components :page-plans page-plans)))
(defpage optimistic-demo
:path "/isomorphism/optimistic"
:path "/geography/isomorphism/optimistic"
:auth :public
:layout :sx-docs
:data (optimistic-demo-data)
:content (~sx-doc :path "/isomorphism/optimistic"
:content (~sx-doc :path "/geography/isomorphism/optimistic"
(~optimistic-demo-content :items items :server-time server-time)))
(defpage offline-demo
:path "/isomorphism/offline"
:path "/geography/isomorphism/offline"
:auth :public
:layout :sx-docs
:data (offline-demo-data)
:content (~sx-doc :path "/isomorphism/offline"
:content (~sx-doc :path "/geography/isomorphism/offline"
(~offline-demo-content :notes notes :server-time server-time)))
;; Wildcard must come AFTER specific routes (first-match routing)
(defpage isomorphism-page
:path "/isomorphism/<slug>"
:path "/geography/isomorphism/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/isomorphism/" slug)
:content (~sx-doc :path (str "/geography/isomorphism/" slug)
(case slug
"bundle-analyzer" (~bundle-analyzer-content
:pages pages :total-components total-components :total-macros total-macros
@@ -487,19 +517,19 @@
;; ---------------------------------------------------------------------------
(defpage plans-index
:path "/plans/"
:path "/etc/plans/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/plans/" (~plans-index-content)))
:content (~sx-doc :path "/etc/plans/" (~plans-index-content)))
(defpage plan-page
:path "/plans/<slug>"
:path "/etc/plans/<slug>"
:auth :public
:layout :sx-docs
:data (case slug
"theorem-prover" (prove-data)
:else nil)
:content (~sx-doc :path (str "/plans/" slug)
:content (~sx-doc :path (str "/etc/plans/" slug)
(case slug
"status" (~plan-status-content)
"reader-macros" (~plan-reader-macros-content)
@@ -530,39 +560,58 @@
:else (~plans-index-content))))
;; ---------------------------------------------------------------------------
;; Reactive Islands section
;; Geography section (parent of Reactive Islands, Hypermedia Lakes, Marshes)
;; ---------------------------------------------------------------------------
(defpage geography-index
:path "/geography/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/geography/"))
;; ---------------------------------------------------------------------------
;; Reactive Islands section (under Geography)
;; ---------------------------------------------------------------------------
(defpage reactive-islands-index
:path "/reactive/"
:path "/geography/reactive/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/reactive/" (~reactive-islands-index-content)))
:content (~sx-doc :path "/geography/reactive/" (~reactive-islands-index-content)))
(defpage reactive-islands-page
:path "/reactive/<slug>"
:path "/geography/reactive/<slug>"
:auth :public
:layout :sx-docs
:content (~sx-doc :path (str "/reactive/" slug)
:content (~sx-doc :path (str "/geography/reactive/" slug)
(case slug
"demo" (~reactive-islands-demo-content)
"event-bridge" (~reactive-islands-event-bridge-content)
"named-stores" (~reactive-islands-named-stores-content)
"plan" (~reactive-islands-plan-content)
"marshes" (~reactive-islands-marshes-content)
"phase2" (~reactive-islands-phase2-content)
:else (~reactive-islands-index-content))))
;; ---------------------------------------------------------------------------
;; Marshes section (under Geography)
;; ---------------------------------------------------------------------------
(defpage marshes-index
:path "/geography/marshes/"
:auth :public
:layout :sx-docs
:content (~sx-doc :path "/geography/marshes/" (~reactive-islands-marshes-content)))
;; ---------------------------------------------------------------------------
;; Bootstrapped page helpers demo
;; ---------------------------------------------------------------------------
(defpage page-helpers-demo
:path "/bootstrappers/page-helpers"
:path "/language/bootstrappers/page-helpers"
:auth :public
:layout :sx-docs
:data (page-helpers-demo-data)
:content (~sx-doc :path "/bootstrappers/page-helpers"
:content (~sx-doc :path "/language/bootstrappers/page-helpers"
(~page-helpers-demo-content
:sf-categories sf-categories :sf-total sf-total :sf-ms sf-ms
:ref-sample ref-sample :ref-ms ref-ms
@@ -580,11 +629,11 @@
;; ---------------------------------------------------------------------------
(defpage testing-index
:path "/testing/"
:path "/language/testing/"
:auth :public
:layout :sx-docs
:data (run-modular-tests "all")
:content (~sx-doc :path "/testing/"
:content (~sx-doc :path "/language/testing/"
(~testing-overview-content
:server-results server-results
:framework-source framework-source
@@ -596,7 +645,7 @@
:engine-source engine-source)))
(defpage testing-page
:path "/testing/<slug>"
:path "/language/testing/<slug>"
:auth :public
:layout :sx-docs
:data (case slug
@@ -608,7 +657,7 @@
"engine" (run-modular-tests "engine")
"orchestration" (run-modular-tests "orchestration")
:else (dict))
:content (~sx-doc :path (str "/testing/" slug)
:content (~sx-doc :path (str "/language/testing/" slug)
(case slug
"eval" (~testing-spec-content
:spec-name "eval"