Hosts
A host is a framework MX compiles into. You keep writing that framework’s components: its props, state, hooks, signals, router and build tools are untouched. MX replaces one thing, the markup, and compiles it back to the JSX or template the framework expects.
Here is a React component, first in JSX, then with MX where the JSX was.
import { Dialog } from "./Dialog.tsx";
export function Invite({ team, open, send }: { team: string; open: boolean; send: () => void }) {
return (
<Dialog
open={open}
title={
<>
Invite to <b>{team}</b>
</>
}
actions={
<button className="primary" onClick={send}>
Send invite
</button>
}
>
<input name="email" id="email" className="field" type="email" required />
</Dialog>
);
}
import { Dialog } from "./Dialog.tsx";
export function Invite({ team, open, send }: { team: string; open: boolean; send: () => void }) {
return (
<Dialog open=open>
<@title>Invite to <b>${team}</b></@title>
<input:email#email.field type="email" required/>
<@actions><button.primary onClick=send>Send invite</button></@actions>
</Dialog>
);
}
Three things changed, and they are the same on every host:
- Attribute tags.
<@title>and<@actions>are thetitleandactionsprops. A prop that holds markup is written as markup, where it belongs in the tree. When the component declares it withAttrTag, asDialogdoes, it is checked against that type. - Name sugar.
<input:email#email.field>isname="email" id="email" class="field".<button.primary>isclass="primary". - No closing ceremony. No fragments around a prop’s markup, no
{}around every value, noclassName.
Dialog did not change. It is the same hand-written React component in both files; its title and actions props are typed AttrTag, which on React is a ReactNode.
MX is not released yet. These pages describe MX 1.0.
Pick your framework
| Host | You write | MX replaces |
|---|---|---|
| React | Team.react.mx, a TSX module |
the JSX |
| Preact | Team.preact.mx, a TSX module |
the JSX |
| Hono | Team.hono.mx, a TSX module |
the hono/jsx JSX |
| Solid | Team.solid.mx, a TSX module |
the JSX; <if> and <for> become <Show> and <For> |
| Astro | Team.astro.mx, an Astro component |
the template under the --- fence |
| Angular | team.component.ng.mx, a component module |
the value of template: |
Each page opens with the same component in the framework’s own syntax and in MX, then the setup.
What you get on every host
- Control flow as tags.
<if>,<else>and<for>compile to what the framework wants: a ternary and a keyed.map()on React,<Show>and<For>on Solid,@ifand@foron Angular. - Attribute tags. Named slots and render props as nested markup:
<@header>,<@row|item|>. - Name sugar.
#id,.classand:name, on the tag or among its attributes. - Errors at the line you wrote. Type errors and MX errors are reported in the
.mxfile, in the editor and inmx-tsc. - No MX component model at run time. The output is the framework’s own code, plus a small
/runtimeimport on the JSX hosts for class objects and<try>.
No framework?
MX also compiles without a host: to HTML strings for a server or a static build, and to a data tree when the markup describes data instead of a page.