Flowmark
HTML-like templates with modern control flow. Compiled to plain JavaScript.
Astro-native authoring
@if, @else if, @for, @switch
Inline
template
Rust
compiler
Astro
host
Why Flowmark?
A template language designed for clarity and performance.
Modern control flow
Write @if, @else if, @for, @empty, and @switch blocks that read like the host language you already know.
Rust compiler
Templates are parsed and compiled to plain JavaScript render functions at build time. No runtime parser, no VDOM.
Framework agnostic
Use Flowmark as standalone .flow files with Vite or embed regions directly inside Astro components.
Secure by default
Interpolated values are HTML-escaped automatically. Templates are trusted source code, not user input.
Familiar syntax
Control flow that reads like the host language you already know.
@if (user.isAdmin) {
<span>Admin</span>
} @else if (user.isMember) {
<span>Member</span>
} @else {
<span>Guest</span>
}
Branch on conditions with @if, @else if, and @else.
@for (product of products; track product.id) {
<article>
<h3>{{ product.name }}</h3>
<p>{{ product.price }}</p>
</article>
} @empty {
<p>No products found.</p>
}
Loop over iterables with optional keyed tracking and an @empty fallback.
@switch (product.status) {
@case ('available') {
<span>In stock</span>
}
@case ('sale') {
<span>On sale</span>
}
@default {
<span>Out of stock</span>
}
}
Match expressions against multiple cases with a fallback @default.
How it works
From template source to server-rendered HTML.
-
1. Author
Write a Flowmark region inside .astro or a standalone .flow file.
-
2. Compile
The Rust compiler parses the template and emits a plain JS render function.
-
3. Inject
The Astro or Vite plugin replaces the region with the generated render call.
-
4. Render
Astro evaluates the function at build time and emits static HTML.
Real-world example
A changelog list rendered with Flowmark control flow inside an Astro component.
-
Feature Breaking Structured HTML and serializable diagnostics
v0.2.0The parser now understands tags and attributes, and diagnostics carry precise spans and stable error codes.
Released 2026-06-24
-
Fix Shared JavaScript expression scanner
v0.1.3Interpolation, parenthesized expressions, and for-headers now share one scanner for strings, comments, regex, and template literals.
Released 2026-06-20
-
Feature Astro integration and inline authoring
v0.1.0Embed Flowmark regions directly inside .astro files with <template flowmark is:raw>.
Released 2026-06-15
-
Docs Documentation and security policy
v0.0.5Added the specification, security model, and contribution guidelines.
Released 2026-06-10
Get started
Add Flowmark to an Astro project and embed your first template region.
Install
Add the Astro integration and runtime to your project.
npm install @flowmark/astro @flowmark/runtime
Configure
Register the integration in your astro.config.mjs file.
import flowmark from "@flowmark/astro";
export default defineConfig({
integrations: [flowmark()],
});
Write
Add a Flowmark region to any .astro component.
<!-- prettier-ignore -->
<template flowmark is:raw context={context}>
@for (item of context.items; track item.id) {
<p>{{ item.name }}</p>
}
</template>