Website Spec
← Performance
Recommended

Speculation Rules

Tell the browser which links to prefetch or prerender before the user clicks. Done well, navigations feel instant; done carelessly, you burn bandwidth on pages nobody visits.

> This site ships it. Every page emits a <script type="speculationrules"> block from BaseLayout.astroprerender on moderate for HTML same-origin links, prefetch on conservative as a fallback. The CSP allows the block via 'inline-speculation-rules' (no 'unsafe-inline'), and our bot logger drops requests with Sec-Purpose: prefetch so the stats stay honest.

What it is

Speculation Rules let a page declare, in a structured way, which URLs the browser should prefetch (download the response in advance) or prerender (download and render the full page in a hidden background tab). When the user actually clicks, the navigation can complete in milliseconds because the work is already done.

The rules live in a <script type="speculationrules"> block:

<script type="speculationrules">
{
  "prerender": [{
    "where": { "href_matches": "/spec/*" },
    "eagerness": "moderate"
  }],
  "prefetch": [{
    "where": { "href_matches": "/*" },
    "eagerness": "conservative"
  }]
}
</script>

eagerness ranges from conservative (only on hover/touch) to eager (as soon as the rule is parsed). moderate is the sensible default — Chromium triggers on hover-with-intent and pointerdown.

This supersedes the older <link rel="prerender"> hint, which has been removed from the platform.

Why it matters

Cross-site prerender is gated on Chrome's No-Vary-Search and additional restrictions; same-site is the realistic target for most sites.

How to implement

Start small. Prerender only the obvious next pages — the main nav links from the homepage, the next page in a paginated list, the most-clicked CTA. Prerendering everything wastes data on links nobody clicks.

Prefer moderate eagerness over eager. It limits speculation to links the user is about to interact with.

Combine prefetch + prerender. Prefetch broadly (cheap), prerender narrowly (expensive). The rules above show the pattern.

Handle JavaScript correctly. Prerendered pages run their JS in a hidden, non-active context. Wait for the prerenderingchange event before running analytics, starting media, or anything user-visible:

<script>
if (document.prerendering) {
  document.addEventListener('prerenderingchange', () => init(), { once: true });
} else {
  init();
}
</script>

Pair with view transitions for cross-document animations on prerendered navigations — together they make MPA navigations feel like an SPA.

Don't speculate on URLs with side effects. Logout endpoints, "delete" actions, payment flows. Use urls/href_matches carefully and exclude them.

Common mistakes

Verification

Sources