Mesa guide / Reference
Every rule
The language spec numbers its rules. Each row is a one-line summary and a link to the section of VISION.md that states it in full.
| Rule | Summary | Section |
|---|---|---|
| 1 | $: is top-level only. A nested one is a compile error | 4.8 |
| 1b | An instance script runs in source order. A declaration is pulled up only when something already emitted needs it | 2 |
| 2 | A const that reads reactive variables is derived | 2.2 |
| 3 | Every reactive variable used in a template is wired automatically | 2 |
| 4 | Scoped variables are never tracked, but can read and write top-level state | 2 |
| 5 | All Mesa source and compiler output is valid JavaScript | 1 |
| 6 | Path watching uses optional-chaining semantics: ?. is soft, none is hard | 4.1 |
| 7 | In a watch with a handler, the handler is last and outside the parentheses | 4.2 |
| 8 | Shared state is plain JavaScript. A $: path makes it reactive per component | 5 |
| 9 | Store files cannot import component files. Not checked by the compiler | 5 |
| 10 | A circular reactive store import is an error | 5 |
| 11 | Static paths become targeted accessors. Dynamic paths become runtime effects | 14 |
| 12 | A template path is an ordinary expression. A nullish value renders empty | 14 |
| 13 | var reads without subscribing and writes without notifying | 6 |
| 13a | bind: on a var is a compile error that names oninput | 3.4 |
| 14 | A let initializer is a snapshot. Use $: name = expr to keep deriving | 2.1 |
| 14a | A writable derived override is temporary. A dependency change wins back | 4.5 |
| 14b | $: (a, b) is a multi-path watch. $: { } is an auto-tracked block effect | 4.4 |
| 15 | Components are ES modules, so top-level await is valid | 13.1 |
| 16 | $async.x exists for a top-level const x = await … and a top-level async function x() | 13.2 |
| 17 | A non-const reactive variable can be assigned any time. Last write wins | 13.3 |
| 18 | Builtins are reached through $, with no import | 17 |
| 18a | $ cannot be destructured, aliased or shadowed | 17 |
| 18b | $ does not exist in <script module> | 11 |
| 18c | $props, $attributes, $slots, $context and $async have a canonical bare spelling | 17 |
| 18d | Four prefixes: $, $:, $$ and __. The whole $$ prefix and the three __ names are reserved | 17 |
| 18e | $class and $dom are protocol names, never authored | 17 |
| 19 | On a server, signals are synchronous, $.onMount does nothing and $context is per instance | 19.3 |
| 20 | There is no hydration. An island is a fresh mount() into a marked range | 19.3 |
| 21 | The compiler targets @frontierjs/mesa/runtime | 1 |
| 22 | bind: is valid only on export let props | 3.4 |
| 22a | On an element, bind: is value, checked, files, group and this | 10.1 |
| 23 | One event spelling, onclick={fn}, with modifiers piped on | 8.2 |
| 24 | bind:group needs a top-level let | 10.3 |
| 25 | $context provides and consumes are top-level in the script | 7.1 |
| 25a | A const consumer tracks the provider. A let initializes at mount. A var snapshots | 7.4 |
| 25b | $context.<key> is a compile step, so script-only. context.use and context.provide work anywhere | 7.4 |
| 26 | client:* is stripped by the compiler. islands: true marks it in a server render | 18.6 |
| 27 | {#key expr} destroys and recreates its content when expr changes | 9.4 |
| 28 | {#snippet} defines a template fragment. {@render} mounts it | 9.5 |
| 29 | Snippets close over outer reactive variables. Arguments are plain values | 9.5 |
| 29b | Every non-void element closes explicitly. HTML's optional end tags are a parse error | 10 |
| 30 | <script module> runs once at module load, shared by all instances | 11 |
| 31 | class="…" on a component is forwarded to the child's class prop | 10.8 |
| 31a | $class is a protocol name. Use {class} or bind:class on the child element | 10.8 |
| 31b | bind:class on an element is a compile error. {class} is the merging form | 10.8 |
| 32 | bind:class and {class} on an element wire the parent's class through | 10.8 |
| 33 | {@html expr} injects raw HTML. Use it on trusted content only | 10.7 |
| 34 | {#virtual each} takes height and viewport. Variable row height is not supported | 9.7 |
| 35 | Snippet props are export let. <slot /> is the preferred way to receive content | 9.6 |
| 35a | children with {@render children?.(value)} is the form for content the child parameterizes | 9.6 |
| 35b | <slot> takes no attribute but name | 9.6 |
| 36 | bind:this on a component exposes exported props and functions, never a DOM node | 10.2 |
| 37 | $.mounted(fn) appears once per component | 12.6 |
| 37a | $.mounted(fn) is wired by name: const ready = $.mounted(fn) | 12.6 |
| 38 | <mesa:mounted> gates the whole component template | 12.6 |
| 39 | onerror on <mesa:mounted> runs on rejection, apart from the failed snippet | 12.6 |
| 40 | <mesa:boundary> and <mesa:mounted> resolve snippets in one order: local, global, blank | 12.6 |
| 41 | bind:value|mask needs a pattern argument in { } | 10.1 |
| 42 | $.inspect is dev-only, stripped when debug is false, and top-level only | 17 |
| 43 | Replacing a value notifies. Mutating one does not, unless a $: path covers it | 4.0 |
| 44 | Every let and const in the component is reactive. An import is inert until a $: names it | 4.0 |
| 45 | A watch fires only for writes through the proxy Mesa made | 4.1 |
| 46 | A watch covers its path and everything beneath it | 4.1 |
| 47 | Watches belong to the object, shared across components | 4.1 |
| 48 | delete obj.key notifies like obj.key = undefined | 4.1 |
| 49 | Date, Map, Set, RegExp, Promise, typed arrays and Error pass through the proxy untouched | 4.1 |
| 50 | A $: { } block whose statements are all bare reads is a compile error | 4.8 |
| 51 | Reactive logic does not belong in .js modules | 5 |
| 52 | In a $: { } block the handler is an inline function | 4.2 |
| 53 | The compiler reports and the build decides | 4.8 |
| 54 | createRoot gives ownership without tracking | 5 |
| 55 | Scoped CSS applies to the selector's subject. Cross a boundary with :global(...) | 5 |
| 56 | An instance script exports export let, export const, export var and export function, and nothing else | 3.5 |
| 57 | <mesa:element this={expr}> takes a non-empty tag name. A new tag rebuilds the element | 12.5 |
| 58 | An unknown mesa: name is a compile error | 12.5 |
| 59 | prev holds a reference. A mutated object gives the same reference for both | 4.2 |
| 60 | Auto-tracked effects run on mount and cannot be deferred | 4.3 |
| 61 | Everything that builds DOM runs before user effects in a flush | 4.7 |
| 62 | An auto-tracked effect's first run is during setup, before the template exists | 4.7 |
| 63 | In a .md file, {…} in prose is a bare path. Anything else is literal text | 18.4 |
| 64 | A call to an imported function re-runs when the component's import watches fire | 4.1 |
| 65 | $.after and $.every are top-level declarations. $.sleep works anywhere | 17 |
| 66 | setTimeout and setInterval in a script are a compile warning | 17 |
The numbers are citation keys and are never reused, so 18d can sit before 18c
in the spec. Page footers in this guide cite them.
Spec: VISION.md § 22