Repository navigation
MESH v0.11.0
MESH v0.11.0 release notes
Prepared 2026-10-13 (not yet released: v0.10.0 is the latest release).
v0.11 makes control flow part of the language. Conditional and repeated structure are written as blocks in an element's content, not as reserved elements, so a tool that lists a model's components has nothing to offer for control flow and a model declares nothing for it.
Highlights
-
Blocks.
{#if condition}…{:else if condition}…{:else}…{/if}, and{#each items as item (key)}…{/each}. A chain of{:else if}branches replaces the multi-way choice. The key of a repeat is mandatory.<list> {#if loading} <spinner /> {:else if failed} <note>Could not load</note> {:else} {#each users as user (user.id)} <user-card user={user} /> {/each} {/if} </list>
-
A branch or body is one element. If it is exactly one element it is that element; anything else (text, several nodes, none, a lone block or slot) is wrapped in a
mesh-fragmentfor you. -
Nothing to declare. The constructs a block lowers to (
mesh-if,mesh-each,mesh-fragment) are built in. A manifest need not declare them, one that does is used as declared, and the model fingerprint covers only what is declared. -
Same templates. The runtime,
template-v1,render-v1, node identities and handler identifiers do not change. A program written with the old elements compiles to the same templates, apart from source spans. -
Better messages. A mistake in a block names the block ("the condition of
{#if}"). A repeat without a key ismissing-repeat-key. Syntax errors in blocks say what is wrong and where: never closed, no open block, malformed opener. -
Editors. The Tree-sitter grammar and highlight queries, the TextMate grammar, completion after the openers, and hover and go-to-definition on a repeat's binding.
Upgrading
-
Move
@valancex/mesh-runtimeand@valancex/mesh-compiler(andmesh-lsp) to^0.11.0together. Before 1.0 a minor is a new range. -
Rewrite control flow as blocks.
retired-elementtells you which block to write.Before After <mesh-if when={a}>X</mesh-if>{#if a}X{/if}<mesh-if when={a}>X Y</mesh-if>(two alternatives){#if a}X{:else}Y{/if}<mesh-each items={xs} as="x" key={x.id}>X</mesh-each>{#each xs as x (x.id)}X{/each}<mesh-switch><mesh-case when={a}>X</mesh-case><mesh-default>Y</mesh-default></mesh-switch>{#if a}X{:else}Y{/if}A two-alternative
mesh-ifand an{#if}/{:else}are both conditional sites, but an{:else}is written as a second conditional (as amesh-switchwas), so node identities under the else branch differ from the second alternative of the old element. -
A model that declared
mesh-if,mesh-each,mesh-switch,mesh-caseormesh-defaultcan drop them; one that keeps them is used as declared.
Compatibility
- Breaking, before 1.0. The reserved elements are errors. Templates already compiled keep their meaning: stored renders and handler identifiers are unchanged.
- Tooling. Tag completion and component listing offer nothing for a block.
Target::Bindingis a new resolution target (a RustmatchonTargetneeds an arm). - Diagnostics. New codes
retired-elementandmissing-repeat-key.invalid-switchis no longer reported and stays in the catalogue. - npm. All packages move to 0.11.0 together.
Stability
Blocks, retired-element and missing-repeat-key are stable on release. The runtime's behavior for the constructs a template names (mesh-if, mesh-each, mesh-fragment and their identity steps) stays provisional.