hypermedia-engine-stacks
Skill0 starsChanged 13 days agoISCView on GitHub
Use when the task is a Rust-first hypermedia application or simulation shell — a Rama gateway with SSE, SQLx typed queries and LISTEN/NOTIFY fan-out, Maud server-rendered HTML, Datastar signals and morphing, a Bevy WASM canvas, or binary rama-ws telemetry. Task-shaped triggers include an SSE dashboard, a WASM canvas embedded in server-rendered HTML, PostgreSQL notify fan-out, a graceful drain of open streams, a stream connection budget, and a SQLx offline metadata drift gate. Do not use for SvelteKit, React, or any JS SPA stack; do not use for Axum-based hypermedia, which has its own extractor and SSE surface.
In this repository18 other files it gives its agents.
- AGENTS.mdAGENTS.md
- apex-performance-auditorSkill
- checkSkill
- context7-mcpSkill
- design-craftSkill
- framework-engine-stacksSkill
- guardrailsSkill
- learning-curatorSkill
- okf-docsSkill
- pi-lens-ast-grepSkill
- pi-lens-lsp-navigationSkill
- pi-lens-write-ast-grep-ruleSkill
- pi-lens-write-tree-sitter-ruleSkill
- rust-systemsSkill
- scalabilitySkill
- select-modelSkill
- skill-authoring-visionSkill
- systems-auditorSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 37
Zero-JS server runtime: every byte of HTML comes from Maud through Rama.
- Very specific: line 83
Prefer the re-anchor over retry: 'always': the ladder is 1 s → 30 s over ten attempts (~181 s) before retries-failed, while a replaced node …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Hypermedia & Engine Stacks
Rust-first architecture for server-rendered applications: Rama is the gateway, SQLx the typed persistence layer, Maud the template compiler, Datastar the client engine, and Bevy WASM plus rama-ws the conditional simulation tier. Five per-pillar archives carry the signatures; this syllabus carries the rules.
Fidelity command of record: bun scripts/verify-archives.ts (rule helpers in scripts/verify-archives-lib.ts). It asserts both Markdown ceilings, archive-link resolution, the provenance lock, the unpinned sweep, the frontmatter description cap and content, the transport-table parity, the archive section order, the stream-lifecycle spine with resolvable owner archives, and the retired-token sweep.
Six-Pillar Matrix
| Pillar | Owns | Archive |
| Gateway and transport | routing, extraction, SSE framing, WSS upgrade, limits, CSRF, drain | references/rama.md |
| Persistence and fan-out | compile-time SQL, pools, migrations, LISTEN/NOTIFY to broadcast | references/sqlx.md |
| Templating | compile-time HTML, escaping, single-buffer rendering | references/maud.md |
| Client reactivity | signals, actions, CQRS commands, Fat Morphing, retry | references/datastar.md |
| Simulation | ECS schedules, messages versus events, WASM build, canvas mount | references/bevy.md |
| High-frequency transport | binary/text frames over rama-ws, consumed by Bevy | references/rama.md, references/bevy.md |
Selection boundary: SvelteKit, React, and Axum work is out of scope. Those are different stack classes — an Axum hypermedia service has its own extractor and SSE surface, and a JS SPA owns rendering that this skill hands to Maud. This skill is the Rust hypermedia stack and does not choose between them.
| Adjacent concern | Shipped owner |
| Queue topology, worker pools, backpressure, push pipelines | scalability |
| HTML/DOM sinks, secret hygiene, dependency and container hardening | guardrails |
| Rust lint and unsafe policy, async cancellation contracts, verification lanes | rust-systems |
| Interface craft, motion, accessibility review | design-craft |
| Whole-system audits | systems-auditor |
This skill carries only the SSE/WSS transport contract and the five pillar archives; it does not restate those owners' rules.
Non-Negotiable Hypermedia & Simulation Invariants
- Zero-JS server runtime: every byte of HTML comes from Maud through Rama. No Node.js, Bun, or external SSR runtime in the serving path.
- Compile-time PostgreSQL lock-in:
query!/query_as!against PostgreSQL,.sqlx/committed,cargo sqlx prepare --checkin CI. No dual-engine trait, no#[cfg]database gate. The isolated SQLite fallback publishes to the same in-processbroadcastchannel and never emulatesLISTEN/NOTIFYin SQL. - Event-driven reactivity only: push state over SSE or WSS. Polling,
setIntervalrefetches, and Datastar interval actions are prohibited as state transport. - Hybrid simulation boundary: high-frequency inputs and ticks go directly over
rama-wsinto Bevy; low-frequency HUD, inventory, and menus cross viaCustomEventor Datastar signals. A 60 Hz transform stream never touches the DOM. - No shared memory:
SharedArrayBufferand cross-origin memory locks are prohibited between WASM and the DOM. Bound thewasm-bindgenqueue instead; a hidden tab pausesrequestAnimationFramewhile WSS keeps writing. - Canvas morph boundary:
data-ignore-morphon the<canvas>and its mount container.data-ignoresuppresses plugin processing and is not a morph boundary. Anydata-on:*listener that must survive a patch sits on an ancestor outside the morphed region. - Open streams are bounded:
ConcurrentCounter::new(max)with the guard moved into the stream, released onDrop; over budget answers503withRetry-After, never429and never204. That503is the route's own mapping —LimitReachedimplements noIntoResponse— whileLimitLayer/ConcurrentPolicycap in-flightserve()inputs only and answer429on the request lane, because an SSE response completes at handoff. - Streams end by decision: drain broadcasts an explicit exit, answers new streams
410 Gonewith a proxy-facingRetry-After, and re-anchors the@getnode with a finalPatchElements. A clean200close is not re-requested by the engine. - Authorization is bounded, not re-checked: an established SSE response cannot re-authorize. Cap the stream lifetime; at expiry re-anchor under a fresh principal check, or answer
410when the session is gone. - Lag is a resync signal:
RecvError::Lagged(n)means drop buffered state, re-query a snapshot, render it, and count it. It is not an error to log and ignore. - Extensions isolate by fork, not by clone:
Extensions::fork()gives a child store whose inserts the parent never sees; a clone shares its store, so an insert through a clone is visible to the original handle. A request-local overlay starts withfork(). - Routing is case-insensitive unless told otherwise:
PathMatchPolicydefaults toAsciiInsensitive+PercentDecoded, so a security-sensitive path opts intoPathMatchPolicy::STRICT; specificity breaks a tie, static over capture over catch-all. - CSRF is fetch metadata, not an allow-list:
CsrfLayerallows the safe methods,Sec-Fetch-Sitesame-originornone, a trustedOrigin, absent fetch metadata, or anOriginauthority matching the effective host.TRACEandQUERYare not exempt, and a proxy that rewritesHostor stripsOriginsilently degrades the check. Datastar ships no CSRF rule, so an application-invented origin check is not a substitute.
Transport Status
| State | Answer | Datastar consequence |
| Draining, stream route | 410 Gone (+ Retry-After, proxy-facing) | datastar-fetch error; retry: 'auto' does not retry a 4xx, so the client needs the re-anchor patch |
| Draining, command route | 503 + Retry-After | error event, no retry |
| Over stream budget | 503 + Retry-After | error event, no retry; pair with the same re-anchor patch |
| Stream ended on purpose | 410, never 204 | 204 applies no patch and emits no error or retrying event; started and finished still fire |
| Command accepted | 204 No Content | command routes only; never a stream |
410 is stream-only: it means permanently gone, and a deploy is not. Retry-After is proxy, load-balancer, and browser-facing; the Datastar engine never reads it. 429 belongs to neither stream state: it is the request-rate lane's answer, from RatePolicy or KeyedRatePolicy in the gateway archive, and never the budget or drain answer.
Stream Lifecycle
One ordered sequence, each step carrying the mechanism that enforces it. The owner archive holds the detail; this is the spine, not a second copy of it.
| # | Step | Enforcing mechanism | Owner |
| 1 | Admit under a stream-owned guard | ConcurrentTracker::try_access() on a ConcurrentCounter; the guard moves into the stream and Drop releases it | references/rama.md |
| 2 | Subscribe, then snapshot | PgListener::listen before the snapshot query, merged by id — the reverse order loses any commit landing between the two | references/sqlx.md |
| 3 | Render the shell and first patch | a Maud page opened with maud::DOCTYPE, then a PatchElements against a deterministic id | references/maud.md |
| 4 | Stream patches and keep-alive | Sse::new(KeepAliveStream::new(..)) over the broadcast receiver, one guard held for the body's life | references/rama.md |
| 5 | Detect lag and resync | RecvError::Lagged(n) → drop buffered state, re-query a snapshot, re-render it, count it | references/sqlx.md |
| 6 | Re-anchor the subscription node | a final PatchElements replacing the @get node, so the engine re-subscribes immediately instead of waiting on the retry ladder | references/datastar.md |
| 7 | Drain, then answer 410 | broadcast an explicit exit; the stream ends on that message, not on a poll of the shutdown guard | references/rama.md |
| 8 | Treat a closed stream as closed | a cleanly closed 200 is never re-requested — only a replaced node or retry: 'always' brings it back | references/datastar.md |
Bounded Streams and Principal Reverification
- Admit with the
ConcurrentCounterguard inside the stream; the guard is the budget, not a request-layer permit. - Cap the stream lifetime (a value inside the proxy idle timeout) and treat expiry as a re-subscription, not a mid-stream check: emit a final
PatchElementsthat replaces the@getnode, or answer410when the session is gone. openWhenHidden: falseon@getalready forces one rebuild per tab onvisibilitychange; the lifetime bound rides that re-subscribe instead of inventing a second one.- Prefer the re-anchor over
retry: 'always': the ladder is 1 s → 30 s over ten attempts (~181 s) beforeretries-failed, while a replaced node re-subscribes immediately.
Retained and Retired Invariants
| Shipped invariant | Status | Home |
| Zero-JS server runtime | carried | this syllabus |
| PostgreSQL compile-time lock-in | carried | references/sqlx.md |
| Polling prohibition | carried | this syllabus |
| Hybrid simulation boundary | carried and sharpened to the Message/Event lane rule | references/bevy.md |
SharedArrayBuffer prohibition | carried, with the bounded-queue replacement | references/bevy.md |
| Canvas morph boundary | rewritten: data-ignore → data-ignore-morph on canvas and container | references/datastar.md, references/bevy.md |
Telemetry
Server signals beside the client rule, each with the condition it detects. All four ride the wide event emitted by TraceLayer::on_eos, the hook that fires when the response body ends — on_response fires at handoff and would report every stream as zero-duration.
| Failure mode | Metric | Condition it detects |
| Streams outlive their budget | open_streams | current ConcurrentCounter occupancy; at or above the cap with a flat request rate, streams are not ending — a permit leak or a client that never disconnects |
| Subscriber falls behind the channel | broadcast_lagged_total | RecvError::Lagged occurrences, i.e. resyncs; a capacity problem, not a database one |
| Shutdown strands a stream | drain_state | accepting versus draining; a stream still open past the drain ceiling means the window is shorter than the stream's own keep-alive |
| Admission refuses a stream | stream_rejections_total | over-budget and drain-time answers, counted by status, so a 503 spike is distinguishable from a 410 deploy |
The client datastar-fetch event is the only lifecycle signal; it fires on document with detail.type = started, finished, error, retrying, or retries-failed. No per-phase event name exists.
Workflow
- Scope the tier. Pick the matrix row; write the one-line boundary (hypermedia only, or canvas plus WSS).
- Shape the data. Append expand-contract migrations; write
query!/query_as!; runcargo sqlx prepare --workspace -- --all-targets --all-featuresin the same commit. - Wire the gateway.
Router::new_with_state,ReadSignalsper the method rule,CsrfLayer, a request-concurrencyLimitLayer, and theConcurrentCounterstream budget. Commands answer204; streams answer410at drain. - Render the shell. Maud components with deterministic
ids, serializeddata-signalsJSON spliced through escaping (neverPreEscaped), and a single pre-sized buffer withRender::render_tofor row lists. - Fan out events. One
PgListener::connect(url)per replica intotokio::sync::broadcast; oneConcurrentCounter-guarded SSE route per view;Laggedtriggers a snapshot resync. - Mount simulation when required. Bevy canvas with
data-ignore-morph,Messagefor frame telemetry andOn<E>for input reactions,postcardoverrama-wsfor high-frequency traffic,CustomEventfor the HUD. - Verify. Consumer lane, available wherever this skill is installed:
bun scripts/verify-archives.ts, run from the skill directory. Repository-only: the package gatebun scripts/gates.tsinvokes that verifier,bun scripts/check.tsruns the whole lane, andbun scripts/docs-corpus.ts --lockrefreshes the pin record. None of those three ship in the package. Runcargo sqlx prepare --checkin CI.
Verification
Five application tests, each the smallest thing that fails if its layer breaks. They assert the transport, not the framework; keep them beside the code they exercise.
| Layer | Test | Command |
| Gateway | #[tokio::test] calling the stream route, asserting text/event-stream and at least one datastar-patch-elements frame before the body ends | cargo test --test sse |
| Persistence | #[sqlx::test] for a migration plus a query_as! round trip, against a test database created from DATABASE_URL | cargo test --test db |
| Templating | a snapshot assertion on the rendered Markup, deterministic ids included | cargo test --test render |
| Simulation | a headless App with MinimalPlugins, one app.update(), asserting the queue drain wrote the message | cargo test --test sim |
| Transport | a rama WSS client against the upgrade route, asserting a postcard round trip and a clean close | cargo test --test wss |
cargo test --workspace runs all five. The archive gate is the fidelity lane, not an application test; cargo sqlx prepare --check belongs in CI beside both.
Anti-Pattern Matrix
| Anti-pattern | Failure | Instead |
LimitLayer as the open-stream cap | permit released at response handoff | ConcurrentCounter guard owned by the stream |
204 ending a stream | no patch and no error, but started/finished still fire — a silent dead stream | 410 plus a re-anchor patch |
Relying on Retry-After in the client | the engine never reads it | re-anchor, or retry: 'always' |
data-ignore on the canvas | plugin suppression, not a morph boundary | data-ignore-morph on canvas and container |
| 60 Hz coordinates through signals or HTML | DOM thrashing | binary frames over rama-ws |
| Buffered reader on the cross-frame telemetry lane | a two-update buffer used as an immediate one | MessageReader with #[derive(Message)] |
Nested html! inside a loop | one allocation per row | Render::render_to into one buffer |
Hand-concatenated data-signals JSON | escaping bypassed | serialize, then splice through Maud |
PgListener::connect_with(&app_pool) | the listener holds an application-pool connection for its life | PgListener::connect(url) |
test_before_acquire(true) everywhere | a round trip on every checkout | test_before_acquire(false) plus before_acquire on meta.idle_for |
| Aliased Datastar bundle | every data-* attribute is silently dead | serve the embedded unaliased bundle |
| SQL state without offline metadata | CI cannot build without a database | commit .sqlx/ and gate prepare --check |
Provenance
scripts/provenance.lock is the single pin record: the five repositories, their commits, their verification dates, and the local-corpus digest. The digest is local-corpus scoped because it also folds the cargo-registry crates, so the commit pins — not the digest — are the durable anchor; the digest mirrors the recorded corpus snapshot, and the corpus and lock are refreshed together when a claim is re-verified. This syllabus and its archives stay version-free so a stale release number cannot be mistaken for an observed claim; each archive keeps only its Re-verify when: trigger. Read the lock before trusting a claim, and move the pin when you re-verify one.
Reference Archives
references/rama.md— read before touching routing, SSE framing, the stream budget, CSRF, WSS upgrades, compression, or drain.references/sqlx.md— read before adding SQL, tuning the pool, writing a migration, or wiringPgListener.references/maud.md— read before changing templates, escaping, JSON attributes, orMarkupconversion.references/datastar.md— read before changing attributes, signals, actions, morph boundaries, CSP, or retry behaviour.references/bevy.md— read before touching ECS schedules, WASM builds, the canvas mount, or the shell bridge.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

