Server-first forms for Astro
Your form.
Your server.
One place.
Form state, validation, and server actions in your .astro components. Build interactive forms with the server tools you already know.
---import { getCollection } from "astro:content";import { Bind, BindForm, BInput, BButton } from "@astro-utils/forms/forms.js";import Layout from "../layouts/Layout.astro";
const bind = Bind({ query: "" });
let products = await getCollection("products");
async function search() { products = products.filter(product => product.name.toLowerCase().includes(bind.name.toLowerCase()) );}---
<Layout> <BindForm {bind}> <label for="query">Find a product</label>
<BInput id="query" name="query" /> <BButton onClick={search}>Search</BButton>
<p>{products.length} products found</p>
<ul> {products.map(({ data }) => <li>{data.name} — ${data.price}</li>)} </ul> </BindForm></Layout>Search an Astro content collection on the server. Render the results here. Setup and collection schema →
Start with something useful.
All examples ↗
Add and remove persisted items while the form automatically renders the latest server state.

Upload a file in bounded chunks and show progress before processing it on the server.

Group an application into sections and save a small draft in the session.
Build on Astro.
Building with an AI agent?
Give your agent the documentation index, start with the implementation guide, or download the complete Markdown documentation. All examples include source files.
Coming from ASP.NET, PHP, or Next.js?
Astro Utils brings familiar server-side ideas into Astro: bound controls and postbacks for ASP.NET developers, HTML close to server logic for PHP developers, and form actions close to the UI for Next.js developers. The APIs and state model are specific to Astro Utils.