Ox / Hypermedia

Behavior, right where it happens.

moo= for reactive signals and ordinary JavaScript on the element itself. Datastar SSE when the interaction has to cross the wire and patch HTML and state.

~8 kB gzip · no build · no DSL

Try it here

Write the order. Print the ticket.

Order

1

Kitchen

No ticket yet.

One attribute. Exact behavior.

The markup says what happens.

Start with local behavior. Add the server only when the interaction needs to cross the wire. The attribute is moo= — in case you were wondering what the ox says.

index.html
<div moo="{ init: 'st.cups ??= 1' }">
  <output moo="el.textContent = st.cups">1</output>
  <button moo="{ click: 'st.cups = Math.max(0, st.cups - 1)' }"></button>
  <button moo="{ click: 'st.cups++' }">+</button>
  <button moo="{ click: 'ox.post(\"/ox/demo/order\", { body: { cups: st.cups } })' }">
    Print ticket
  </button>
</div>

Built to stay direct

A small browser tool that shows its work.

Ox adds reactivity without turning the page into a second application. Its state, events, server calls, and trust boundary stay visible in the HTML.

01

Behavior stays with the element.

Write exact JavaScript in moo= beside the element it affects. Expressions receive el, st, evt, and ox; there is no second template or directive language.

02

One reactive state bag.

The page shares one st object. Effects track the values they read, and ordinary object or array writes update only the expressions that depend on them.

03

The server is optional, not separate.

Local interaction can stay in the browser. When the server is useful, ox.get and ox.post send only the query or body you pass, then apply Datastar SSE patches from the response stream.

04

A small delivery surface.

Load one script. There is no bundler, component runtime, generated client, or build step. The page remains HTML that the server can render.

05

The boundary is stated.

Ox is for server-owned HTML, not untrusted markup or a React replacement. Expressions use new Function, so a strict CSP needs an explicit unsafe-eval decision.

See when Ox fits

Add one script. Keep the page.

The guide starts with local state, then adds the server.