Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 15s
lib/host/blog.sx serves blog posts as HTML at GET /<slug>/ (the original strangler target, Quart blog post_detail). A post is a content-on-sx CtDoc rendered via content/html; anonymous + world-visible. In-memory slug->doc registry now (host/blog-lookup swappable for a persist-backed content stream later, handler/route unchanged). :slug catch-all mounted LAST so /feed, /health, /internal/* take precedence. Needs the Smalltalk+persist+content preload chain + (st-bootstrap-classes!)+(content/bootstrap!) — blog.sx self-bootstraps at load. serve.sh loads the chain + seeds a welcome post. Ledger gains the migrated blog post-detail (off-Quart 50% -> 53%). LIVE: blog.rose-ash.com/welcome/ renders real HTML through Cloudflare->Caddy; /feed still JSON (precedence verified), unknown slug 404. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
51 lines
2.4 KiB
Plaintext
51 lines
2.4 KiB
Plaintext
;; lib/host/blog.sx — Blog domain on the host. Serves published posts as HTML at
|
|
;; GET /<slug>/ — 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 /<slug>/ -> 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 "<!doctype html><title>Not found</title>"
|
|
"<h1>404</h1><p>No published post: " slug "</p>")))))))
|
|
|
|
;; 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!)
|