Astro: .mx components and pages
Besides .astro.mx, the integration renders plain .mx files. They are a different kind of file: an .astro.mx is an Astro component, while a .mx compiles to a function from props to an HTML string that Astro calls at build time. Use .mx for a template you also render outside Astro, with the HTML target.
Both render static markup. The stateful tags (<let>, <effect>, <lifecycle>, <script>, <id>, client blocks) are build errors here.
Components
---
import Card from "../components/card.mx";
---
<Card title="Hello">
<p>Default slot content.</p>
<Fragment slot="footer">Footer content.</Fragment>
</Card>
export interface Input {
title: string;
content: () => string;
footer?: () => string;
}
<article.card>
<h2>${input.title}</h2>
<div>$!{input.content()}</div>
<if=input.footer>
<footer>$!{input.footer()}</footer>
</if>
</article>
Astro hands over its slots already rendered, and MX receives each as a function returning that HTML: the default slot is input.content, <Fragment slot="footer"> is input.footer, and props are props.
Render a slot with $!{…}, never ${…}. The slot is markup Astro already rendered; ${…} would escape it into visible angle brackets.
A client:* directive on an MX component fails the build and names the component: there is no state and no runtime, so there is nothing to hydrate.
Pages
A .mx file under src/pages is a page: src/pages/about.mx routes to /about.
export const layout = "../../layouts/Base.astro";
export const getStaticPaths = () => [
{ params: { slug: "first" }, props: { title: "First post" } },
{ params: { slug: "second" }, props: { title: "Second post" } },
];
<h1>${input.title}</h1>
<p>Reading ${input.params.slug} at ${input.url.pathname}.</p>
inputis the page’s props plusparamsandurl, which areAstro.paramsandAstro.url.export const layoutwraps the page in that layout’s default slot. Every other top-levelexport constbecomes afrontmatterkey for the layout, as with Astro’s Markdown pages.getStaticPaths,prerenderand any other export reach Astro’s router unchanged.
Typing .mx imports
With the TypeScript plugin configured, each imported .mx has its own props type, derived from the file. There is no ambient declare module "*.mx": one would give every component the same any props and hide every error.