What is a server action?

A server action is a function that runs on the server when a user submits a form. The browser sends the form data, the server processes it, and sends back a response — all without you writing any API endpoints.

The flow

Here's what happens when someone clicks "Save" on your form builder:

  1. Form — The browser collects the field values and sends them to the server
  2. Action — The server function receives the form data
  3. Validate — Check the input against your schema (e.g., title is required)
  4. Model — Call Form.create(data) to write to the database
  5. Respond — Redirect on success, or return errors for the form to display

This all happens in a single route file. The action export handles the form submission the same way the loader export handles page loads.

Why not call the database from the browser?

The database runs on the server. Browser code can't reach it directly — and you wouldn't want it to. If the database were accessible from the browser, anyone could read, modify, or delete data by opening the developer console.

Server actions keep the boundary clear: the browser sends data, the server decides what to do with it. Validation, authorization, and database access all happen where they can't be tampered with.

Two ways actions respond

  • redirect() — On success, send the user to a new page (e.g., the results page after creating a form)
  • return { errors } — On validation failure, send the errors back so the form can show them next to the relevant fields

This is the same pattern you'll see in every route that handles form submissions — create, update, delete. The action receives data, validates it, talks to a model, and responds.

?The loader → Page → action cycle