Getting started
Pick where you render
FlowView is pre-1.0. Every npm command below installs a published package. Requires Node.js 22.12 or newer for the JavaScript tooling.
Astro
Supports Astro 5, 6 and 7. Embed templates in .astro files, or import standalone.flow files.
1. Install
sh npm install @flowview/astro @flowview/runtime2. Configure
js // astro.config.mjs import { defineConfig } from "astro/config"; import flowview from "@flowview/astro"; export default defineConfig({ integrations: [flowview()], });3. Write a template
astro <template flowview={context} is:raw> @if (context.user) { <h1>Hello {{ context.user.name }}</h1> } </template>
Add Events to Astro
npm install @flowview/astro-events @flowview/events @flowview/vite-events// astro.config.mjs
import { defineConfig } from "astro/config";
import flowview from "@flowview/astro";
import flowviewEvents from "@flowview/astro-events";
export default defineConfig({
integrations: [flowviewEvents(), flowview()],
});Then write (click)="save()" in a template and declare save in one<script data-flowview> block. See Events →
Vite, Hono, Node.js and Workers
Supports Vite 6, 7 and 8. A .flow import is a module exportingrender(context). Your server decides when to call it.
1. Install
sh npm install @flowview/vite @flowview/runtime2. Configure
ts // vite.config.ts import { defineConfig } from "vite"; import flowview from "@flowview/vite"; export default defineConfig({ plugins: [flowview()], });3. Render from a route
Honots import { render } from "./users.flow"; app.get("/users", async (c) => { return c.html(render({ users: await getUsers() })); });Or from a Worker
Cloudflare Workersts import { render } from "./page.flow"; export default { async fetch() { return new Response(render({ title: "Hello" }), { headers: { "Content-Type": "text/html; charset=utf-8" }, }); }, };
Add Events to Vite
npm install @flowview/vite-events @flowview/events// vite.config.ts
import { defineConfig } from "vite";
import flowview from "@flowview/vite";
import flowviewEvents from "@flowview/vite-events";
export default defineConfig({
// Events must run before the HTML compiler sees the template.
plugins: [flowviewEvents(), flowview()],
});The <script data-flowview> block is served as a virtual module, so your client entry must import it, and your server must emit that script tag. The repository's Hono example shows the full wiring.
TypeScript: add "types": ["@flowview/vite/client"] to import .flow files.
Browser DOM
For a small client-side UI, compile a .flow file with Vite or Astro and mount it with@flowview/dom. Each update() replaces the target's HTML. State is yours to manage;@flowview/reactive is optional.
1. Install
sh npm install @flowview/dom @flowview/vite @flowview/runtime2. Template
items.flowflow <ul> @for (item of context.items; track item.id) { <li [class.done]="item.done">{{ item.name }}</li> } @empty { <li>Nothing yet</li> } </ul>3. Mount and update
ts import { createView } from "@flowview/dom"; import { render } from "./items.flow"; const view = createView("#app", render); view.render({ items: [] }); view.update({ items: [{ id: 1, name: "Ship it" }] });4. Optional state
ts import { createView } from "@flowview/dom"; import { effect, signal } from "@flowview/reactive"; import { render } from "./items.flow"; const state = signal({ loading: false, items: [] }); const view = createView("#app", render); // The one explicit boundary: state -> view. effect(() => { view.update(state()); });
Native Rust static rendering
Render templates to HTML from Rust with no Node.js, browser or JavaScript engine. The context is JSON, and templates use a deterministic expression subset (property paths, literals, comparisons and boolean operators). Function calls are rejected with a diagnostic.
Add the crate
# Not yet published on crates.io; depend on the Git repository.
cargo add --git https://github.com/Andersseen/flowview flowview-compiler
cargo add serde_jsonflowview-compiler is not yet published on crates.io, so the command above uses the Git repository.
Compile once, render many
use flowview_compiler::{compile_static, StaticCompileOptions};
let template = compile_static(source, StaticCompileOptions::default())?;
for page in &pages {
let context = serde_json::to_value(page)?;
let html = template.render(&context)?;
// write html ...
}Prefer the command line? Build the CLI from the repository and runflowview compile page.flow --target static-html --data context.json. See theRust embedding guide.