;; lib/host/blog.sx — Blog domain on the host. Serves published posts as HTML at ;; GET // — the original strangler target (Quart: blog/bp/post/routes.py, ;; handler post_detail). Published posts are world-visible, so this endpoint is ;; ANONYMOUS — no auth, visibility is trivially "visible". ;; ;; A post is a content-on-sx document (CtDoc) rendered to HTML via the content ;; facade (content/html). Posts live in an in-memory registry keyed by slug: this ;; is the "prove the machinery" step — swap host/blog-lookup for a persist-backed ;; content stream later without touching the handler or the route. ;; Depends on lib/content/* (+ the Smalltalk + persist preloads its classes need) ;; + lib/dream/* + lib/host/handler.sx. ;; Register the content class table + render methods (idempotent). Must run before ;; any CtDoc is built/rendered; called at module load below. (define host/blog-bootstrap! (fn () (begin (st-bootstrap-classes!) (content/bootstrap!)))) ;; ── in-memory post registry (slug -> CtDoc) ───────────────────────── (define host/blog-posts {}) (define host/blog-register! (fn (slug doc) (set! host/blog-posts (assoc host/blog-posts slug doc)))) (define host/blog-lookup (fn (slug) (get host/blog-posts slug))) (define host/blog-reset! (fn () (set! host/blog-posts {}))) ;; Build a simple post doc (title heading + body paragraph). Convenience for ;; seeding and tests; real posts arrive from the content store. (define host/blog-make (fn (slug title body) (doc-append (doc-append (doc-empty slug) (mk-heading (str slug "-h") 1 title)) (mk-text (str slug "-body") body)))) ;; ── handler: GET // -> rendered HTML (200) or 404 ───────────── (define host/blog-post (fn (req) (let ((slug (dream-param req "slug"))) (let ((doc (host/blog-lookup slug))) (if doc (dream-html (content/html doc)) (dream-html-status 404 (str "Not found" "

404

No published post: " slug "

"))))))) ;; Anonymous read route. MUST be mounted LAST: the :slug pattern matches any ;; single-segment path, so domain routes (/feed, /health) take precedence. (define host/blog-routes (list (dream-get "/:slug" host/blog-post))) ;; Self-bootstrap at load (content modules are loaded before this one). (host/blog-bootstrap!)