---
title: "How Web Pages Work · RUAL Documentation"
description: "What a RUAL web page is: a template rendered on the server, a small script, and actions that answer with only the parts of the page that changed."
canonical: https://docs.rual.nl/web/overview
language: en
---

# Web Pages

A web page is a URL, a short flow and a template. The server sends finished HTML, and buttons and forms update only the part of the page that changed: one row, one counter, the errors of one form.

In short

- A [`web_page`](https://docs.rual.nl/block-types/web/web_page) block owns a URL. Its flow reaches a [`web_render`](https://docs.rual.nl/block-types/web/web_render), which turns a template into the whole page.

- A button with `data-action="delete"` runs the [`web_action`](https://docs.rual.nl/block-types/web/web_action) named `delete` in the same blueprint, which answers with only the changes.

- There is no frontend framework and no build step. The browser gets complete HTML and one small script, under 4 KB when compressed.

- Web pages replace state pages and UI components for new work.

## A page answers two kinds of request

Each kind starts its own flow in the same blueprint.

| Request | Starts | Answers with |
| --- | --- | --- |
| Opening the page (`GET /shop`) | [`web_page`](https://docs.rual.nl/block-types/web/web_page) | The whole page, from [`web_render`](https://docs.rual.nl/block-types/web/web_render). |
| Clicking a button or sending a form on that page (`POST /shop`) | The [`web_action`](https://docs.rual.nl/block-types/web/web_action) whose name the button carries | Only the changes: replace this row, remove that one, show these field errors. |

When a visitor deletes a row, this is all that crosses the network on the way back. The script in the page applies it, and nothing else on the page moves:

```
{"ops": [{"op": "remove", "key": "p1"}]}
```

An action is posted to the page's own URL, so the page's scopes decide first who may use it. An action can carry scopes of its own. An action without them is allowed only for visitors every page of the blueprint allows, so a public page is never the way in to an action meant for an admin page in the same blueprint. A request from another website is refused. [Escaping and Security](https://docs.rual.nl/web/security#who-may-run-an-action) has the rules.

[`web_render`](https://docs.rual.nl/block-types/web/web_render) also works outside a web page: in the flow of an API endpoint it answers that request with the finished HTML. That page has no script and no actions.

## What you get without building it

- **A page search engines can read.** The title, description, canonical link, Open Graph tags, Twitter card, hreflang links and structured data are in the HTML when it leaves the server. See [SEO and Sharing](https://docs.rual.nl/web/seo).

- **Escaping that follows your markup.** A value in text, a link, a script or a style attribute is written safely for that place, and a template that cannot be made safe refuses to compile. See [Escaping and Security](https://docs.rual.nl/web/security).

- **A Content Security Policy with a fresh nonce** on every page, so a string that sneaks into your HTML cannot run as a script.

- **Forms that check themselves.** Required fields, email addresses, patterns and lengths are judged in the browser, with no request. Your server's own messages land next to the right field. See [Forms and Validation](https://docs.rual.nl/web/forms).

- **Forms that survive without JavaScript.** A plain form post runs the same action and sends the visitor back to a page.

- **Loading states and small interactions.** Spinners, disabled buttons, confirm dialogs, optimistic removal and show or hide toggles come from a few attributes. See the [Markup Reference](https://docs.rual.nl/web/markup).

- **Speed on every request.** Templates compile once, unchanged pages answer with a 304, and links a visitor hovers load before the click. See [Speed and Caching](https://docs.rual.nl/web/speed).

- **One page in many languages.** A URL per language, hreflang and `og:locale` written for you, translations, and numbers and money in the page's language. See [Languages](https://docs.rual.nl/web/languages).

> **Web pages replace state pages and UI components for new work** State pages and UI components keep running, but new pages should be web pages. They hold no state on the server between requests and need no React and no WebSocket. Typing into a form costs nothing, because what the browser can judge never reaches the server. [Migrating from State Pages](https://docs.rual.nl/web/migrate-from-state-pages) shows which web block replaces what, what has no direct replacement, and a safe order to move a page in.

## Where to go in this section

- [Your First Page](https://docs.rual.nl/web/first-page): Publish a page in five minutes, from an empty blueprint to a working URL.

- [Tutorial: A Small Webshop](https://docs.rual.nl/web/build-a-shop): A product list, a product page, live search, a cart and a checkout form.

- [Template Syntax](https://docs.rual.nl/web/templates): Values, conditions, loops and every filter, each with an example.

- [Layouts and Partials](https://docs.rual.nl/web/layouts-and-partials): Store a template once and reuse it on every page.

- [Lists and Tables](https://docs.rual.nl/web/lists): Keyed rows from a storage search, so an action can reach exactly one row.

- [Actions](https://docs.rual.nl/web/actions): Who may run an action, and every block it can answer with.

- [Forms and Validation](https://docs.rual.nl/web/forms): Browser checks, server errors next to the field, and forms without JavaScript.

- [Markup Reference](https://docs.rual.nl/web/markup): Every attribute the script in the page reads, and the hooks for your CSS.

- [SEO and Sharing](https://docs.rual.nl/web/seo): The head tags written for you and how to add or override your own.

- [Languages](https://docs.rual.nl/web/languages): URLs and domains per language, hreflang and localized numbers.

- [Speed and Caching](https://docs.rual.nl/web/speed): ETags, shared caching, prefetching and what each of them leaves out.

- [Escaping and Security](https://docs.rual.nl/web/security): How values are escaped, what refuses to compile, the policy and the gates.

- [Building with AI](https://docs.rual.nl/web/with-ai): What to ask an agent for, and the habits that keep its pages consistent.

- [Migrating from State Pages](https://docs.rual.nl/web/migrate-from-state-pages): Which block replaces which, and a safe order to move a page in.

## Next steps

- [Your First Page](https://docs.rual.nl/web/first-page): From an empty blueprint to a working URL in five minutes.

- [Tutorial: A Small Webshop](https://docs.rual.nl/web/build-a-shop): Everything in this section used together, step by step.

- [Migrating from State Pages](https://docs.rual.nl/web/migrate-from-state-pages): Which web block replaces what, for pages you already have.

## Frequently asked

**Can I build a website or webshop with RUAL blueprints?**

Yes. A web_page block gives a URL a flow, and web_render renders its template on the server into a complete HTML page with title, meta description, canonical link, Open Graph and Twitter tags, hreflang links and JSON-LD. Templates use Mustache, the same syntax as mail templates, and shared pieces such as a layout, header or product card are stored templates used by name.

**Should I use web pages or state pages in RUAL?**

Web pages. State pages and UI components are deprecated: existing pages keep running, but new work should use the web blocks, which send a complete page from the server with its SEO tags already in it, and update only what changed. The migration guide shows which web block replaces what.
