;; --------------------------------------------------------------------------- ;; js.sx — Self-Hosting JavaScript Bootstrapper ;; --------------------------------------------------------------------------- (defcomp ~plans/js-bootstrapper/plan-js-bootstrapper-content () (~docs/page :title "js.sx — JavaScript Bootstrapper" ;; ----------------------------------------------------------------------- ;; Overview ;; ----------------------------------------------------------------------- (~docs/section :title "Overview" :id "overview" (p (code "bootstrap_js.py") " is a 4,361-line Python program that reads the " (code ".sx") " spec files and emits " (code "sx-ref.js") " — the entire " "browser runtime. Parser, evaluator, three rendering adapters (HTML, SX wire, DOM), " "the engine (fetch/swap/trigger), orchestration, boot, signals, router, component " "dependency analysis — all transpiled from " (code ".sx") " spec files into JavaScript.") (p (code "js.sx") " replaces that Python program with an SX program. " "Like " (code "py.sx") " for Python, " (code "js.sx") " is an SX-to-JavaScript " "translator written in SX. But it goes further.") (p "Because the JS bootstrapper produces " (em "browser code") ", " (code "js.sx") " can also compile " (em "any") " SX component tree into a standalone JavaScript " "program. The server evaluates an " (code ".sx") " page definition, calls " (code "#js") " on the result, and gets a self-contained JS bundle that renders " "the same output in the browser — no SX runtime needed.")) ;; ----------------------------------------------------------------------- ;; Two Modes ;; ----------------------------------------------------------------------- (~docs/section :title "Two Compilation Modes" :id "modes" (~docs/subsection :title "Mode 1: Spec Bootstrapper" (p "Same job as " (code "bootstrap_js.py") ". Read spec " (code ".sx") " files, " "emit " (code "sx-ref.js") ".") (~docs/code :src (highlight ";; Translate eval.sx to JavaScript (js-translate-file (parse-file \"eval.sx\")) ;; → \"function evalExpr(expr, env) { ... }\" ;; Full bootstrap: all spec modules → sx-ref.js (js-bootstrap :adapters (list \"html\" \"sx\" \"dom\" \"engine\" \"boot\") :modules (list \"deps\" \"router\" \"signals\"))" "lisp")) (p "The output is identical to " (code "python bootstrap_js.py") ". " "Verification: " (code "diff <(python bootstrap_js.py) <(python run_js_sx.py)") ".")) (~docs/subsection :title "Mode 2: Component Compiler" (p "Server-side SX evaluation + " (code "js.sx") " translation = static JS output. " "Given a component tree that the server has already evaluated (data fetched, " "conditionals resolved, loops expanded), " (code "js.sx") " compiles the " "resulting DOM description into a JavaScript program that builds the same DOM.") (~docs/code :src (highlight ";; Server evaluates the page (fetches data, expands components) ;; Result is a resolved SX tree: (div :class \"...\" (h1 \"Hello\") ...) ;; js.sx compiles that tree to standalone JS (js-compile-component evaluated-tree) ;; → \"(function(){ ;; var el = document.createElement('div'); ;; el.className = '...'; ;; var h1 = document.createElement('h1'); ;; h1.textContent = 'Hello'; ;; el.appendChild(h1); ;; return el; ;; })()\"" "lisp")) (p "This is ahead-of-time compilation. The browser receives JavaScript, " "not s-expressions. No parser, no evaluator, no runtime. " "Just DOM construction code."))) ;; ----------------------------------------------------------------------- ;; Architecture ;; ----------------------------------------------------------------------- (~docs/section :title "Architecture" :id "architecture" (p "The JS bootstrapper has more moving parts than the Python one because " "JavaScript is the " (em "client") " host. The browser runtime includes " "things Python never needs:") (div :class "overflow-x-auto rounded border border-stone-200 my-4" (table :class "w-full text-sm" (thead :class "bg-stone-50" (tr (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Spec Module") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Purpose") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Python?") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Browser?"))) (tbody (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "eval.sx") (td :class "px-4 py-2" "Core evaluator, special forms, TCO") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "render.sx") (td :class "px-4 py-2" "Tag registry, void elements, boolean attrs") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "parser.sx") (td :class "px-4 py-2" "Tokenizer, parser, serializer") (td :class "px-4 py-2 text-center" "—") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "adapter-html.sx") (td :class "px-4 py-2" "Render to HTML string") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "adapter-sx.sx") (td :class "px-4 py-2" "Serialize to SX wire format") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100 bg-blue-50" (td :class "px-4 py-2 font-mono" "adapter-dom.sx") (td :class "px-4 py-2" "Render to live DOM nodes") (td :class "px-4 py-2 text-center" "—") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100 bg-blue-50" (td :class "px-4 py-2 font-mono" "engine.sx") (td :class "px-4 py-2" "Fetch, swap, trigger, history") (td :class "px-4 py-2 text-center" "—") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100 bg-blue-50" (td :class "px-4 py-2 font-mono" "orchestration.sx") (td :class "px-4 py-2" "Element scanning, attribute processing") (td :class "px-4 py-2 text-center" "—") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100 bg-blue-50" (td :class "px-4 py-2 font-mono" "boot.sx") (td :class "px-4 py-2" "Script processing, mount, hydration") (td :class "px-4 py-2 text-center" "—") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "signals.sx") (td :class "px-4 py-2" "Reactive signal runtime") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "deps.sx") (td :class "px-4 py-2" "Component dependency analysis") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "router.sx") (td :class "px-4 py-2" "Client-side route matching") (td :class "px-4 py-2 text-center" "Yes") (td :class "px-4 py-2 text-center" "Yes"))))) (p "Blue rows are browser-only modules. " (code "js.sx") " must handle all of them. " "The platform interface is also larger: DOM primitives (" (code "dom-create-element") ", " (code "dom-append") ", " (code "dom-set-attr") ", ...), " "browser APIs (" (code "fetch") ", " (code "history") ", " (code "localStorage") "), and event handling.")) ;; ----------------------------------------------------------------------- ;; Translation Rules ;; ----------------------------------------------------------------------- (~docs/section :title "Translation Rules" :id "translation" (p (code "js.sx") " shares the same pattern as " (code "py.sx") " — expression translator, " "statement translator, name mangling — but with JavaScript-specific mappings:") (~docs/subsection :title "Name Mangling" (p "SX uses kebab-case. JavaScript uses camelCase.") (div :class "overflow-x-auto rounded border border-stone-200 my-4" (table :class "w-full text-sm" (thead :class "bg-stone-50" (tr (th :class "px-4 py-2 text-left font-semibold text-stone-700" "SX") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "JavaScript") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Rule"))) (tbody (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "eval-expr") (td :class "px-4 py-2 font-mono" "evalExpr") (td :class "px-4 py-2" "kebab → camelCase")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "nil?") (td :class "px-4 py-2 font-mono" "isNil") (td :class "px-4 py-2" "predicate → is-prefix")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "empty?") (td :class "px-4 py-2 font-mono" "isEmpty") (td :class "px-4 py-2" "? → is-prefix (general)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "set!") (td :class "px-4 py-2 font-mono" "—") (td :class "px-4 py-2" "assignment (no rename)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "dom-create-element") (td :class "px-4 py-2 font-mono" "domCreateElement") (td :class "px-4 py-2" "platform function rename")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "delete") (td :class "px-4 py-2 font-mono" "delete_") (td :class "px-4 py-2" "JS reserved word escape")))))) (~docs/subsection :title "Special Forms → JavaScript" (div :class "overflow-x-auto rounded border border-stone-200 my-4" (table :class "w-full text-sm" (thead :class "bg-stone-50" (tr (th :class "px-4 py-2 text-left font-semibold text-stone-700" "SX") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "JavaScript"))) (tbody (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(if c t e)") (td :class "px-4 py-2 font-mono" "(sxTruthy(c) ? t : e)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(when c body)") (td :class "px-4 py-2 font-mono" "(sxTruthy(c) ? body : NIL)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(let ((a 1)) body)") (td :class "px-4 py-2 font-mono" "(function(a) { return body; })(1)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(fn (x) body)") (td :class "px-4 py-2 font-mono" "function(x) { return body; }")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(define name val)") (td :class "px-4 py-2 font-mono" "var name = val;")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(and a b c)") (td :class "px-4 py-2 font-mono" "(sxTruthy(a) ? (sxTruthy(b) ? c : b) : a)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(case x \"a\" 1 ...)") (td :class "px-4 py-2 font-mono" "sxCase(x, [[\"a\", () => 1], ...])")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "(str a b c)") (td :class "px-4 py-2 font-mono" "sxStr(a, b, c)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "&rest args") (td :class "px-4 py-2 font-mono" "...args (rest params)")))))) (~docs/subsection :title "JavaScript Advantages" (p "JavaScript is easier to target than Python in two key ways:") (ul :class "list-disc pl-6 space-y-2 text-stone-700" (li (strong "No mutation problem. ") "JavaScript closures capture by reference, not by value. " (code "set!") " from a nested function Just Works — no cell variable " "hack needed. This eliminates the hardest part of " (code "py.sx") ".") (li (strong "Expression-oriented. ") "JavaScript's comma operator, ternary, and IIFEs make " "almost everything expressible as an expression. " "The statement/expression duality is less painful than Python.")))) ;; ----------------------------------------------------------------------- ;; Component Compilation ;; ----------------------------------------------------------------------- (~docs/section :title "Component Compilation" :id "component-compiler" (p "Mode 2 is the interesting one. The server already evaluates SX page " "definitions — it fetches data, resolves conditionals, expands components, " "and produces a complete DOM description as an SX tree. Currently this tree " "is either:") (ul :class "list-disc pl-6 space-y-1 text-stone-700" (li "Rendered to HTML server-side (" (code "render-to-html") ")") (li "Serialized as SX wire format for the client to render (" (code "aser") ")")) (p "A third option: " (strong "compile it to JavaScript") ". " "The SX tree is already fully resolved — no data to fetch, no conditionals " "to evaluate. It's just a description of DOM nodes. " (code "js.sx") " walks this tree and emits imperative JavaScript that constructs the same DOM.") (~docs/subsection :title "What Gets Compiled" (p "A resolved SX tree like:") (~docs/code :src (highlight "(div :class \"container\" (h1 \"Hello\") (ul (map (fn (item) (li :class \"item\" (get item \"name\"))) items)))" "lisp")) (p "After server-side evaluation (with " (code "items") " = " (code "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]") "):") (~docs/code :src (highlight "(div :class \"container\" (h1 \"Hello\") (ul (li :class \"item\" \"Alice\") (li :class \"item\" \"Bob\")))" "lisp")) (p "Compiles to:") (~docs/code :src (highlight "var _0 = document.createElement('div'); _0.className = 'container'; var _1 = document.createElement('h1'); _1.textContent = 'Hello'; _0.appendChild(_1); var _2 = document.createElement('ul'); var _3 = document.createElement('li'); _3.className = 'item'; _3.textContent = 'Alice'; _2.appendChild(_3); var _4 = document.createElement('li'); _4.className = 'item'; _4.textContent = 'Bob'; _2.appendChild(_4); _0.appendChild(_2);" "javascript"))) (~docs/subsection :title "Why Not Just Use HTML?" (p "HTML already does this — " (code "innerHTML") " parses and builds DOM. " "Why compile to JS instead?") (ul :class "list-disc pl-6 space-y-2 text-stone-700" (li (strong "Event handlers. ") "HTML can't express " (code ":on-click") " or " (code ":sx-get") " — those need JavaScript. The compiled JS can wire up event " "listeners inline during construction.") (li (strong "Reactive islands. ") "Signal bindings (" (code "deref") "), reactive text nodes, and " "reactive attributes need to register subscriptions during construction. " "Compiled JS can create signals and wire subscriptions as it builds the DOM.") (li (strong "No parse overhead. ") "The browser doesn't need to parse HTML or SX source. " "The JavaScript engine JIT-compiles the DOM construction code. " "For large pages, this can be faster than " (code "innerHTML") ".") (li (strong "Tree-shakeable. ") "The compiled output only contains what the page uses. " "No SX parser, no evaluator, no rendering runtime. " "A static page compiles to pure DOM API calls — zero framework overhead.") (li (strong "Portable. ") "The output is a JavaScript module. It works in any JS environment: " "browser, Node, Deno, Bun. Server-side rendered pages become " "testable JavaScript programs."))) (~docs/subsection :title "Hybrid Mode" (p "Not every page is fully static. Some parts are server-rendered, " "some are interactive. " (code "js.sx") " handles this with a hybrid approach:") (ul :class "list-disc pl-6 space-y-2 text-stone-700" (li (strong "Static subtrees") " → compiled to DOM construction code (no runtime)") (li (strong "Reactive islands") " → compiled with signal creation + subscriptions " "(needs signal runtime, ~2KB)") (li (strong "Hypermedia attributes") " (" (code "sx-get") ", " (code "sx-post") ") → compiled with event listeners + fetch calls " "(needs engine, ~5KB)") (li (strong "Client-routed pages") " → full SX runtime included")) (p "The compiler analyzes the tree and includes only the runtime slices needed. " "A purely static page ships zero SX runtime. " "A page with one reactive counter ships just the signal runtime."))) ;; ----------------------------------------------------------------------- ;; The Bootstrap Chain ;; ----------------------------------------------------------------------- (~docs/section :title "The Bootstrap Chain" :id "chain" (p "With both " (code "py.sx") " and " (code "js.sx") ", the full picture:") (div :class "overflow-x-auto rounded border border-stone-200 my-4" (table :class "w-full text-sm" (thead :class "bg-stone-50" (tr (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Translator") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Written in") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Outputs") (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Replaces"))) (tbody (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "z3.sx") (td :class "px-4 py-2" "SX") (td :class "px-4 py-2" "SMT-LIB") (td :class "px-4 py-2 text-stone-400 italic" "(none — new capability)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono" "prove.sx") (td :class "px-4 py-2" "SX") (td :class "px-4 py-2" "Constraint proofs") (td :class "px-4 py-2 text-stone-400 italic" "(none — new capability)")) (tr :class "border-t border-stone-100 bg-violet-50" (td :class "px-4 py-2 font-mono text-violet-700" "py.sx") (td :class "px-4 py-2" "SX") (td :class "px-4 py-2" "Python") (td :class "px-4 py-2 font-mono" "bootstrap_py.py")) (tr :class "border-t border-stone-100 bg-blue-50" (td :class "px-4 py-2 font-mono text-blue-700" "js.sx") (td :class "px-4 py-2" "SX") (td :class "px-4 py-2" "JavaScript") (td :class "px-4 py-2 font-mono" "bootstrap_js.py")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono text-stone-400" "go.sx") (td :class "px-4 py-2" "SX") (td :class "px-4 py-2" "Go") (td :class "px-4 py-2 text-stone-400 italic" "(future host)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2 font-mono text-stone-400" "rs.sx") (td :class "px-4 py-2" "SX") (td :class "px-4 py-2" "Rust") (td :class "px-4 py-2 text-stone-400 italic" "(future host)"))))) (p "Every translator is an SX program. The only Python left is the platform " "interface (types, DOM primitives, runtime support functions) and the thin " "runner script that loads " (code "py.sx") " or " (code "js.sx") " and feeds it the spec files.")) ;; ----------------------------------------------------------------------- ;; Implementation Plan ;; ----------------------------------------------------------------------- (~docs/section :title "Implementation" :id "implementation" (~docs/subsection :title "Phase 1: Expression Translator" (p "Core SX-to-JavaScript expression translation.") (ul :class "list-disc pl-6 space-y-1 text-stone-700" (li (code "js-mangle") " — SX name → JavaScript identifier (RENAMES + kebab→camelCase)") (li (code "js-literal") " — atoms: numbers, strings, booleans, nil, symbols, keywords") (li (code "js-expr") " — recursive expression translator") (li "Ternary: " (code "if") ", " (code "when") ", " (code "cond") ", " (code "and") ", " (code "or")) (li (code "let") " → IIFE: " (code "(function(a) { return body; })(val)")) (li (code "fn") " → " (code "function(x) { return body; }")) (li (code "str") " → " (code "sxStr(...)")) (li "Infix: " (code "+") ", " (code "-") ", " (code "*") ", " (code "/") ", " (code "===") ", " (code "!==") ", " (code "%")) (li (code "&rest") " → " (code "...args") " (rest parameters)"))) (~docs/subsection :title "Phase 2: Statement Translator" (p "Top-level and function body statement emission.") (ul :class "list-disc pl-6 space-y-1 text-stone-700" (li (code "js-statement") " — emit as JavaScript statement") (li (code "define") " → " (code "var name = expr;")) (li (code "set!") " → direct assignment (closures capture by reference)") (li (code "for-each") " → " (code "for (var i = 0; i < arr.length; i++)") " loop") (li (code "do") "/" (code "begin") " → comma expression or block") (li "Function bodies with multiple expressions → explicit " (code "return")))) (~docs/subsection :title "Phase 3: Spec Bootstrapper" (p "Process spec files identically to " (code "bootstrap_js.py") ".") (ul :class "list-disc pl-6 space-y-1 text-stone-700" (li (code "js-extract-defines") " — parse .sx source, collect top-level defines") (li (code "js-translate-file") " — translate a list of define expressions") (li "Adapter selection: parser, html, sx, dom, engine, orchestration, boot") (li "Dependency resolution: engine requires dom, boot requires engine + parser") (li "Static sections (IIFE wrapper, platform interface) stay as string templates"))) (~docs/subsection :title "Phase 4: Component Compiler" (p "Ahead-of-time compilation of evaluated SX trees to JavaScript.") (ul :class "list-disc pl-6 space-y-1 text-stone-700" (li (code "js-compile-element") " — emit " (code "createElement") " + attribute setting") (li (code "js-compile-text") " — emit " (code "textContent") " or " (code "createTextNode")) (li (code "js-compile-component") " — inline-expand or emit component call") (li (code "js-compile-island") " — emit signal creation + reactive DOM subscriptions") (li (code "js-compile-fragment") " — emit " (code "DocumentFragment") " construction") (li "Runtime slicing: analyze tree → include only necessary runtime modules"))) (~docs/subsection :title "Phase 5: Verification" (~docs/code :src (highlight "# Mode 1: spec bootstrapper parity python bootstrap_js.py > sx-ref-g0.js python run_js_sx.py > sx-ref-g1.js diff sx-ref-g0.js sx-ref-g1.js # must be empty # Mode 2: component compilation correctness # Server renders page → SX tree → compile to JS # Compare DOM output: runtime-rendered vs compiled python test_js_compile.py # renders both, diffs DOM" "bash"))) ;; ----------------------------------------------------------------------- ;; Comparison with py.sx ;; ----------------------------------------------------------------------- (~docs/section :title "Comparison with py.sx" :id "comparison" (div :class "overflow-x-auto rounded border border-stone-200 my-4" (table :class "w-full text-sm" (thead :class "bg-stone-50" (tr (th :class "px-4 py-2 text-left font-semibold text-stone-700" "Concern") (th :class "px-4 py-2 text-left font-semibold text-stone-700" (code "py.sx")) (th :class "px-4 py-2 text-left font-semibold text-stone-700" (code "js.sx")))) (tbody (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "Naming convention") (td :class "px-4 py-2" "snake_case") (td :class "px-4 py-2" "camelCase")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "Closures & mutation") (td :class "px-4 py-2" "Cell variable hack") (td :class "px-4 py-2" "Direct (reference capture)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "Spec modules") (td :class "px-4 py-2" "eval, render, html, sx, deps, signals") (td :class "px-4 py-2" "All 12 modules")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "Platform interface") (td :class "px-4 py-2" "~300 lines") (td :class "px-4 py-2" "~1500 lines (DOM, browser APIs)")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "RENAMES table") (td :class "px-4 py-2" "~200 entries") (td :class "px-4 py-2" "~350 entries")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "Component compilation") (td :class "px-4 py-2 text-stone-400" "N/A") (td :class "px-4 py-2" "Ahead-of-time DOM compiler")) (tr :class "border-t border-stone-100" (td :class "px-4 py-2" "Estimated size") (td :class "px-4 py-2" "~800-1000 lines") (td :class "px-4 py-2" "~1200-1500 lines")))))) ;; ----------------------------------------------------------------------- ;; Implications ;; ----------------------------------------------------------------------- (~docs/section :title "Implications" :id "implications" (~docs/subsection :title "Zero-Runtime Static Sites" (p "A static page written in SX compiles to a JavaScript program with " "no SX runtime dependency. The output is just DOM API calls — " (code "createElement") ", " (code "appendChild") ", " (code "textContent") ". This gives SX a compilation target competitive with Svelte's " "approach: components compile away, the framework disappears.") (p "Combined with the " (a :href "/sx/(etc.(plan.content-addressed-components))" "content-addressed components") " plan, a page's compiled JS could be stored on IPFS by its content hash. " "The server returns a CID. The browser fetches and executes pre-compiled JavaScript. " "No parser, no evaluator, no network round-trip for component definitions.")) (~docs/subsection :title "Progressive Enhancement Layers" (p "The component compiler naturally supports progressive enhancement:") (ol :class "list-decimal pl-6 space-y-1 text-stone-700" (li (strong "HTML") " — server renders to HTML string. No JS needed. Works everywhere.") (li (strong "Compiled JS") " — server compiles to DOM construction code. " "Event handlers work. No SX runtime. Kilobytes, not megabytes.") (li (strong "SX runtime") " — full evaluator + engine. Client-side routing, " "component caching, reactive islands. The current architecture.") (li (strong "SX + signals") " — full reactive islands. Fine-grained DOM updates.")) (p "Each layer adds capability and weight. The right layer depends on the page. " "A blog post needs layer 1. An interactive form needs layer 2. " "A single-page app needs layer 3. A real-time dashboard needs layer 4. " (code "js.sx") " makes layer 2 possible — it didn't exist before.")) (~docs/subsection :title "The Bootstrap Completion" (p "With " (code "py.sx") " and " (code "js.sx") " both written in SX:") (ul :class "list-disc pl-6 space-y-2 text-stone-700" (li "The " (em "spec") " defines SX semantics (" (code "eval.sx") ", " (code "render.sx") ", ...)") (li "The " (em "translators") " convert the spec to host languages (" (code "py.sx") ", " (code "js.sx") ")") (li "The " (em "prover") " verifies the spec's properties (" (code "z3.sx") ", " (code "prove.sx") ")") (li "All four are written " (em "in") " SX, executable " (em "by") " any SX evaluator")) (p "The language defines itself, verifies itself, and compiles itself. " "The Python and JavaScript \"bootstrappers\" are not programs that produce SX — " "they are SX programs that produce Python and JavaScript. " "The arrow points the other way."))))))