Getting Started
Install Astro Utils Forms and run a complete server action without an external service.
View MarkdownBuild a form that sends a name to your server and renders a greeting. Start inside an existing Astro project; no database or email provider is needed.
1. Install Forms and the adapter
Section titled “1. Install Forms and the adapter”npm install @astro-utils/forms @astrojs/nodebun add @astro-utils/forms @astrojs/nodepnpm add @astro-utils/forms @astrojs/nodeyarn add @astro-utils/forms @astrojs/node2. Configure Astro
Section titled “2. Configure Astro”import { defineConfig } from 'astro/config';import node from '@astrojs/node';import forms from '@astro-utils/forms/dist/integration.js';
export default defineConfig({ output: 'server', adapter: node({ mode: 'standalone' }), integrations: [forms]});3. Add middleware
Section titled “3. Add middleware”import forms from '@astro-utils/forms';
export const onRequest = forms();The default is enough for local development. For deployed projects, pass a stable environment secret through the middleware configuration. Keep it stable across restarts and out of source control. For an existing middleware chain, compose this middleware with Astro’s sequence() helper.
4. Add the shared layout
Section titled “4. Add the shared layout”Use one WebForms root around your form content. The examples throughout these docs import this layout.
---import { WebForms } from '@astro-utils/forms/forms.js';---<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <title><slot name="title" /></title> </head> <body> <WebForms> <slot /> </WebForms> </body></html>5. Create your first form
Section titled “5. Create your first form”Save the following page as src/pages/hello.astro. Preview simulates the same interaction inside the docs; running the page in your own project executes the callback on your server.
---import { BButton, BInput, Bind, BindForm, FormErrors } from '@astro-utils/forms/forms.js';import Layout from '../layouts/Layout.astro';
const bind = Bind({ name: '' });let message = '';
function greet() { message = `Hello, ${bind.name}! Your server action ran.`;}---<Layout> <span slot="title">Your first form</span> <BindForm {bind}> <FormErrors />
<label for="name">Your name</label> <BInput id="name" name="name" required maxlength={40} />
<BButton onClick={greet} whenFormOK>Say hello</BButton> {message && <p role="status">{message}</p>} </BindForm></Layout>6. Run it
Section titled “6. Run it”Start your Astro project with your package manager’s dev script. Open /hello on the URL printed by Astro, enter a name, and select Say hello. You should see Hello, Alex! Your server action ran. when you enter Alex. An empty name prevents the valid-only callback.
What happens on submit
Section titled “What happens on submit”WebFormsreceives the POST request.BindFormrestores state and validates the submitted controls.BButtoncallsgreetwhen validation succeeds.- The form renders again with the updated message.
message is request-local feedback. Use omitState when feedback is stored on bind but should not persist into the next submission.
Next steps
Section titled “Next steps”Learn binding and validation, or adapt the account example to your application. If the action does not run, check server rendering, middleware, the integration, and the WebForms layout first.