host: hand off the native SX-island editor (browser-capable session)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 17s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 17s
The editor is the interactivity layer — it belongs on the --http island pipeline (SSRs + hydrates islands), not the http-listen host, and needs browser/Playwright iteration which this worktree lacks. plans/blog-editor-island.md is the handoff: goal, architecture (docs-side island -> host /new), the live host contract (form-urlencoded title/sx_content/status -> 303), the sx_content markup to emit (standard tags, NOT legacy ~kg-* cards), island authoring gotchas, and pointers. Host side is ready (ingest proven; CORS on request). Phase 5.5 marked handed off. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
75
plans/blog-editor-island.md
Normal file
75
plans/blog-editor-island.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Handoff: native SX-island blog editor
|
||||
|
||||
> Handed off from the **host-on-sx** loop (2026-06-19). Build this in a
|
||||
> **browser-capable session** (Playwright installed) — a reactive island only
|
||||
> proves out when it hydrates in a browser; this worktree has no Playwright.
|
||||
|
||||
## Goal
|
||||
|
||||
A native **SX reactive island** WYSIWYG block editor for blog posts — replacing
|
||||
the legacy `shared/static/scripts/sx-editor.js` (Koenig-era JS, ~2500 lines).
|
||||
It edits blocks reactively and, on publish, emits **`sx_content`** (SX element
|
||||
markup) + a title + status, and submits to the host's create endpoint.
|
||||
|
||||
## Architecture (decided this session)
|
||||
|
||||
- The editor is the **interactivity layer**, so it lives on the **`--http`
|
||||
island pipeline** (`sx.rose-ash.com`, which already SSRs + hydrates islands),
|
||||
**NOT** in the `http-listen` host (the host deliberately doesn't do island
|
||||
hydration — see `plans/host-on-sx.md` Phase 5).
|
||||
- It **publishes to the host**: the host serves `blog.rose-ash.com` and owns the
|
||||
durable store + create/render. The editor is a docs-side island that talks to
|
||||
the host's API. Two cooperating SX servers: host = content/API/state, `--http`
|
||||
= interactive UI.
|
||||
|
||||
## The host contract (already live + proven)
|
||||
|
||||
`POST /new` on the host (`blog.rose-ash.com`) — **works today**:
|
||||
- Body: **form-urlencoded** `title`, `sx_content`, `status` (`draft`/`published`).
|
||||
- Behaviour: slug derived from title, post stored in the durable KV, **303
|
||||
redirect** to `/<slug>/`.
|
||||
- `host/blog-form-submit` in `lib/host/blog.sx`; route `host/blog-open-create-routes`
|
||||
(currently UNGUARDED experimental — gate before real use).
|
||||
- A **form POST** (303 redirect) needs **no CORS**. If the editor uses `fetch`
|
||||
instead, the host needs CORS on `/new` — the host loop can add `dream-cors-with`
|
||||
(`lib/dream/cors.sx`) in minutes; just ask.
|
||||
|
||||
## `sx_content` format — what to emit
|
||||
|
||||
SX **element markup**, rendered host-side by `render-page` → `render-to-html`,
|
||||
**per block, guarded** (`host/blog-render` in `lib/host/blog.sx`). So:
|
||||
- Top level is a fragment: `(<> (h2 "Title") (p "para " (strong "bold")) (ul (li "a") (li "b")))`.
|
||||
- **Use standard tags `render-to-html` knows**: `p h1..h6 ul ol li blockquote
|
||||
code pre strong em a img figure hr br span div`. These render cleanly + fast.
|
||||
- **AVOID the legacy `~kg-*` card components** — they show as `(unsupported
|
||||
block)` placeholders (the legacy editor emits bare `~kg-md` but the components
|
||||
are `~kg_cards/kg-md` — name drift we deliberately did NOT alias). If cards are
|
||||
wanted, define **canonical** card components the host loads (no bare-name shim).
|
||||
- A bad/unknown block degrades to a placeholder, never crashes the page — but
|
||||
aim to emit only renderable markup.
|
||||
|
||||
## Build notes
|
||||
|
||||
- It's a `defisland` served as a `defpage` on `--http`. Example island:
|
||||
`sx/sx/home/stepper.sx`. Reactive primitives: `signal`/`deref`/`computed`/
|
||||
`effect` (see the signals spec).
|
||||
- **SX island authoring gotchas** (CLAUDE.md "SX Island Authoring Rules"):
|
||||
multi-expr bodies need `(do …)`; `let` is parallel (nest for sequencing);
|
||||
reactive text needs `(deref (computed …))`; effects go in an inner `let`.
|
||||
- A reasonable MVP: title input (signal) + an ordered list of block signals
|
||||
(type + text), add/remove/reorder, a few block types (paragraph, heading,
|
||||
list, quote, code), a **live preview** (computed → rendered), and a Publish
|
||||
that serialises blocks → `sx_content` and form-POSTs to the host's `/new`.
|
||||
- **Test with `sx_playwright`** (inspect / hydrate / interact / trace-boot) —
|
||||
hydrate the island, simulate typing, assert the serialized `sx_content` and
|
||||
the live preview. Don't ship an island you haven't hydrated in a browser.
|
||||
|
||||
## Pointers
|
||||
|
||||
- Host ingest + render + page shell: `lib/host/blog.sx` (the `/new` POST is the
|
||||
target; `host/blog-render` shows exactly which markup renders).
|
||||
- `render-page` (host's component renderer) + the static-page pattern:
|
||||
`lib/host/page.sx`, `plans/host-on-sx.md` Phase 5.
|
||||
- Island example: `sx/sx/home/stepper.sx`. HTML renderer (tags it knows):
|
||||
`web/adapter-html.sx`. Legacy editor (reference only, being replaced):
|
||||
`shared/static/scripts/sx-editor.js`.
|
||||
@@ -251,10 +251,14 @@ Sub-steps (each independently gated/verified):
|
||||
- [ ] **5.4 Island hydration.** Confirm a trivial island page boots + hydrates
|
||||
client-side (sx-browser.js) when served by the host. Gate: a counter island
|
||||
increments in the browser.
|
||||
- [ ] **5.5 Editor POC.** Serve an editor page as the FIRST interactive consumer,
|
||||
its form/island posting to the existing `POST /new` ingest (already proven).
|
||||
Gate: visual edit → publish → renders, end-to-end in a browser. (The POC
|
||||
validates the *capability*; the editor itself is replaced next — see below.)
|
||||
- [~] **5.5 Editor POC — HANDED OFF.** The native SX-island editor is the
|
||||
interactivity layer; per the architecture it lives on the `--http` island
|
||||
pipeline (not the host) and needs browser/Playwright iteration (absent in
|
||||
this worktree). Handoff brief: `plans/blog-editor-island.md`. The host side
|
||||
is READY: `POST /new` ingest is live + proven (form-urlencoded
|
||||
title/sx_content/status → 303); CORS can be added on request if the editor
|
||||
uses fetch. Decision: don't port island hydration into the host; the editor
|
||||
is a docs-side island that publishes to the host.
|
||||
|
||||
**Note:** component SSR is interpreted → slow until the `sx-vm-extensions` JIT
|
||||
loop lands; correctness first, speed follows. Scope spans `hosts/` (page-render
|
||||
|
||||
Reference in New Issue
Block a user