JavaScript Runtime
Use Xote's compiled runtime from JavaScript projects without ReScript JSX.
Xote is a ReScript-first library, but the package also ships JavaScript modules that can be imported by JavaScript applications.
The main difference is syntax: ReScript projects usually use Xote's JSX integration, while JavaScript projects should use the runtime constructors directly.
Install
1npm install xote
Use the Client Entry
For browser-rendered UI, import from xote/client. It contains the core rendering modules without router, SSR, hydration, or MDX code.
1import { Signal, Computed, Effect, View } from "xote/client";
Use the other entries only when a feature needs them:
xote/clientfor client-side viewsxote/routerfor routingxote/ssrfor server renderingxote/hydrationfor client hydrationxote/mdxfor MDX integration
JavaScript Counter
Build Xote views with View.element(tag, attrs, events, children). Attributes are View.attr(name, value) pairs. Events are [eventName, handler] pairs.
1import { Signal, Computed, Effect, View } from "xote/client";23const count = Signal.make(0);4const doubled = Computed.make(() => Signal.get(count) * 2);56Effect.run(() => {7 console.log("Count:", Signal.get(count));8});910const increment = () => {11 Signal.update(count, n => n + 1);12};1314const app = View.element("main", [View.attr("class", "counter")], [], [15 View.element("h1", [], [], [View.text("Counter")]),16 View.element("p", [], [], [17 View.text("Count: "),18 View.signalText(() => String(Signal.get(count))),19 ]),20 View.element("p", [], [], [21 View.text("Doubled: "),22 View.signalText(() => String(Signal.get(doubled))),23 ]),24 View.element(25 "button",26 [View.attr("type", "button")],27 [["click", increment]],28 [View.text("Increment")],29 ),30]);3132View.mountById(app, "app");
The reactive reads happen inside Computed.make, Effect.run, and View.signalText. When count changes, the text nodes update in place.
Working with Existing Apps
Xote can be mounted into any existing DOM node:
1<div id="xote-widget"></div>2<script type="module" src="/src/widget.js"></script>
1import { Signal, View } from "xote/client";23const label = Signal.make("Save");45View.mountById(6 View.element("button", [], [["click", () => Signal.set(label, "Saved")]], [7 View.signalText(() => Signal.get(label)),8 ]),9 "xote-widget",10);
That makes JavaScript usage a good fit for small widgets, gradual adoption, and integration tests around the compiled runtime. New full applications should still prefer ReScript so the JSX and type system work together.