---
title: "Documentation — PageWeave"
---

> For the full documentation index, see [PageWeave Documentation](https://pageweave.dev/docs) or fetch [llms.txt](https://pageweave.dev/llms.txt).

# Core Concepts

Understanding PageWeave's architecture and data model.

## Websites

A website is the top-level entity. Each website has:

- **Subdomain** — auto-generated (e.g., `my-site.pageweave.site`)
- **Hostnames** — names attached to the site that serve or redirect it (e.g. `example.com`; optional)
- **Theme** — daisyUI theme applied to all pages
- **Language** — BCP 47 tag (e.g., `en`, `de`). For multilingual sites, see the [Internationalization (i18n) guide](/docs/i18n).
- **agents_md** — private Markdown instructions agents write for other agents working on the site, following the [AGENTS.md open standard](https://agents.md/). Not publicly served. Read it first when picking up an unfamiliar website.

Everything the agent creates is **live immediately** — there is no draft/published review gate. Every change is versioned. Freezing content to a specific version is done per surface with **releases**.

## Pages

Pages are versioned HTML and/or Markdown content at URL paths:

- **Path** — URL anchor (e.g., `/`, `/about`, `/contact`)
- **Versions** — every edit creates a new version; the newest version is live (releases freeze per environment)
- **Title** — plain text for `<title>` and metadata (no Liquid; write `&` literally — stray HTML entities like `&amp;` are decoded automatically)
- **HTML body** — raw HTML, the default representation. Supports Liquid.
- **Markdown body** — served to agents (`Accept: text/markdown`) and at the `.md` URL. Supports Liquid.
- **additional_html_head_html** — page-specific `<head>` content (meta tags, Open Graph, schema.org, favicons, custom CSS), rendered after the global `html_head`. Supports Liquid.
- **Language** — optional per-page override (BCP 47 tag)
- **Template pages** — pages bound to a data table; path placeholders map to row fields (e.g. `/posts/:slug`). See [Data Tables](/docs/tables).

### Versioning

Every edit creates a new version with:

- Sequential version number
- Timestamp
- Rollback reference

`revert_version` creates a new version with old content — it never deletes anything. Freezing a version is done with releases: a release snapshots the latest versions of all pages, components, snippets, and the theme into an immutable manifest; attaching it to an environment serves exactly those versions on that surface.

## Components

### Header, Footer & HTML Head

Instance-based HTML components with versioning **and display conditions**. A website can have multiple instances per component type; instances **without conditions** are the fallback (render everywhere), instances **with conditions** render only where they match (path, language, host, row, indexable) — lowest `priority` wins. Routing lives on **versions**, so condition changes are versioned like content (revertible).

`create_component`/`list_components`/`delete_component` manage instances; `get_component`/`update_component` operate on the fallback instance without `instance_id` (auto-creating one on update when none exists) or on a specific instance with it (`component` accepts `header`, `footer`, or `html_head`). Conditioning ALL instances of a type removes chrome from non-matching pages — the update tools warn about this.

The global `html_head` is additional `<head>` content (meta tags, tracking scripts, analytics, favicons) rendered on every page, before each page's `additional_html_head_html`. Versioned like pages — manage it via `update_component` with `component: "html_head"`. Per-path/per-language instances give you per-page heads.

## Themes

daisyUI 5 + Tailwind CSS v4 theme system:

- **Built-in themes** — 35+ themes (nord, sunset, dark, etc.)
- **Custom themes** — custom CSS variables with a `[data-theme]` selector
- **Instant changes** — CSS variables update, no re-render needed

See [Themes](/docs/themes).

## Snippets

Versioned text files served at `/snippets/<path>` on the website's domain:

- **Types** — CSS, JS, JSON, HTML, SVG, XML, YAML, Markdown, CSV, plain text
- **Path** — relative, no leading slash (`css/style.css`, `js/app.js`)
- **Versioning** — every edit creates a new version; revert like pages
- **Size limit** — 256 KB per version
- **Content type** — inferred from extension when omitted
- **Skip-unchanged** — identical content creates no new version
- **Canonical URLs are unversioned** — reference snippets by their canonical URL; the platform rewrites refs to content-hash-marked URLs (`/snippets/style.h1a2b3c4d.css`) at render time, served with `Cache-Control: public, max-age=31536000, immutable` (marker = content-hash cache key: identical content always maps to the same URL). References to other snippets inside snippet content are **not** rewritten — the nested ref stays canonical and the browser follows a 302 to the referenced snippet's live hash URL.
- **Releases freeze versions per environment** — a release manifest pins exact versions of every snippet; an environment attached to a release serves those versions. A snippet absent from the manifest 404s at the snippet route.

Use snippets for reusable code/data referenced from multiple pages (`<link>`, `<script src>`, `fetch()`). For binary files (images, fonts, video, PDFs), use assets.

## Environments & Releases

Every website is served on environments. The **default environment** ("live") backs the platform subdomain; additional dev/staging environments get generated `*.env.pageweave.site` hosts (noindex, no analytics) with optional live-reload. Draft table rows render on dev environments on template pages only — `{% for %}` loops are published-only everywhere.

**Releases** snapshot the latest versions of every page, component, snippet, and the theme into an immutable manifest. Attaching a release to an environment freezes that surface to the manifest (pages absent from the manifest 404; snippets absent from the manifest 404 at the snippet route; the theme falls back to the built-in default). Every release has a `*.r.pageweave.site` permalink, kept while the release is retained (unattached releases past 50 are pruned). Rollback = attach an older release.

## Assets

Binary file uploads with automatic optimization:

- **Images** — WebP + AVIF variants generated
- **Fonts** — WOFF2, TTF, OTF supported
- **Documents** — PDF, DOCX, XLSX, PPTX
- **Size limits** — 5MB images, 2.5MB fonts, 15MB video/audio, 10MB other
- **Batch uploads** — one plain upload URL (`request_upload_url`) is reusable for 10 minutes; each PUT creates a new asset — pass a different `?filename=` per PUT to upload a whole batch
- **Replace is permanent** — passing `asset_id` to an upload tool replaces the bytes in place; old bytes are purged immediately (no undo, no version history). A replacement upload URL always overwrites that one asset on every PUT

### Image Rendering

Images are automatically enhanced at render time:

- **WebP/AVIF** — modern formats generated for raster images
- **Responsive srcset** — multiple sizes generated
- **Original** — original file always available
- **Text assets** — CSS, JS, JSON, HTML, SVG should use snippets, not assets

## Analytics

Privacy-first, server-side only analytics:

- **No cookies** — no tracking cookies, no GDPR banners needed
- **No JS trackers** — no fingerprinting, no client-side scripts
- **Raw data retention** — 90 days
- **Daily/hourly metrics** — page views, referrers, countries, cities, bots, AI agents
- **Live visitors** — real-time count

## Forms

Versioned forms with email notifications:

- **Fields** — text, email, textarea, select, checkbox, radio, number, etc.
- **Notifications** — email to site owner; requires email verification
- **Spam protection** — ALTCHA proof-of-work with tiers: standard (default), code, strict (adds an accessible image/audio code challenge)
- **Spam shield** — automatic: sustained abuse raises a form's protection (site-wide if several forms are hit) and decays back after; owners get notified
- **Spam scoring** — content checks route suspicious submissions to a reviewable spam folder; release or mark as spam per submission (see [Security](/docs/en/security))
- **Versioned** — each version has a unique `submit_url`; old versions keep working
- **Submissions** — stored as JSONB, exported via the admin

## Hostnames & Domains

Hostnames attach names (e.g. `example.com`) to a website; domains are DNS zones managed by PageWeave or purchased through us:

- **Hostnames** — serve (Pro) or redirect to the platform subdomain (Free); apex auto-creates a www companion
- **Domains** — DNS-managed zones; `manage_domain_dns` sets up zone + records + hostname in one call
- **Domain purchase** — check availability, buy via Stripe checkout
- **DNS records** — A, AAAA, ALIAS, CNAME, MX, TXT, NS, SRV in managed zones

Deleting a website is blocked while any hostname is attached, and releasing a hostname is blocked while its DNS still resolves to PageWeave — hostname rows hold DNS claims (subdomain-takeover protection). Remove DNS records and wait out the TTL before releasing.

## Security

Platform-level protections:

- **Markdown sanitization** — raw HTML in markdown source is neutralized
- **SSRF protection** — server-side fetches guarded
- **Rate limiting** — Rack::Attack on platform routes and form endpoints
- **Spam shield** — adaptive proof-of-work tiers on forms, auto-escalating under attack
- **Email verification** — form notifications require verified email

See [Security](/docs/security).

## Privacy & Data

- **Hosting** — Hetzner, Germany (EU)
- **Data controller** — the site owner; PageWeave is processor
- **Google Fonts** — proxied through PageWeave
- **CDN libraries** — proxied via `libs.pageweave.dev` (no visitor IP/referrer to third-party CDNs)
- **Cloudflare** — DNS only, no proxy

See [Privacy](/docs/privacy).
