Define, const, static, import

These four constructs are part of the portable structural core — they work the same way on every host.

import

Ordinary module imports, hoisted to the top of the compiled output:

import { formatDate } from "./util.ts"

<p>Published ${formatDate(post.date)}</p>

A .mx file compiles to a template — a component, not a module exporting plain helpers like formatDate — so import shared helpers from a .ts module. Import a .mx file itself to call it as a tag, the way <define> calls work.

static

Code that runs once, at module load, rather than once per render:

static
  const GREETING = "Welcome"

<h1>${GREETING}, ${user.name}</h1>

Use static for values or helpers that don’t depend on the current render’s input.

<const>

A non-reactive local binding, computed fresh on each render:

<const/total=items.reduce((sum, i) => sum + i.price, 0)/>

<p>Total: ${total}</p>

<const> never re-runs after its initial evaluation within a render — it isn’t a signal, and it isn’t watched for changes. Contrast this with <let>, which a reactive host can turn into real state; see Stateful tags.

<define>

A named, reusable template fragment, callable like any other tag:

<define/Badge|label, color|>
  <span style={background: color}>${label}</span>
</define>

<Badge label="New" color="green"/>
<Badge label="Sale" color="red"/>

<define> fragments take the same tag params and attribute tags as any other tag call.

A name that shadows input

A <const> (or <let>) binding named input at the top level of a template is rejected: it would shadow the parameter every compiled render function already has. A tag param named input — <for|input|>, <define/Row|input|> — is fine, because it opens a genuinely nested scope. See Errors.