host: blog on the editor's sx_content model + render-to-html, 171/171
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 17s

Pivot blog to the SX editor's content model. The editor (blog/sx/editor.sx)
emits sx_content = SX element markup, NOT content-on-sx CtDoc blocks. So a post
is now a {slug,title,sx_content,status} record in the durable persist KV, and a
post page is render-to-html(parse sx_content) — server-side, static, no client
runtime needed to view.

Endpoints: GET / (HTML index), /<slug>/ (rendered post), /posts (JSON list),
/new (create form); POST /new (form-urlencoded editor ingest, slug from title,
303 redirect), POST /posts (JSON create), PUT/DELETE /posts/<slug>. Writes
behind auth+ACL (edit/blog). Dropped the content-on-sx/Smalltalk preload chain;
added spec/render + web/adapter-html (render-to-html) + lib/dream/form.

BONUS: render-to-html is ~0ms (vs the 2s content-on-sx Smalltalk asHTML) — it
doesn't hit the JIT-miscompiled path, so blog rendering is no longer slow.

Live: blog.rose-ash.com/ lists posts, /welcome/ renders instantly. Reads live;
the form-ingest write path needs an auth decision before going live (browser
forms can't send bearer; needs session or a Caddy basicauth gate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 19:52:05 +00:00
parent 64985ff6f7
commit 6ed9e7dbe6
5 changed files with 234 additions and 293 deletions

View File

@@ -60,27 +60,19 @@ MODULES=(
"lib/feed/normalize.sx"
"lib/feed/stream.sx"
"lib/feed/api.sx"
"lib/smalltalk/tokenizer.sx"
"lib/smalltalk/parser.sx"
"lib/guest/reflective/class-chain.sx"
"lib/smalltalk/runtime.sx"
"lib/guest/reflective/env.sx"
"lib/smalltalk/eval.sx"
"lib/persist/event.sx"
"lib/persist/backend.sx"
"lib/persist/log.sx"
"lib/persist/kv.sx"
"lib/persist/api.sx"
"lib/content/block.sx"
"lib/content/doc.sx"
"lib/content/render.sx"
"lib/content/api.sx"
"lib/content/store.sx"
"lib/persist/durable.sx"
"spec/render.sx"
"web/adapter-html.sx"
"lib/dream/types.sx"
"lib/dream/json.sx"
"lib/dream/auth.sx"
"lib/dream/error.sx"
"lib/dream/form.sx"
"lib/dream/router.sx"
"lib/host/handler.sx"
"lib/host/middleware.sx"
@@ -98,15 +90,13 @@ EPOCH=1
echo "(epoch $EPOCH)"; echo "(load \"$M\")"; EPOCH=$((EPOCH+1))
done
# Point the blog at the DURABLE file backend (persists under $SX_PERSIST_DIR),
# then idempotently seed a welcome post — re-seeding is a no-op if it already
# exists on disk, so restarts don't duplicate blocks.
# then idempotently seed a welcome post (sx_content = SX element markup, the
# editor's content model). Re-seeding is a no-op if the slug already exists.
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog-use-store! (persist/durable-backend))\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
# Idempotently seed the welcome post into the durable store (no-op if present).
# Handlers read + render from the store per request (per-request IO).
echo "(eval \"(host/blog-seed! \\\"welcome\\\" \\\"Welcome to the SX host\\\" \\\"This page is rendered by lib/host on the SX runtime, persisted in the SX store — no Quart.\\\" 1)\")"
echo "(eval \"(host/blog-seed! \\\"welcome\\\" \\\"Welcome to the SX host\\\" \\\"(article (h1 \\\\\\\"Welcome to the SX host\\\\\\\") (p \\\\\\\"Rendered by lib/host via render-to-html, from the durable SX store.\\\\\\\"))\\\" \\\"published\\\")\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
# Anonymous read endpoints: feed timeline + relations container reads + blog