---
title: "Website checklist: all 237 rules · Agent Wranglers"
url: https://agentwranglers.se/playbook/website/checklist
updated: 2026-10-20
licence: "All rights reserved"
---

# Website checklist

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

Every rule in the website playbook, by chapter, required rules first. Each links to its own page with how we built it and how to check it.

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers website playbook: https://agentwranglers.se/playbook/website/checklist`.

## HTML basics

- [ ] **Required** [Start every page with the doctype](https://agentwranglers.se/playbook/website/html-basics/doctype): Start every HTML page with `<!doctype html>` as its very first bytes, so browsers use standards mode (the modern, predictable way of laying out pages).
- [ ] **Required** [Say the page's language](https://agentwranglers.se/playbook/website/html-basics/html-lang): Set the page's language on the `<html>` element of every page, such as `lang="en"`, using a standard language code (BCP 47).
- [ ] **Required** [Declare UTF-8 first](https://agentwranglers.se/playbook/website/html-basics/meta-charset): Make `<meta charset="utf-8">` the first element in `<head>`, so it falls inside the first 1024 bytes as the HTML standard requires. Send the same character set in the `Content-Type` header.
- [ ] **Required** [Fit the page to the phone](https://agentwranglers.se/playbook/website/html-basics/meta-viewport): Add `<meta name="viewport" content="width=device-width, initial-scale=1">` to every page, and never turn off zooming.
- [ ] **Required** [Give every page its own title](https://agentwranglers.se/playbook/website/html-basics/title): Give every page exactly one unique, non-empty `<title>`, sent by the server. Put the page's name first and the site name last, in 60 characters at most.
- [ ] **Recommended** [Keep the HTML valid](https://agentwranglers.se/playbook/website/html-basics/valid-html): Make every built page pass an HTML validator with zero errors, so every browser, crawler and screen reader reads the same structure.
- [ ] **Recommended** [Write a summary for search results](https://agentwranglers.se/playbook/website/html-basics/meta-description): Write a unique description of 120 to 160 characters for every public page by hand. Tell a searcher what the page offers.
- [ ] **Recommended** [Ship a full set of icons](https://agentwranglers.se/playbook/website/html-basics/favicons): Ship an SVG favicon, a `/favicon.ico` fallback, a 180 px opaque `apple-touch-icon`, and 192, 512 and maskable icons for installed web apps.
- [ ] **Recommended** [Support light and dark from the start](https://agentwranglers.se/playbook/website/html-basics/color-scheme): Say which colour schemes the page supports, with `<meta name="color-scheme">` and the CSS `color-scheme` property. Design dark mode on purpose.
- [ ] **Recommended** [Control how shared links look](https://agentwranglers.se/playbook/website/html-basics/open-graph): Give every page Open Graph tags (type, title, description, url, and an image with width, height and alt). Shared links then show the page's title, description and image.
- [ ] **Recommended** [Point readers to your feed](https://agentwranglers.se/playbook/website/html-basics/feed-discovery): Announce every feed in each page's `<head>` with `<link rel="alternate">` and the right type, so readers and agents can find it.
- [ ] **Recommended** [Keep your feed clean and valid](https://agentwranglers.se/playbook/website/html-basics/feed-hygiene): Publish valid feeds with a self link and the full text. Give each entry a stable id and an honest updated date.
- [ ] **Optional** [Colour the browser bar to match](https://agentwranglers.se/playbook/website/html-basics/theme-color): Set `<meta name="theme-color">` twice, once for light and once for dark, so the browser's own bar matches the page. Also give `body` an explicit background colour.
- [ ] **Optional** [Push feed updates to subscribers](https://agentwranglers.se/playbook/website/html-basics/websub): If you publish a feed, name a WebSub hub in it and in a `Link` header. Tell the hub whenever the content changes.
- [ ] **Optional** [Say in DNS if a domain is for sale](https://agentwranglers.se/playbook/website/html-basics/for-sale-dns): Only if a domain is for sale, say so with a TXT record at `_for-sale`, as RFC 10023 describes. Otherwise publish nothing.

## Site architecture

- [ ] **Required** [Build on HTML that already works](https://agentwranglers.se/playbook/website/site-architecture/progressive-enhancement): Ship working HTML first. Let JavaScript add behaviour to what is already there.
- [ ] **Required** [Keep the previous build's assets](https://agentwranglers.se/playbook/website/site-architecture/keep-the-previous-build-s-assets): After a deploy, keep the hashed files of the last three deploys and of the last 7 days, whichever keeps more. Pages cached before the deploy still find their scripts.
- [ ] **Required** [Audit every page in a browser before release](https://agentwranglers.se/playbook/website/site-architecture/browser-audits-before-release): Run an accessibility checker and a lab tool such as Lighthouse in a browser. Test light and dark mode, at phone and desktop width, and watch the console for policy errors.
- [ ] **Recommended** [Keep pages as data](https://agentwranglers.se/playbook/website/site-architecture/pages-as-data): Write each page as plain values (path, title, description, date, HTML, Markdown), not as a template full of logic.
- [ ] **Recommended** [Write each page once for every format](https://agentwranglers.se/playbook/website/site-architecture/one-source-many-formats): Build every format (HTML, Markdown, JSON-LD, sitemap, feeds, llms.txt) from the same page data, so they cannot drift apart.
- [ ] **Recommended** [Render at build time and serve from memory](https://agentwranglers.se/playbook/website/site-architecture/render-at-build-time-serve-from-memory): Do all templating at build time. Render each page once, compress it once, and keep the bytes, ETag and security policy in memory.
- [ ] **Recommended** [Load one of each from your own site](https://agentwranglers.se/playbook/website/site-architecture/one-of-each-all-first-party): One HTML request, one inline stylesheet, one script bundle, one image per screen size, self-hosted fonts, and no third-party origins.
- [ ] **Recommended** [Build repeated HTML from shared modules](https://agentwranglers.se/playbook/website/site-architecture/shared-html-modules-only): Build every repeated piece of HTML from one shared module, such as tables, code blocks, cards, breadcrumbs and calls to action. Make the build reject hand-written copies of the ones that break most easily.
- [ ] **Recommended** [Give every module its own class names](https://agentwranglers.se/playbook/website/site-architecture/module-class-names): Give each module its own class names, so one module's styles can never reach into another.

## Interface

- [ ] **Recommended** [Build menus with popover](https://agentwranglers.se/playbook/website/interface/popover-api): Build menus, tooltips and simple overlays with the built-in `popover` attribute, instead of JavaScript modal code.
- [ ] **Recommended** [Build modal dialogs with dialog](https://agentwranglers.se/playbook/website/interface/dialog-element): Build modal dialogs with the `<dialog>` element and `showModal()`, never with a styled `div` and your own focus code.
- [ ] **Recommended** [Pin menus to their button with CSS](https://agentwranglers.se/playbook/website/interface/anchor-positioning): Attach popovers and menus to the element they belong to with CSS anchor positioning. Keep a plain fallback where browsers lack it.
- [ ] **Recommended** [Let parts fit the space they get](https://agentwranglers.se/playbook/website/interface/container-queries): Let components adapt to the space they are given with container queries, not only to the width of the screen.
- [ ] **Recommended** [Let the browser balance line breaks](https://agentwranglers.se/playbook/website/interface/text-wrap): Use `text-wrap: balance` on headings and `text-wrap: pretty` on paragraphs, instead of manual line breaks.
- [ ] **Recommended** [Keep room for the scrollbar](https://agentwranglers.se/playbook/website/interface/scrollbar-gutter): Keep space for the scrollbar with `scrollbar-gutter: stable`, so the page doesn't shift when scrolling is locked or unlocked.
- [ ] **Recommended** [Size full-height panels for phones](https://agentwranglers.se/playbook/website/interface/dynamic-viewport-units): Size full-height phone layouts with `dvh`, `svh` or `lvh` instead of `vh`, so they fit when the address bar moves.
- [ ] **Optional** [Wire buttons without click handlers](https://agentwranglers.se/playbook/website/interface/invoker-commands): Connect buttons to popovers and dialogs in HTML with `commandfor` and `command`. Keep a fallback for older browsers.
- [ ] **Optional** [Define every colour once](https://agentwranglers.se/playbook/website/interface/colour-as-tokens): Define every colour once as a `light-dark()` custom property, and switch themes with `color-scheme`, never with duplicate rules.
- [ ] **Optional** [Animate on scroll with CSS](https://agentwranglers.se/playbook/website/interface/scroll-driven-animations): Drive scroll effects with CSS `animation-timeline` instead of scroll event listeners in JavaScript.
- [ ] **Optional** [Skip page fades unless they help](https://agentwranglers.se/playbook/website/interface/view-transitions): Use View Transitions only where the animation helps people follow a change, and check that it doesn't slow down clicks.

## Performance

- [ ] **Required** [Keep load, response and stability fast](https://agentwranglers.se/playbook/website/performance/core-web-vitals): Keep the three Core Web Vitals in the good range for at least 75% of visits. LCP (main content shown) stays under 2.5 s, INP (reaction to a tap) under 200 ms and CLS (layout jumps) under 0.1.
- [ ] **Required** [Send small, modern images](https://agentwranglers.se/playbook/website/performance/image-optimization): Send AVIF or WebP images, each one sized for the screen it lands on with `srcset` and `sizes`, and always give `width` and `height`.
- [ ] **Required** [Cache files for a year and pages briefly](https://agentwranglers.se/playbook/website/performance/cache-control): Cache files with a content hash in their name for a year as `immutable`. Give HTML a `max-age` of at most 600 seconds, or `no-cache`.
- [ ] **Required** [Compress every text response](https://agentwranglers.se/playbook/website/performance/compression): Compress every text response with Brotli (or zstd), with gzip as a fallback, ideally ahead of time at the highest level.
- [ ] **Required** [Fail the build when pages get heavier](https://agentwranglers.se/playbook/website/performance/performance-budget): Set a budget for page weight, request count and lab metrics, and make the build fail when a change goes over it.
- [ ] **Recommended** [Measure speed in visitors' browsers](https://agentwranglers.se/playbook/website/performance/field-measurement): Collect LCP, INP and CLS from visitors' browsers on every page type, and report the 75th percentile for phones and desktops apart.
- [ ] **Recommended** [Load far-down images later](https://agentwranglers.se/playbook/website/performance/lazy-loading): Lazy-load images and iframes below the fold (load them only when someone scrolls near), and never the main image at the top.
- [ ] **Recommended** [Hint only what speeds up the first paint](https://agentwranglers.se/playbook/website/performance/preload-prefetch-preconnect): Preload only what the first paint needs, prefetch likely next pages, and preconnect only to other origins you are certain to use.
- [ ] **Recommended** [Say which request headers change a response](https://agentwranglers.se/playbook/website/performance/vary): Send `Vary` with every request header that changes a response, such as `Accept-Encoding` and `Accept`.
- [ ] **Recommended** [Answer repeat requests with 304](https://agentwranglers.se/playbook/website/performance/conditional-requests): Send an `ETag` or `Last-Modified` on responses, and answer matching requests with 304 Not Modified.
- [ ] **Recommended** [Ignore tracking parameters in caches](https://agentwranglers.se/playbook/website/performance/no-vary-search): Tell caches to ignore tracking parameters with `No-Vary-Search`, so one page isn't stored many times.
- [ ] **Recommended** [Load fonts without moving the page](https://agentwranglers.se/playbook/website/performance/font-loading): Self-host fonts as WOFF2, subset them, and add fallback fonts adjusted to the same size. Never let a late font move the page. Use `font-display: optional` on long text, and `swap` only where you measured no shift.
- [ ] **Recommended** [Put the styles in the page](https://agentwranglers.se/playbook/website/performance/critical-css): Put nothing in the head that blocks the first paint. Inline the key CSS and load the rest without blocking.
- [ ] **Recommended** [Never let a script block the page](https://agentwranglers.se/playbook/website/performance/script-loading): Load scripts as `type="module"` or with `defer`, keep blocking scripts out of the head, and send as little JavaScript as possible.
- [ ] **Recommended** [Break up long tasks](https://agentwranglers.se/playbook/website/performance/long-tasks): Never run JavaScript for more than 50 ms at a time. Split long work into chunks, and let the browser handle input between them.
- [ ] **Recommended** [Fetch the next page on hover](https://agentwranglers.se/playbook/website/performance/speculation-rules): Fetch or fully load likely next pages ahead of time with Speculation Rules, but skip addresses that change something.
- [ ] **Recommended** [Keep the back button instant](https://agentwranglers.se/playbook/website/performance/bfcache): Keep every page able to use the back/forward cache, which shows a page instantly on Back. Use no `unload` handlers, and no `Cache-Control: no-store` on ordinary pages.
- [ ] **Optional** [Send early hints only when they help](https://agentwranglers.se/playbook/website/performance/early-hints): Send 103 Early Hints (a note sent before the answer) only for critical, safe files. Check that first paint gets faster.
- [ ] **Optional** [Skip work for what is off screen](https://agentwranglers.se/playbook/website/performance/visibility-aware-rendering): Skip drawing content that is off screen with `content-visibility: auto`, and start heavy widgets only when they come into view.
- [ ] **Optional** [Fence off self-contained parts](https://agentwranglers.se/playbook/website/performance/css-containment): Use `contain` on self-contained parts of the page, so the browser can limit layout and paint work.
- [ ] **Optional** [Use shared dictionaries for big bundles](https://agentwranglers.se/playbook/website/performance/compression-dictionary-transport): Use shared compression dictionaries only for bundles over 100 KB compressed that change at least monthly. Skip them otherwise.
- [ ] **Optional** [Report how long the server took](https://agentwranglers.se/playbook/website/performance/server-timing): Report how long the server took in a `Server-Timing` header, without internal names.
- [ ] **Avoid** [Drop old HTTP/1 tricks](https://agentwranglers.se/playbook/website/performance/http1-workarounds): Don't use old HTTP/1 tricks such as extra asset domains, image sprites or merging everything into one file. With HTTP/2 they do harm.

## SEO

- [ ] **Required** [Serve phones the same content](https://agentwranglers.se/playbook/website/seo/mobile-first-indexing): Give phone visitors the same content, links, metadata and structured data as desktop visitors. Google indexes the phone version of every page.
- [ ] **Required** [Keep private pages out of search](https://agentwranglers.se/playbook/website/seo/meta-robots): Leave public pages open to search engines. Mark error, private, utility and internal search-result responses `noindex`, with a meta tag or `X-Robots-Tag` header.
- [ ] **Required** [Use one h1 and keep headings in order](https://agentwranglers.se/playbook/website/seo/heading-hierarchy): Give every page exactly one `h1`, and a heading outline that never skips a level. Never use headings just for their look.
- [ ] **Recommended** [Tell crawlers where they may go](https://agentwranglers.se/playbook/website/seo/robots-txt): Serve a plain-text `/robots.txt` at the root of every host. It allows public content, blocks only private paths and names the sitemap.
- [ ] **Recommended** [List every public page in a sitemap](https://agentwranglers.se/playbook/website/seo/xml-sitemaps): Publish an XML sitemap, a list of your pages for search engines. List only canonical public URLs that answer 200, each with an honest last-changed date.
- [ ] **Recommended** [Keep addresses short and readable](https://agentwranglers.se/playbook/website/seo/url-structure): Keep addresses lowercase, hyphenated, descriptive and shallow. Leave out file endings and session parameters, and treat addresses as permanent.
- [ ] **Recommended** [Send the content in the HTML](https://agentwranglers.se/playbook/website/seo/server-side-rendering): Put each page's content, metadata, links and structured data in the HTML the server sends. Don't leave them to JavaScript to build later.
- [ ] **Recommended** [Link every page from another](https://agentwranglers.se/playbook/website/seo/internal-linking): Link every page from others with `<a href>` links and text that says where they go, so no page is left orphaned.
- [ ] **Recommended** [Give paginated lists their own addresses](https://agentwranglers.se/playbook/website/seo/pagination): Give every page of a long list its own URL, linked with plain `<a href>` links. Each page carries a canonical to itself, never to page one.
- [ ] **Recommended** [Keep filter combinations out of the crawl](https://agentwranglers.se/playbook/website/seo/faceted-navigation): Stop crawlers from following every combination of filters and sorting. Let them crawl only the filtered pages you want found.
- [ ] **Recommended** [Describe each page for machines](https://agentwranglers.se/playbook/website/seo/structured-data): Describe each page with schema.org JSON-LD, a block of data search engines read. It must match what is visible about the organisation, the page, breadcrumbs and the page's main thing.
- [ ] **Recommended** [Show where the page sits](https://agentwranglers.se/playbook/website/seo/breadcrumbs): Show a breadcrumb trail on inner pages, with the current page not linked. Mark it up as a matching `BreadcrumbList`.
- [ ] **Recommended** [Watch how search engines see the site](https://agentwranglers.se/playbook/website/seo/search-console): Verify the site in Google Search Console and Bing Webmaster Tools, submit the sitemap, and read the indexing reports after every large change.
- [ ] **Recommended** [Mark links you do not vouch for](https://agentwranglers.se/playbook/website/seo/user-link-attributes): Mark links in user content with `rel="ugc"`, paid links with `rel="sponsored"`, and other links you don't vouch for with `rel="nofollow"`.
- [ ] **Optional** [Split sitemaps only when huge](https://agentwranglers.se/playbook/website/seo/sitemap-index): Split the sitemap only when one file would pass 50,000 URLs or 50 MB uncompressed. List the parts in a sitemap index. Below those limits, keep one file.
- [ ] **Optional** [List key images in the sitemap](https://agentwranglers.se/playbook/website/seo/image-sitemaps): List important images in the sitemap with the image extension. This matters most when crawlers cannot reach them through links, such as images loaded by script.
- [ ] **Optional** [Tell search engines what changed](https://agentwranglers.se/playbook/website/seo/indexnow): Tell search engines that support IndexNow, such as Bing, Yandex and Seznam, about new and changed pages. Prove the site is yours with a key file served from it.

## Redirects and canonicals

- [ ] **Required** [Keep every old address in one redirect map](https://agentwranglers.se/playbook/website/redirects-and-canonicals/redirect-map): Keep every address you have ever published in one redirect map, and check it before any other route. Never delete an entry.
- [ ] **Required** [Send each old page to its closest new page](https://agentwranglers.se/playbook/website/redirects-and-canonicals/closest-match): Redirect each old address to the new page that best replaces it. Never send many old pages to the home page.
- [ ] **Required** [Link only to final addresses](https://agentwranglers.se/playbook/website/redirects-and-canonicals/final-addresses): Link only to addresses that answer 200. Never link to a redirect from your own pages, sitemap, feeds or canonical tags.
- [ ] **Required** [Use the right redirect code](https://agentwranglers.se/playbook/website/redirects-and-canonicals/redirect-codes): Use a server-side permanent redirect (301 or 308) for anything that moved for good. Use 302 or 307 only for short-term moves, and 303 only to show a result page after a form post.
- [ ] **Required** [Make every canonical signal agree](https://agentwranglers.se/playbook/website/redirects-and-canonicals/canonical-signals): Give each page one canonical address, and make the canonical tag, sitemap, Open Graph address, hreflang links and internal links all use exactly that address.
- [ ] **Recommended** [Answer 404 or 410 when a page is gone for good](https://agentwranglers.se/playbook/website/redirects-and-canonicals/gone-pages): Answer unknown addresses and content removed with no replacement with 404 or 410 and a helpful page. Never show "not found" with a 200, and never send unknown pages to the home page.
- [ ] **Recommended** [Move a site or domain without losing links](https://agentwranglers.se/playbook/website/redirects-and-canonicals/site-moves): When a whole site or domain moves, redirect every old address one to one. Keep the redirects as long as possible, and at least a year.
- [ ] **Recommended** [Watch for broken old links](https://agentwranglers.se/playbook/website/redirects-and-canonicals/watch-not-found): Every week, list the missing addresses people still request, and add a redirect for each one with a replacement.
- [ ] **Optional** [Say who made each redirect](https://agentwranglers.se/playbook/website/redirects-and-canonicals/redirect-by): Name the system that made each redirect in a `Redirect-By` header, so you can trace redirects.
- [ ] **Avoid** [Avoid meta refresh and JavaScript redirects](https://agentwranglers.se/playbook/website/redirects-and-canonicals/client-side-redirects): Don't redirect with `<meta http-equiv="refresh">` or JavaScript. Do it on the server.

## Accessibility

- [ ] **Required** [Make text easy to read](https://agentwranglers.se/playbook/website/accessibility/color-contrast): Give text at least 4.5:1 contrast against its background, and large text at least 3:1. Give control borders, focus rings and meaningful icons at least 3:1. Meet this in light and dark mode.
- [ ] **Required** [Describe images in words](https://agentwranglers.se/playbook/website/accessibility/image-alt-text): Give every `<img>` an `alt` attribute. Say what it shows if it carries meaning, or leave it empty if it is decoration. This is WCAG criterion 1.1.1 (A).
- [ ] **Required** [Label every form field](https://agentwranglers.se/playbook/website/accessibility/form-labels): Give every form field a visible label tied to it with `<label for>`. A placeholder is not a label. These are WCAG criteria 1.3.1, 3.3.2 and 4.1.2 (A).
- [ ] **Required** [Put the visible words in the name](https://agentwranglers.se/playbook/website/accessibility/label-in-name): When a control shows text, its accessible name must contain that text, ideally at the start. This is WCAG criterion 2.5.3 (A).
- [ ] **Required** [Make everything work by keyboard](https://agentwranglers.se/playbook/website/accessibility/keyboard-navigation): Every link, button and control must work with just a keyboard. Tab moves in reading order, and focus never gets stuck. These are WCAG criteria 2.1.1, 2.1.2 and 2.4.3 (A).
- [ ] **Required** [Never take over single keys](https://agentwranglers.se/playbook/website/accessibility/character-key-shortcuts): Never use a shortcut that is a single letter, number or symbol key unless people can turn it off or remap it. This is WCAG criterion 2.1.4 (A).
- [ ] **Required** [Always show where focus is](https://agentwranglers.se/playbook/website/accessibility/focus-indicators): Show a clear focus ring on every control when someone reaches it with the keyboard. This is WCAG criterion 2.4.7 (AA).
- [ ] **Required** [Never hide the focused element](https://agentwranglers.se/playbook/website/accessibility/focus-not-obscured): Never let a sticky header, cookie banner or chat widget cover the element that has keyboard focus. WCAG 2.2 criterion 2.4.11 (AA) forbids hiding it entirely. Aim to hide no part of it, as 2.4.12 (AAA) asks.
- [ ] **Required** [Let people skip to the content](https://agentwranglers.se/playbook/website/accessibility/skip-links): Make a "Skip to main content" link the first thing that takes focus on every page. It meets WCAG criterion 2.4.1 (A) together with landmarks.
- [ ] **Required** [Use the right element for the job](https://agentwranglers.se/playbook/website/accessibility/semantic-html): Use landmark elements (`header`, `nav`, `main`, `footer`) and the right element for each job, with one `main` per page. This is WCAG criterion 1.3.1 (A).
- [ ] **Required** [Say where each link goes](https://agentwranglers.se/playbook/website/accessibility/link-text): Write link text that says where the link goes. Never write "click here" or "read more". This meets WCAG criterion 2.4.4 (A).
- [ ] **Required** [Never use colour as the only signal](https://agentwranglers.se/playbook/website/accessibility/not-color-alone): Never show meaning by colour alone, such as red for an error or a coloured line in a chart. Add text, an icon, a pattern or an underline. This is WCAG criterion 1.4.1 (A).
- [ ] **Required** [Name every link and button](https://agentwranglers.se/playbook/website/accessibility/empty-links-buttons): Never ship a link or button without a name a screen reader can read. Give icon-only controls an `aria-label`. This is WCAG criterion 4.1.2 (A).
- [ ] **Required** [Explain form errors next to the field](https://agentwranglers.se/playbook/website/accessibility/form-errors): Show form errors as text next to the field, tie them to it with `aria-describedby`, and say how to fix them. These are WCAG criteria 3.3.1 (A) and 3.3.3 (AA).
- [ ] **Required** [Let people check before they commit](https://agentwranglers.se/playbook/website/accessibility/error-prevention): Before a purchase, a legal commitment, or a change or deletion of stored data, let people review and fix, confirm, or undo. This is WCAG criterion 3.3.4 (AA).
- [ ] **Required** [Announce changes without moving focus](https://agentwranglers.se/playbook/website/accessibility/status-messages): Announce changes such as "Copied" or "3 results" through a live region that is already in the page, without moving focus. This is WCAG criterion 4.1.3 (AA).
- [ ] **Required** [Make signing in easy for everyone](https://agentwranglers.se/playbook/website/accessibility/accessible-authentication): Never make any sign-in step depend only on remembering, transcribing or solving a puzzle. Allow paste and password managers. This is WCAG 2.2 criterion 3.3.8 (AA).
- [ ] **Required** [Never ask for the same thing twice](https://agentwranglers.se/playbook/website/accessibility/redundant-entry): Never ask people for the same information twice in one process. Fill it in for them or let them pick it. This is WCAG 2.2 criterion 3.3.7 (A).
- [ ] **Required** [Keep help in the same place](https://agentwranglers.se/playbook/website/accessibility/consistent-help): Put help and contact links in the same order relative to the rest of the page on every page. This is WCAG 2.2 criterion 3.2.6 (A).
- [ ] **Required** [Keep navigation in the same order](https://agentwranglers.se/playbook/website/accessibility/consistent-navigation): Show repeated navigation in the same order on every page, and give the same function the same name everywhere. These are WCAG criteria 3.2.3 and 3.2.4 (AA).
- [ ] **Required** [Offer two ways to every page](https://agentwranglers.se/playbook/website/accessibility/multiple-ways): Give people at least two ways to reach each page, such as navigation plus site search or a page listing every page. This is WCAG criterion 2.4.5 (AA).
- [ ] **Required** [Change nothing on focus or input alone](https://agentwranglers.se/playbook/website/accessibility/no-surprise-changes): Never open a new page, submit a form or move focus just because a field got focus or its value changed. These are WCAG criteria 3.2.1 and 3.2.2 (A).
- [ ] **Required** [Show hover content that people can reach](https://agentwranglers.se/playbook/website/accessibility/content-on-hover-focus): Content that appears on hover or focus must be dismissible with Escape, hoverable without vanishing, and stay until people move away. This is WCAG criterion 1.4.13 (AA).
- [ ] **Required** [Work in both orientations](https://agentwranglers.se/playbook/website/accessibility/orientation): Never lock the page to portrait or landscape. This is WCAG criterion 1.3.4 (AA).
- [ ] **Required** [Never use flashing content](https://agentwranglers.se/playbook/website/accessibility/no-flashing): Never show anything that flashes more than three times in one second. This is WCAG criterion 2.3.1 (A).
- [ ] **Required** [Respect people who turn motion off](https://agentwranglers.se/playbook/website/accessibility/reduced-motion): Honour `prefers-reduced-motion` and stop or reduce animation, parallax and smooth scrolling. Never start motion by itself.
- [ ] **Required** [Give people enough time](https://agentwranglers.se/playbook/website/accessibility/time-limits): Let people turn off, lengthen or extend every time limit. Let them pause anything that moves or updates by itself for more than five seconds. These are WCAG criteria 2.2.1 and 2.2.2 (A).
- [ ] **Required** [Caption video, transcribe audio](https://agentwranglers.se/playbook/website/accessibility/captions-and-transcripts): Caption every video, describe what it shows that is not said, and give a transcript for audio. These are WCAG criteria 1.2.1, 1.2.2 (A), 1.2.4 and 1.2.5 (AA).
- [ ] **Required** [Give tables headers](https://agentwranglers.se/playbook/website/accessibility/data-tables): Mark up data tables with `th`, `scope` and a caption or label. Use tables only for data, never for layout. This is WCAG criterion 1.3.1 (A).
- [ ] **Required** [Never make people scroll sideways](https://agentwranglers.se/playbook/website/accessibility/no-sideways-scrolling): Never let a page or a component scroll sideways with a visible scrollbar, at any width from 320 CSS px up. This meets WCAG criterion 1.4.10 (AA).
- [ ] **Required** [Let text grow without breaking the page](https://agentwranglers.se/playbook/website/accessibility/text-resize): Keep all content readable at 200% text zoom and with wider letter, word and line spacing. Never block pinch zoom. These are WCAG criteria 1.4.4 and 1.4.12 (AA).
- [ ] **Required** [Make tap targets big enough](https://agentwranglers.se/playbook/website/accessibility/touch-target-size): Make every pointer target at least 24 by 24 CSS pixels, as WCAG 2.2 criterion 2.5.8 (AA) asks. Make icon-only buttons 44 by 44, as 2.5.5 (AAA) asks.
- [ ] **Required** [Offer a way that needs no dragging](https://agentwranglers.se/playbook/website/accessibility/dragging-movements): Give every drag a single-pointer alternative, such as buttons. This is WCAG 2.2 criterion 2.5.7 (AA).
- [ ] **Required** [Make every gesture work with one tap](https://agentwranglers.se/playbook/website/accessibility/pointer-gestures): Make every action that needs a multi-finger or path gesture also work with single taps. Act on release, not on press. These are WCAG criteria 2.5.1 and 2.5.2 (A).
- [ ] **Required** [Show the right keyboard on phones](https://agentwranglers.se/playbook/website/accessibility/mobile-form-inputs): Give every field that asks about the person the right `autocomplete` token, as WCAG criterion 1.3.5 (AA) asks. Give inputs the right `type` and `inputmode` too.
- [ ] **Recommended** [Work in high-contrast mode](https://agentwranglers.se/playbook/website/accessibility/forced-colors): Test the site in forced-colours mode, a high-contrast setting in Windows. Repair what it flattens under `forced-colors: active`.
- [ ] **Recommended** [Lock the page behind open menus](https://agentwranglers.se/playbook/website/accessibility/inert-attribute): Make everything behind an open menu or dialog unreachable with the `inert` attribute.
- [ ] **Recommended** [Reach for HTML before ARIA](https://agentwranglers.se/playbook/website/accessibility/aria-usage): Use native HTML elements first. Add ARIA, extra attributes for screen readers, only for what no native element can say.
- [ ] **Recommended** [Make links look like links](https://agentwranglers.se/playbook/website/accessibility/links-look-like-links): Underline every text link in content with one subtle, consistent style. Leave it off only in navigation bars and on links styled as buttons, where the shape already says "link".
- [ ] **Recommended** [Know which accessibility law applies](https://agentwranglers.se/playbook/website/accessibility/accessibility-law): Find out which accessibility laws cover the site. Meet WCAG 2.2 AA, which includes the WCAG 2.1 AA level most laws point to.
- [ ] **Recommended** [Let find-in-page open hidden text](https://agentwranglers.se/playbook/website/accessibility/hidden-until-found): Hide folded content in a way find-in-page can still reach, such as `<details>` or `hidden="until-found"`.
- [ ] **Recommended** [Build with native controls](https://agentwranglers.se/playbook/website/accessibility/native-interactive-elements): Build controls from native elements (`button`, `a`, `details`, `dialog`, `popover`) instead of scripted `div`s.
- [ ] **Recommended** [Style from the state](https://agentwranglers.se/playbook/website/accessibility/css-state-selectors): Style interface state from the state itself with selectors like `:has()`, `:popover-open` and `[aria-expanded]`, not from toggled classes.
- [ ] **Optional** [Let the browser pick readable text colour](https://agentwranglers.se/playbook/website/accessibility/contrast-color): Let the browser pick readable black or white text on brand colours with `contrast-color()`, after a fallback you have checked.
- [ ] **Avoid** [Fix the site instead of adding overlays](https://agentwranglers.se/playbook/website/accessibility/accessibility-overlays): Never install an accessibility overlay widget. Fix the site itself.

## Security

- [ ] **Required** [Make browsers always use HTTPS](https://agentwranglers.se/playbook/website/security/hsts): Send `Strict-Transport-Security` so browsers always use HTTPS. Give it a long `max-age` (at least a year) and `includeSubDomains`, on HTTPS responses only.
- [ ] **Required** [Allow only the scripts you wrote](https://agentwranglers.se/playbook/website/security/content-security-policy): Send a strict Content Security Policy, a header that says which scripts may run. Allow scripts only by nonce or hash, with `'strict-dynamic'`, `object-src 'none'`, `base-uri 'none'` and no `unsafe-inline`.
- [ ] **Required** [Stop browsers guessing file types](https://agentwranglers.se/playbook/website/security/x-content-type-options): Send `X-Content-Type-Options: nosniff` on every response, so browsers don't guess file types. Give every response its correct Content-Type.
- [ ] **Required** [Refuse to be framed](https://agentwranglers.se/playbook/website/security/frame-ancestors): Stop other sites from showing yours inside a frame. Use `frame-ancestors 'none'` (or a list) in the CSP, plus `X-Frame-Options` for older browsers.
- [ ] **Required** [Set cookies safely or not at all](https://agentwranglers.se/playbook/website/security/cookie-attributes): Set every cookie with `Secure` and an explicit `SameSite`. Add `HttpOnly` to every cookie that no script reads. Use `SameSite=None` only for a cookie that must work inside another site.
- [ ] **Required** [Limit how often anyone can call your APIs](https://agentwranglers.se/playbook/website/security/rate-limits): Put a rate limit on every endpoint that does work for each request, such as APIs, agent endpoints, forms and report collectors.
- [ ] **Recommended** [Load nothing over plain HTTP](https://agentwranglers.se/playbook/website/security/mixed-content): Load every file over HTTPS. Add `upgrade-insecure-requests` as a safety net.
- [ ] **Recommended** [Collect reports of blocked content](https://agentwranglers.se/playbook/website/security/reporting-endpoints): Name a place for browsers to send policy errors with `Reporting-Endpoints`. Log those reports without any personal data.
- [ ] **Recommended** [Tell people how to report a hole](https://agentwranglers.se/playbook/website/security/security-txt): Publish `/.well-known/security.txt` with a contact and an `Expires` date in the future. It tells people where to report security problems.
- [ ] **Recommended** [Refuse odd requests from other sites](https://agentwranglers.se/playbook/website/security/fetch-metadata): Browsers send `Sec-Fetch-*` headers that say where a request came from. Use them to refuse cross-site requests that are not normal page visits.
- [ ] **Recommended** [Keep other sites' windows apart](https://agentwranglers.se/playbook/website/security/cross-origin-isolation): Send `Cross-Origin-Opener-Policy: same-origin` and a `Cross-Origin-Resource-Policy`. These keep other sites' windows and pages away from yours. Add COEP only if you need full isolation.
- [ ] **Recommended** [Share less in the Referer header](https://agentwranglers.se/playbook/website/security/referrer-policy): Send `Referrer-Policy: strict-origin-when-cross-origin` or stricter. It limits what other sites learn about the page a visitor came from.
- [ ] **Recommended** [Switch off browser features you don't use](https://agentwranglers.se/playbook/website/security/permissions-policy): Use `Permissions-Policy` to turn off every browser feature the site does not use. Allow the rest only for your own origin.
- [ ] **Recommended** [Lock scripts to a known hash](https://agentwranglers.se/playbook/website/security/subresource-integrity): Put an `integrity` hash, a fingerprint of the file, on every script and stylesheet. Let the browser refuse any script without one.
- [ ] **Recommended** [Lock down risky DOM writes](https://agentwranglers.se/playbook/website/security/trusted-types): Require Trusted Types in the CSP, so scripts can't write raw HTML into the page. Send every remaining case through one small named policy.
- [ ] **Optional** [Send a hash of the body](https://agentwranglers.se/playbook/website/security/digest-fields): Send a `Content-Digest`, a hash of the response body, on files clients download to verify, such as Markdown copies and downloads. RFC 9530 defines it.
- [ ] **Optional** [Wipe browser data on sign-out](https://agentwranglers.se/playbook/website/security/clear-site-data): Send `Clear-Site-Data` when a person signs out. Then their data does not stay behind in the browser.
- [ ] **Avoid** [Drop the old XSS header](https://agentwranglers.se/playbook/website/security/x-xss-protection): Do not turn on `X-XSS-Protection`. The filter it controls is gone from current browsers, and in old ones it could open holes. Rely on the Content Security Policy instead.

## Hosting and network

- [ ] **Required** [Serve everything over HTTPS](https://agentwranglers.se/playbook/website/hosting-and-network/https-tls): Serve every page over HTTPS, the encrypted web, using TLS 1.2 or 1.3 and a valid certificate chain. Redirect plain HTTP to HTTPS.
- [ ] **Required** [Renew certificates automatically](https://agentwranglers.se/playbook/website/hosting-and-network/certificate-renewal): Renew every certificate automatically, and get an alert when one has under 14 days left.
- [ ] **Required** [Keep the domain name yours](https://agentwranglers.se/playbook/website/hosting-and-network/domain-renewal): Renew the domain automatically, lock it against transfers and protect the registrar account with two-factor login. A lapsed or stolen domain takes down the site and its email.
- [ ] **Recommended** [Turn off old encryption](https://agentwranglers.se/playbook/website/hosting-and-network/tls-configuration): Allow only TLS 1.2 and 1.3, with ECDHE key exchange and AEAD ciphers. Turn off TLS compression and 0-RTT for requests that change data.
- [ ] **Recommended** [Serve over HTTP/2 or HTTP/3](https://agentwranglers.se/playbook/website/hosting-and-network/http3): Serve the site over HTTP/2 at least, and over HTTP/3 where the server supports it.
- [ ] **Recommended** [Choose who may issue your certificates](https://agentwranglers.se/playbook/website/hosting-and-network/caa-records): Publish DNS CAA records. They list which certificate authorities may sign certificates for your name. All others must refuse.
- [ ] **Recommended** [Host where routes are signed](https://agentwranglers.se/playbook/website/hosting-and-network/rpki): Host the site and its DNS with providers that sign their internet routes with RPKI. They should also drop invalid routes.
- [ ] **Recommended** [Be reachable over IPv6](https://agentwranglers.se/playbook/website/hosting-and-network/ipv6): Make the site and its DNS reachable over IPv6 with AAAA records, as well as over IPv4.
- [ ] **Optional** [Send more in the first round trip](https://agentwranglers.se/playbook/website/hosting-and-network/tcp-initial-congestion-window): Let the server's first send carry the whole page. Raise the TCP initial congestion window. That is how much the server sends before waiting for a reply. Then the whole compressed HTML goes out without waiting.
- [ ] **Optional** [Sign your DNS](https://agentwranglers.se/playbook/website/hosting-and-network/dnssec): Sign the DNS zone with DNSSEC, so answers can't be forged. Then add the DS record where you bought the domain.
- [ ] **Optional** [Use TLSA records only where checked](https://agentwranglers.se/playbook/website/hosting-and-network/dane): Publish TLSA records only for services whose clients check them, such as mail servers. Browsers do not check them.

## Standard addresses

- [ ] **Recommended** [Serve standard files at fixed addresses](https://agentwranglers.se/playbook/website/standard-addresses/well-known-overview): Serve files under `/.well-known/` at their exact paths, with the right content types and no sign-in. Open them to other sites where they are meant for agents.
- [ ] **Recommended** [List your APIs in one file](https://agentwranglers.se/playbook/website/standard-addresses/api-catalog): List your public APIs and machine-readable files at `/.well-known/api-catalog`, as an RFC 9727 linkset (a JSON list of links).
- [ ] **Recommended** [Require encrypted mail delivery](https://agentwranglers.se/playbook/website/standard-addresses/mta-sts): If the domain receives email, publish an MTA-STS policy, so other mail servers deliver to it only over checked TLS.
- [ ] **Optional** [Point to the change-password page](https://agentwranglers.se/playbook/website/standard-addresses/change-password): If people have accounts, redirect `/.well-known/change-password` to the page where they change their password.
- [ ] **Optional** [List the sites that share passkeys](https://agentwranglers.se/playbook/website/standard-addresses/webauthn): If you accept passkeys across several of your domains, list the related origins in `/.well-known/webauthn`.
- [ ] **Optional** [Point to the passkey pages](https://agentwranglers.se/playbook/website/standard-addresses/passkey-endpoints): If people can sign in with passkeys, publish `/.well-known/passkey-endpoints` with the pages where they add and manage them.
- [ ] **Optional** [Publish identity provider settings](https://agentwranglers.se/playbook/website/standard-addresses/openid-configuration): If you are an OpenID identity provider, publish discovery data at `/.well-known/openid-configuration`.
- [ ] **Optional** [Publish OAuth server settings](https://agentwranglers.se/playbook/website/standard-addresses/oauth-authorization-server): If you run an OAuth authorisation server, publish its details at `/.well-known/oauth-authorization-server`.
- [ ] **Optional** [Explain how to get API access](https://agentwranglers.se/playbook/website/standard-addresses/oauth-protected-resource): If an API needs OAuth, describe how to get access at `/.well-known/oauth-protected-resource`.
- [ ] **Optional** [Say you honour privacy signals](https://agentwranglers.se/playbook/website/standard-addresses/gpc-json): If you honour Global Privacy Control, a browser signal that means "don't sell or share my data", say so in `/.well-known/gpc.json`.
- [ ] **Optional** [Answer account lookups](https://agentwranglers.se/playbook/website/standard-addresses/webfinger): If you have accounts that others look up, answer `/.well-known/webfinger` queries.
- [ ] **Optional** [Open links in your iOS app](https://agentwranglers.se/playbook/website/standard-addresses/apple-app-site-association): If you have an iOS app, publish `/.well-known/apple-app-site-association` so links open in it.
- [ ] **Optional** [Open links in your Android app](https://agentwranglers.se/playbook/website/standard-addresses/assetlinks-json): If you have an Android app, publish `/.well-known/assetlinks.json` so links open in it.
- [ ] **Optional** [Describe a federated server](https://agentwranglers.se/playbook/website/standard-addresses/nodeinfo): If you run a federated server, such as a Mastodon-style social server, publish `/.well-known/nodeinfo`.
- [ ] **Optional** [Limit prefetch proxies only if needed](https://agentwranglers.se/playbook/website/standard-addresses/traffic-advice): Publish `/.well-known/traffic-advice` only to limit private prefetch proxies, which load pages early for privacy browsers. Leaving it out welcomes them.

## Ready for AI agents

- [ ] **Recommended** [Make the site easy for AI agents](https://agentwranglers.se/playbook/website/ready-for-ai-agents/agent-readiness-overview): Make the site easy for AI agents to read and use. Put content in the HTML, and add structured data, Markdown copies, clear crawler rules and discovery files.
- [ ] **Recommended** [Give AI tools a site guide](https://agentwranglers.se/playbook/website/ready-for-ai-agents/llms-txt): Publish `/llms.txt`, a short Markdown guide to your site for AI tools. Give the site's name, a one-line summary, and links to the Markdown version of each important page.
- [ ] **Recommended** [Offer every page as Markdown](https://agentwranglers.se/playbook/website/ready-for-ai-agents/markdown-source-endpoints): Serve every page as Markdown too. Use its address plus `.md`, and answer requests with `Accept: text/markdown`. Point back to the HTML as the canonical copy.
- [ ] **Recommended** [Decide what each AI crawler may do](https://agentwranglers.se/playbook/website/ready-for-ai-agents/robots-for-ai-crawlers): Decide what each AI crawler may do. Write it in robots.txt as its own user-agent group.
- [ ] **Recommended** [Publish each page's data as a file](https://agentwranglers.se/playbook/website/ready-for-ai-agents/structured-data-for-agents): Publish each page's JSON-LD (structured facts) in the page and as its own file. Then agents can read the facts without parsing HTML.
- [ ] **Recommended** [Offer content machines can read](https://agentwranglers.se/playbook/website/ready-for-ai-agents/machine-readable-formats): Offer the site's content as a sitemap, feeds, Markdown and JSON-LD.
- [ ] **Recommended** [Advertise agent files in headers](https://agentwranglers.se/playbook/website/ready-for-ai-agents/link-headers): List your discovery files in HTTP `Link` headers on every response. These include llms.txt, the sitemap, feeds, the API catalog and agent cards.
- [ ] **Optional** [Offer all content in one file](https://agentwranglers.se/playbook/website/ready-for-ai-agents/llms-full-txt): Publish `/llms-full.txt` with the full text of every public page in one Markdown file.
- [ ] **Optional** [Say how your content may be used](https://agentwranglers.se/playbook/website/ready-for-ai-agents/content-signals): Use `Content-Signal` lines in robots.txt to say whether your content may be used for search, AI answers or AI training.
- [ ] **Optional** [State your text-mining choice](https://agentwranglers.se/playbook/website/ready-for-ai-agents/tdmrep): State whether you reserve text-and-data-mining rights. Use a `tdm-reservation` header and `/.well-known/tdmrep.json`, matching robots.txt.
- [ ] **Optional** [Sign your bot's requests](https://agentwranglers.se/playbook/website/ready-for-ai-agents/web-bot-auth): If you run a crawler or agent, sign its requests with Web Bot Auth. As a site, don't block unsigned bots by default.
- [ ] **Optional** [Explain how agents sign up](https://agentwranglers.se/playbook/website/ready-for-ai-agents/auth-md): If agents must register before using your service, explain how in an `auth.md` file at the root of your service.
- [ ] **Optional** [Describe your MCP tools honestly](https://agentwranglers.se/playbook/website/ready-for-ai-agents/mcp-and-tool-discovery): If you run an MCP server, a way for AI assistants to use your tools, publish a server card and label every tool honestly.
- [ ] **Optional** [Publish an agent card](https://agentwranglers.se/playbook/website/ready-for-ai-agents/a2a-agent-cards): If you run an A2A agent, one that talks to other agents, publish its card at `/.well-known/agent-card.json`. Keep a working endpoint behind it.
- [ ] **Optional** [List skills agents can learn](https://agentwranglers.se/playbook/website/ready-for-ai-agents/agent-skills-discovery): Publish agent skills as `SKILL.md` files, listed in `/.well-known/agent-skills/index.json`. Give each one a digest, a hash of its exact bytes.
- [ ] **Optional** [List agent endpoints in DNS](https://agentwranglers.se/playbook/website/ready-for-ai-agents/dns-aid): List your agent endpoints in DNS with SVCB records, as the DNS-AID draft describes. Sign the zone with DNSSEC so answers can be trusted.
- [ ] **Optional** [Keep one catalogue of agent tools](https://agentwranglers.se/playbook/website/ready-for-ai-agents/agentic-resource-discovery): List your MCP servers, agents and skills in `/.well-known/ai-catalog.json`. Link it from every page.
- [ ] **Optional** [Answer questions from your own pages](https://agentwranglers.se/playbook/website/ready-for-ai-agents/nlweb): Offer an endpoint that answers plain-language questions from your own content, with sources.
- [ ] **Optional** [Give in-browser agents your tools](https://agentwranglers.se/playbook/website/ready-for-ai-agents/webmcp): Register the site's tools with the browser through WebMCP. Mark the ones with effects, and report expected failures in the tool's answer.
- [ ] **Optional** [Package your knowledge for agents](https://agentwranglers.se/playbook/website/ready-for-ai-agents/okf-bundle): Publish the site's knowledge as an Open Knowledge Format bundle. It has an index, one typed Markdown file per concept, and a change log.
- [ ] **Optional** [Index every page's data file](https://agentwranglers.se/playbook/website/ready-for-ai-agents/schemamap): List every JSON-LD file with its types in `/schemamap.xml`. Link it from the page head.
- [ ] **Optional** [Ask agents to credit you](https://agentwranglers.se/playbook/website/ready-for-ai-agents/ask-for-credit): If agents may reuse your content in their own work, tell them how to credit it, on every page and in the Markdown copy.
- [ ] **Avoid** [Show agents the same page as people](https://agentwranglers.se/playbook/website/ready-for-ai-agents/same-content-for-agents): Never serve AI crawlers or agents different content from what people see, chosen by user agent, IP address or bot signature.

## Privacy

- [ ] **Required** [Explain what you keep and why](https://agentwranglers.se/playbook/website/privacy/privacy-policy): Publish a full privacy policy, linked from every page. It says who you are, what you collect and why, the legal basis, retention, recipients, rights and complaints.
- [ ] **Required** [Store nothing extra without a yes](https://agentwranglers.se/playbook/website/privacy/cookie-consent): Ask before storing anything non-essential. Make saying no as easy as saying yes, and store nothing until people agree.
- [ ] **Required** [Keep only what you need and delete it on time](https://agentwranglers.se/playbook/website/privacy/data-minimization): Collect only the data a task needs. Keep it only for its set retention period, and delete it on schedule and on request.
- [ ] **Required** [Keep personal data out of addresses](https://agentwranglers.se/playbook/website/privacy/personal-data-out-of-urls): Never put names, email addresses or other personal data in URLs. Send them in the body of a POST request instead. Only single-use links from an email may carry a random token.
- [ ] **Required** [Sign a contract with every processor](https://agentwranglers.se/playbook/website/privacy/processor-agreements): Have a data processing agreement with every service that handles personal data for you, such as hosting, email or analytics.
- [ ] **Required** [Plan for a data breach](https://agentwranglers.se/playbook/website/privacy/breach-plan): Write down what to do when personal data leaks, before it happens.
- [ ] **Required** [Let people see and delete their data](https://agentwranglers.se/playbook/website/privacy/data-requests): Give people a working way to get a copy of their data, correct it and have it deleted, and answer within one month.
- [ ] **Required** [Say when people talk to an AI](https://agentwranglers.se/playbook/website/privacy/disclose-ai): Tell people when they are talking to an AI system, and label AI-made images, audio and video that could pass as genuine.
- [ ] **Recommended** [Treat the privacy signal as a no](https://agentwranglers.se/playbook/website/privacy/global-privacy-control): Treat a `Sec-GPC: 1` signal as an opt-out of selling or sharing data, and say so in the privacy policy.
- [ ] **Recommended** [Host everything yourself for privacy](https://agentwranglers.se/playbook/website/privacy/third-party-scripts): Avoid third-party scripts. Host what you need yourself, so visitors' data does not go to other companies.
- [ ] **Recommended** [Count visits without tracking people](https://agentwranglers.se/playbook/website/privacy/analytics-privacy): Measure without tracking people. Use no analytics, or analytics without cookies or personal data.
- [ ] **Recommended** [Store each preference where it is needed](https://agentwranglers.se/playbook/website/privacy/preference-storage): Keep a visitor's preferences in local storage when only the browser needs them. Use a cookie only when the server must know the preference before it answers.
- [ ] **Recommended** [Load embedded videos and maps only after a click](https://agentwranglers.se/playbook/website/privacy/click-to-load-embeds): Show a still image and a button in place of each third-party embed. Load the video, map or social post only after the visitor clicks.
- [ ] **Optional** [Ask before embedded content uses cookies](https://agentwranglers.se/playbook/website/privacy/storage-access-api): If embedded content needs its own cookies, ask for them with the Storage Access API. Don't rely on third-party cookies.

## When things break

- [ ] **Required** [Make error pages helpful and honest](https://agentwranglers.se/playbook/website/when-things-break/error-pages): Serve 404 and 500 pages with the right status codes and the site's own navigation. Never show stack traces.
- [ ] **Recommended** [Say when you'll be back](https://agentwranglers.se/playbook/website/when-things-break/maintenance-pages): During planned maintenance, answer 503 with `Retry-After` and a clear page. Keep the health check working.
- [ ] **Recommended** [Keep working when a script or service fails](https://agentwranglers.se/playbook/website/when-things-break/graceful-degradation): When a script, a font or another company's service fails at runtime, the page still shows its content and its main actions still work.
- [ ] **Recommended** [Hide buttons that need JavaScript until it runs](https://agentwranglers.se/playbook/website/when-things-break/hide-script-only-controls): Never show a button that does nothing. Hide controls that need JavaScript until the script is running, without moving the page.
- [ ] **Recommended** [Let people install the site](https://agentwranglers.se/playbook/website/when-things-break/pwa-manifest): Publish a web app manifest with a name, start address, colours, and 192 and 512 px icons, including a maskable one.
- [ ] **Recommended** [Serve the last good page when the server fails](https://agentwranglers.se/playbook/website/when-things-break/serve-stale-on-error): Let caches keep serving the last good copy of a public page for up to a day when the app fails or times out.
- [ ] **Recommended** [Collect script errors from visitors' browsers](https://agentwranglers.se/playbook/website/when-things-break/browser-error-reports): Send every uncaught script error and rejected promise from the browser to your own endpoint, and alert when they rise.
- [ ] **Optional** [Keep working when the network drops](https://agentwranglers.se/playbook/website/when-things-break/offline-support): Add a service worker, a small script that sits between the page and the network. Show an offline page and cached pages when the network fails.
- [ ] **Optional** [Warn before retiring an address](https://agentwranglers.se/playbook/website/when-things-break/deprecation-and-sunset): Before you retire an address or API, announce it with `Deprecation` and `Sunset` headers.

## Languages and regions

- [ ] **Required** [Mark foreign words](https://agentwranglers.se/playbook/website/languages-and-regions/lang-attribute): Mark every passage in another language with its own `lang` attribute.
- [ ] **Recommended** [Give each language its own path](https://agentwranglers.se/playbook/website/languages-and-regions/international-url-structure): On sites with several languages, give each language one clear address pattern, such as `/en/` and `/sv/`, and keep it stable. A one-language site needs no prefix.
- [ ] **Recommended** [Link language versions together](https://agentwranglers.se/playbook/website/languages-and-regions/hreflang): On sites with several languages, link each language version of a page to the others with `hreflang`. A one-language site should not use it.
- [ ] **Recommended** [Translate the metadata too](https://agentwranglers.se/playbook/website/languages-and-regions/localised-metadata): Set the language in `lang`, `og:locale` and `inLanguage` in structured data, and write alt text in that language.
- [ ] **Recommended** [Let people pick their language](https://agentwranglers.se/playbook/website/languages-and-regions/language-switcher): On sites with several languages, offer a switcher that names each language in that language and keeps people on the same page.
- [ ] **Recommended** [Support right-to-left text](https://agentwranglers.se/playbook/website/languages-and-regions/rtl-support): Support right-to-left languages with `dir`, logical CSS properties and `dir="auto"` on user input.
- [ ] **Recommended** [Format dates and numbers for the reader](https://agentwranglers.se/playbook/website/languages-and-regions/locale-content): Format dates, numbers and money for the reader's locale with a formatting library. Show times with a named time zone.
- [ ] **Recommended** [Get plurals right in every language](https://agentwranglers.se/playbook/website/languages-and-regions/plural-rules): Choose plural forms from the language's plural rules instead of adding an "s".
- [ ] **Recommended** [Translate whole sentences](https://agentwranglers.se/playbook/website/languages-and-regions/whole-sentence-messages): On sites with several languages, or one planned, keep every visible text in a message file. Use one entry per whole sentence with named placeholders, and never build a sentence from translated pieces.
- [ ] **Recommended** [Test with a pseudo-locale](https://agentwranglers.se/playbook/website/languages-and-regions/pseudo-localisation): When a site will be translated, build a pseudo-locale that makes every text longer and accented. Run the page tests in it before any translation exists.
- [ ] **Recommended** [Sort and compare text by locale](https://agentwranglers.se/playbook/website/languages-and-regions/locale-collation): Sort and compare visible text with a collator for the reader's locale, and normalise Unicode before comparing or storing it.
- [ ] **Recommended** [Accept names and addresses from every country](https://agentwranglers.se/playbook/website/languages-and-regions/international-names-and-addresses): Let people enter names and addresses as they are written in their country. Never reject letters, word counts or field shapes your own country does not use.
- [ ] **Optional** [List language versions in the sitemap](https://agentwranglers.se/playbook/website/languages-and-regions/sitemap-hreflang): On sites with several languages, list each page's language versions in the sitemap with `hreflang`.
- [ ] **Optional** [Keep names out of machine translation](https://agentwranglers.se/playbook/website/languages-and-regions/translate-attribute): Protect names, code and addresses from machine translation with `translate="no"`.
- [ ] **Optional** [Support vertical and CJK text](https://agentwranglers.se/playbook/website/languages-and-regions/writing-modes): Where Chinese, Japanese or Korean (CJK) text appears, support vertical writing and their line breaking with `writing-mode` and the right line-break rules.
- [ ] **Optional** [Make non-ASCII domains work](https://agentwranglers.se/playbook/website/languages-and-regions/idn-support): If you use a domain name with non-Latin or accented letters, make its punycode form work everywhere the name appears.
- [ ] **Avoid** [Never redirect by location](https://agentwranglers.se/playbook/website/languages-and-regions/avoid-auto-geo-redirects): Never send people to another language or country by IP address or `Accept-Language`. Suggest it and let them choose.
