Astro Actions
Astro Actions are typed server functions. Use an action for a form that validates input and changes server state.
The Verge Kit starter includes an empty action registry at src/actions/index.ts.
1. Define the action
Replace the empty registry with one action:
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
saveTheme: defineAction({
accept: 'form',
input: z.object({
theme: z.enum(['light', 'dark']),
}),
handler: async ({ theme }, context) => {
context.cookies.set('theme', theme, {
path: '/',
sameSite: 'lax',
secure: import.meta.env.PROD,
});
return { message: 'Theme saved.' };
},
}),
};The input schema validates the form before the handler runs. The handler stores the preference and returns a small result.
2. Use the action in a form
Add the action to an Astro page:
---
import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.saveTheme);
---
{result?.data && <p role="status">{result.data.message}</p>}
{result?.error && <p role="alert">The theme was not saved.</p>}
<form method="POST" action={actions.saveTheme}>
<label for="theme">Theme</label>
<select id="theme" name="theme" required>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<button type="submit">Save theme</button>
</form>The form works without client JavaScript. Astro returns validation errors in result.error and successful data in result.data.
Astro exposes every action as a public endpoint. For a private action, authorize the user in the handler before you change data.
Related guides
- Astro Actions guide - Official guide for the complete Astro Actions workflow
- bejamas/ui forms with Astro Actions - Building validated forms for Astro Actions with bejamas/ui field primitives