Ox / Hypermedia · StarioStarioHypermedia
Server<br>Hypermedia<br>Deploy<br>Blog<br>About
Try it here<br>Write the order. Print the ticket.<br>Order<br>Print ticket<br>Kitchen
No ticket yet.
One attribute. Exact behavior.<br>The markup says what happens.<br>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.<br>index.htmlCopy<br>moo="{ init: 'st.cups ??= 1' }"> moo="el.textContent = st.cups">1> moo="{ click: 'st.cups = Math.max(0, st.cups - 1)' }">−> moo="{ click: 'st.cups++' }">+> moo="{ click: 'ox.post(\"/ox/demo/order\", { body: { cups: st.cups } })' }"> Print ticket >>
01Initialize local state.<br>The element creates the value only when it is missing. There is no component instance or store setup.
02A read becomes reactive.<br>The output reads st.cups. Ox remembers that dependency and reruns the expression after a write.
03DOM events use JavaScript.<br>The click handler is an ordinary assignment. Event names are real DOM event names.
04–06Call the server when useful.<br>ox.post sends only the body you pass. Print ticket uses that call. Stario morphs the ticket.
Built to stay direct<br>A small browser tool that shows its work.<br>Ox adds reactivity without turning the page into a second application. Its state, events, server calls, and trust boundary stay visible in the HTML.<br>01Behavior stays with the element.<br>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.
02One reactive state bag.<br>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.
03The server is optional, not separate.<br>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.
04A small delivery surface.<br>Load one script. There is no bundler, component runtime, generated client, or build step. The page remains HTML that the server can render.
05The boundary is stated.<br>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<br>Add one script. Keep the page.<br>The guide starts with local state, then adds the server.
Open the Ox guide
Also<br>Stario / Server<br>The Python server path.
Orbit / Deploy<br>The deploy steps you wrote.
Made by Adam with Stario
Server<br>Hypermedia<br>Deploy<br>Blog<br>About<br>Theme
Made by Adam with Stario