# Getting Started

Install Astro Utils Forms and run a complete server action without an external service.

Source: https://withastro-utils.github.io/docs/guides/forms/getting-started/

Build 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.

**Use server rendering**

Forms need on-demand rendering. This guide configures the Node adapter and a single `WebForms` root.

## 1. Install Forms and the adapter

```sh title="Terminal"
npm install @astro-utils/forms @astrojs/node
```

```sh title="Terminal"
pnpm add @astro-utils/forms @astrojs/node
```

```sh title="Terminal"
yarn add @astro-utils/forms @astrojs/node
```

```sh title="Terminal"
bun add @astro-utils/forms @astrojs/node
```

## 2. Configure Astro

```js title="astro.config.mjs"
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

```ts title="src/middleware.ts"
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](https://withastro-utils.github.io/docs/reference/forms/configuration/index.md). 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

Use one `WebForms` root around your form content. The examples throughout these docs import this layout.

```astro title="src/layouts/Layout.astro"
---
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

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.

### src/pages/hello.astro

```astro title="src/pages/hello.astro"
---
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

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

1. `WebForms` receives the POST request.
2. `BindForm` restores state and validates the submitted controls.
3. `BButton` calls `greet` when validation succeeds.
4. 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

Learn [binding and validation](https://withastro-utils.github.io/docs/guides/forms/data-binding/index.md), or adapt the [account example](https://withastro-utils.github.io/docs/examples/signup/index.md) to your application. If the action does not run, check server rendering, middleware, the integration, and the `WebForms` layout first.
