slhx agent c8c71deb68 docs(hemx): add diagnostics guide
Document the v1 diagnostics story for common template, derive, form, result-handler, and runtime/deploy mistakes. The guide names expected user-facing diagnostics and recurring verification gates without exposing raw ids/selectors as the beginner path.

req: diagnostics/001

req: diagnostics/002

req: diagnostics/003

req: failure/004

req: failure/005

req: public_api/005

req: test/003
2026-06-05 09:46:32 +02:00
2026-06-05 09:46:32 +02:00
2026-06-05 06:52:37 +02:00
2026-06-05 06:52:37 +02:00
2026-06-05 06:52:37 +02:00
2026-06-05 06:52:37 +02:00
2026-06-05 09:46:32 +02:00

hemx

hemx is checked hypermedia for Rust: write hemplate templates, write typed Rust handlers, and return generated UI commands. The browser receives checked UI commands; ordinary server-first apps do not need a frontend framework, handwritten UI JavaScript, selector targeting, or raw runtime primitives. req: pitch/001 req: canonical_authoring/001

Status: the repository currently has a strong v0 example/API path, an advanced Kanban milestone sketch, and a full techdemo. The polished v1 production SaaS tutorial app is still a goal, not a completed artifact.

The normal path

For beginner and production-shaped app code, stay on this path. req: public_api/001 req: public_api/005

  1. Templates declare the surface. .heml files declare roots, slots, forms, handles, keys, page targets, optional pending states, and explicit leaf islands with data-hemx-* attributes.
  2. Build generates typed helpers. hemx_build::app().run() consumes the hemplate Surface and emits generated Rust helpers for slots, forms, handles, page targets, classes, and events. req: ceremony/003 req: build/001
  3. Handlers are plain Rust. App code uses #[hemx::handler] functions with ordinary domain types, framework extractors, generated Form<T> inputs, and impl IntoEffect or Result<impl IntoEffect, E> returns. req: derive_handler/004
  4. Handlers return generated commands. Common handlers return helpers such as todos.append(todo), todo_row.replace(row), new_todo.error("title", "Required"), new_todo.clear(), page.replace(view), or tuples of those commands. req: dx/006 req: dx/007
  5. The runtime only applies effects. The JavaScript runtime is a small, root-scoped effect interpreter: no VDOM, no hydration framework, no client expression engine, no selector retargeting, and no app state store. req: runtime/003 req: invariant/002

Mental model: render → slot/key → effect → runtime

  • Render: hemplate renders Rust view structs into checked HTML. App code normally reaches rendering through generated helpers or hemx::page(...) at a server page boundary, not raw HTML construction. req: html_safety/002 req: view/001
  • Slot/key: a generated slot names the target, and a generated keyed slot also carries the stable row key. A list target inside h-for must have a stable h-key, so row updates are addressable without CSS selectors. req: list/001
  • Effect: handlers return typed commands that become a checked effect response. Tuple composition is the normal batch syntax.
  • Runtime: the browser checks the build fingerprint, resolves targets within the current data-hemx-root, and applies compatible batches. Mismatched server/runtime builds fail closed instead of silently mutating the wrong DOM. req: abi/002 req: check/004 req: failure/005

Forms and errors

Forms remain HTML forms. hemx checks the generated form contract against a user-authored Rust form type, so domain newtypes such as Email, TodoId, and Title parse through ordinary Rust traits rather than generated DTOs. req: form/001

Use validation effects for expected user mistakes, and Result<impl IntoEffect, E> for fallible domain, database, or infrastructure work. Integration crates map E to generated UI effects, redirects, events, or HTTP responses; the canonical app code still uses the same handler shape for plain and fallible handlers. See docs/diagnostics.md for common compile/build/runtime mistakes and fixes. req: failure/004 req: derive_handler/004

Pages, push, CSS, and islands

  • Page navigation is a specialized generated page/slot effect around real anchors and ordinary HTTP routes. hemx does not own routing. req: modes/002 req: axum_integration/002
  • Server push streams send checked effect responses over framework-managed transports such as SSE; auth and connection policy stay in the server integration. req: wire/004 req: push/002
  • Appearance is plain CSS. Generated class tokens can make dynamic classes checked, but hemx does not introduce a styling runtime.
  • Custom JavaScript belongs at explicit opaque leaf boundaries: charts, maps, editors, Web Components, or similar widgets. Islands communicate through generated handles/events and do not create a second UI model. req: canonical_authoring/007 req: interop/003

Production boundary

hemx is not a SaaS platform. Production concerns stay in normal Rust/web crates and integrate at explicit boundaries. req: laws/002 req: auth/001

  • Persistence: use SQLx or another storage adapter in your application state/handlers. hemx should see ordinary domain values and generated UI commands, not own the database layer. See docs/recipes/sqlx-persistence.md.
  • Auth/session: use Axum/Tower extractors and middleware. Handlers may accept typed auth/session context and return ordinary HTTP failures or generated UI failures. See docs/recipes/auth-session-csrf.md. req: auth/002
  • CSRF: keep CSRF policy in middleware/extractors with hidden form fields, cookies, and normal SameSite/browser semantics. hemx preserves submitted form fields and credentials semantics. See docs/recipes/auth-session-csrf.md. req: auth/004 req: auth/005
  • Observability, feature flags, killswitches, deploy: use explicit platform integrations around handlers, routes, and runtime assets. Core hemx must not vendor providers or add framework-specific magic. See docs/recipes/deploy-versioning.md.
  • PWA/offline/sync: optional adapters may reuse generated targets/effects, but core hemx must not gain a mandatory client state graph or local app runtime. req: canonical_authoring/008

Escape hatches

Advanced APIs are named and isolated. Raw effects, low-level ids, manual registries, raw HTML/render/target construction, runtime hooks, SSE internals, and island internals are for integration crates, tests, migrations, or explicit leaf boundaries. They should not appear in beginner examples or ordinary handler docs. req: public_api/002 req: public_api/005

Versioning and deploy compatibility

The generated API, symbols, effect wire schema, and JavaScript runtime carry schema/ABI versions. Deploy a matching server, generated output, and runtime asset together. Build fingerprints are derived from the generated surface and ABI parts; the runtime refuses incompatible effect responses and integrations should fall back to a full page reload when possible. See docs/recipes/deploy-versioning.md. req: abi/001 req: abi/002 req: failure/005

Before a v1 release, the semver policy and upgrade notes should explicitly state which surfaces are stable: beginner generated helpers and handler shapes; the wire/runtime ABI; and advanced escape hatches that may remain integration-level.

Examples

  • examples/v0: canonical beginner path covering counter, typed todo CRUD, form wizard, auth action, page swaps, SSE notifications, and keyed list updates. Start here.
  • examples/saas: compile-tested v1 tutorial skeleton covering auth/session, CSRF-safe mutation, local persistence, generated swaps, page/push shape, plain CSS, and one explicit island without provider-heavy platform scope. The SQLx persistence recipe in docs/recipes/sqlx-persistence.md shows the provider boundary without moving SQL into core.
  • examples/kanban: advanced / north-star milestone boundary sketch. It may expose manual registry or render escape hatches while exploring product limits.
  • examples/techdemo: advanced integration demo with a leaf island and broader product interactions.

Local checks

cargo run -p hemx-xtask -- test
cargo check --workspace
redgate health --strict

Use cargo run -p hemx-xtask -- test for the full local verification path so jobs stay capped for local CPU and memory. req: test/004

S
Description
No description provided
Readme 1.9 MiB
Languages
Rust 92.3%
JavaScript 7.6%