Agent Experience is the new SEO

# Your next customer may never visit your website.

Get more AI user traffic and agent visibility.

**AgentSite optimizes your site's agent experience.** Better agent experience means better conversions for agent users and more traffic from AI chat users on ChatGPT, Gemini, Claude, or Perplexity — we inject titles, meta, OpenGraph, JSON-LD, markdown twins, and WebMCP tools into your existing site, **without modifying any site code**.

Diagnose my site — free

Free · no signup · live on screen in under 3 minutes · snippet stays in your codebase

Asked the best reasoning model in the world

## Even Claude Opus won’t read your site.

Typical websites built with React, Vue, or Angular show empty pages to agents. While agents stop reading advanced server-side rendering sites that render the kitchen sink for old SEO.

**Modern Agent Experience is about clean direct content readable by agents.** Not browsers and humans.

[Get your score — free](/score)

![Software professional with a skeptical expression](/portraits/c1.png "AI rendering of a product manager thinking about agent experience")

Appears to be a marine biology research portal focused on lobster habitats in the North Atlantic.

— Claude Opus 4.7, asked about lobster.app

Claude Opus 4.7 — what can you tell me about lobster.appClaude Opus 4.7 — what can you tell me about workspot.ioClaude Opus 4.7 — what can you tell me about ridesell.appClaude Opus 4.7 — what is paperflow.io

What is Agent Experience?

## Five things make your site readable to agents — or not.

Agent Experience (formerly called AEO) is what your site looks like to ChatGPT, Claude, Perplexity, and the long tail of bots that fetch HTML without running JavaScript. Five essentials decide whether you get cited or skipped.

1.  Content shows up in raw HTML
    
    SPAs serve an empty shell to non-JS bots. If `curl` of your page returns no body, agents see nothing. [Read: SSR-junk and bot walls →](/ssr-junk-bot-wall)
    
2.  The page tells the truth about itself
    
    Title, meta description, OG tags, JSON-LD schema — agents check these before they read body copy. Mismatches between what the schema claims and what the page says cost citations. [Read: Schema-content fit →](/schema-content-fit)
    
3.  There's a markdown mirror
    
    Agents prefer markdown to HTML noise — fewer tokens, cleaner structure. Per-page `.md` siblings and a `/llms.txt` pointer index are the standard. [Read: What llms.txt is and what it's for →](/llms-txt)
    
4.  The site declares itself
    
    `robots.txt` posture, `sitemap.xml`, well-known files, and emerging headers (Content-Usage, TDMRep, AI-Disclosure) tell crawlers how to behave. [Read: Robots Exclusion Protocol →](/robots-exclusion-protocol)
    
5.  What's claimed matches what's served
    
    A page that says "we offer X" but returns an empty shell or stale copy when an agent fetches it is a citation deduction. Fetch-time accuracy — the lane AgentSite owns. [Read: Schema-content mismatch →](/schema-content-mismatch)

### Where AgentSite sits

Four categories of tools attack agent experience. Most do one slice. AgentSite is the middleware lane.

-   Middleware
    
    Renders the SPA shell, injects `llms.txt` / schema / markdown twins, ships fresh HTML at fetch time — same bytes to humans and bots, no UA branching. **AgentSite is here.**
    
-   Mention monitoring
    
    Reports where you appear in chat answers. Telemetry only — doesn't change what agents see when they fetch the page.
    
-   AEO graders
    
    Single-shot quality scores against a chat model. Good for a number; doesn't move the underlying assets.
    
-   Framework SSR migration
    
    Move your stack from SPA to Next / Nuxt / SvelteKit SSR. Solves it at the source; weeks of work, permanent overhead.

#### Frank comparisons

One card per competitor. Each opens the honest four-section comparison.

[MiddlewareAgentSite vs Prerender.ioThe longest-running JS-rendering service. Different install, different bundled extras.→](/agent/vs-prerender)  
[MiddlewareAgentSite vs EncitedCloudflare-edge prerender (formerly LovableHTML) for the agency channel.→](/agent/vs-encited)  
[MiddlewareAgentSite vs Hado SEOLovable-marketplace-native prerender at the lowest entry price in the category.→](/agent/vs-hado)  
[MiddlewareAgentSite vs DataJellyDNS reverse-proxy dual-output (HTML + markdown). Per-domain pricing axis.→](/agent/vs-datajelly)  
[Mention monitoringAgentSite vs Profound$96M-funded category leader. Measures share of voice; doesn't change the underlying pages.→](/agent/vs-profound)  
[Mention monitoringAgentSite vs ScrunchNow a Sitecore company. Enterprise marketing teams; we're indie-SaaS.→](/agent/vs-scrunch)  
[Mention monitoringAgentSite vs Otterly$29 entry-tier monitoring with strong agency adoption. Same price, different problem.→](/agent/vs-otterly)  
[Deeper readsThe Learn libraryFoundations, technical layers, content tactics, field reports — and every comparison in one place.→](/learn)

## Before vs after AgentSite — same URL, real HTML.

Two fetches against the same live SPA. On the left, the raw shell agents see without us. On the right, the same URL with AgentSite's one-injection splice — **highlighted lines are what we added**. No code changes to your site; the snippet does it at response time.

Target`https://agentsite.app/features`

static snapshot

\+ Title & meta tags\+ JSON-LD schema\+ Markdown body\+ WebMCP tools

curl -H 'X-Agentsite: none' 'https://agentsite.app/features'

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>agentsite — ready for the agent era.</title>
  <meta name="description" content="Make your site agent-readable. Yours by default — we watch the agents, ship the best practices, and level your site up. ChatGPT, Claude, Gemini, and Perplexity see your SPA as an empty <div id=&quot;app&quot;>. We fix that with a snippet that stays in your codebase.">
  <link rel="icon" type="image/x-icon" href="/favicon.ico"/>
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png"/>
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png"/>
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
  <meta property="og:type" content="website">
  <meta property="og:site_name" content="AgentSite">
  <meta property="og:url" content="https://agentsite.app/">
  <meta property="og:title" content="agentsite — ready for the agent era.">
  <meta property="og:description" content="Make your site agent-readable. Yours by default — we watch the agents, ship the best practices, level your site up. Snippet stays in your codebase.">
  <meta property="og:image" content="https://agentsite.app/brand/og-card.png">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="630">
  <meta property="og:image:alt" content="Claude can't read your SPA. AgentSite is middleware that fixes that — get your score, free.">
  <!-- Square variant for clients that prefer 1:1 (WhatsApp, iMessage). -->
  <meta property="og:image" content="https://agentsite.app/brand/og-square.png">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="1200">
  <meta property="og:image:alt" content="Claude can't read your SPA. AgentSite is middleware that fixes that — get your score, free.">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title" content="agentsite — ready for the agent era.">
  <meta name="twitter:description" content="Make your site agent-readable. Yours by default — we watch the agents, ship the best practices, level your site up. Snippet stays in your codebase.">
  <meta name="twitter:image" content="https://agentsite.app/brand/og-card.png">
  <script src="/env.js"></script>
  <script>
    function loadScript(src, async) {var script = document.createElement("script");script.setAttribute('src', src);if (async) script.setAttribute('async', "");document.head.appendChild(script);}
    if (window.env.GOOGLE_ID) {
      loadScript("https://www.googletagmanager.com/gtag/js?id=" + window.env.GOOGLE_ID, true);
    }
  </script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag() {
      dataLayer.push(arguments);
    }
    if (window.env.GOOGLE_ID) {
      gtag('js', new Date());
      gtag('config', window.env.GOOGLE_ID);
    }
    // todo: uncomment consent when analytics tests complete
    // const consent = localStorage.getItem('consentParams');
    // gtag('consent', 'default', consent ? JSON.parse(consent) : {ad_storage: 'denied', analytics_storage: 'denied'});
  </script>
  <script type="module" crossorigin src="/assets/index-Wz56DZf_.js"></script>
  <link rel="modulepreload" crossorigin href="/assets/naive-ui-bij2l7m4.js">
  <link rel="modulepreload" crossorigin href="/assets/markdown-CBjZTZqh.js">
  <link rel="stylesheet" crossorigin href="/assets/index-CLD4np5n.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
```

curl 'https://agentsite.app/features'

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>Features — install patterns — agentsite</title>
  <meta name="description" content="AgentSite ships nginx, Express, Express-sidecar, Edge, and streaming-SSR SDK installs. Per-page markdown mirrors, /llms.txt, FAQPage schema, and request cache.">
  <link rel="icon" type="image/x-icon" href="/favicon.ico"/>
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png"/>
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png"/>
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
  <meta property="og:type" content="website">
  <meta property="og:site_name" content="AgentSite">
  <meta property="og:url" content="https://agentsite.app/">
  <meta property="og:title" content="Features — install patterns — agentsite">
  <meta property="og:description" content="AgentSite ships nginx, Express, Express-sidecar, Edge, and streaming-SSR SDK installs. Per-page markdown mirrors, /llms.txt, FAQPage schema, and request cache.">
  <meta property="og:image" content="https://agentsite.app/brand/og-card.png">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="630">
  <meta property="og:image:alt" content="Claude can't read your SPA. AgentSite is middleware that fixes that — get your score, free.">
  <!-- Square variant for clients that prefer 1:1 (WhatsApp, iMessage). -->
  <meta property="og:image" content="https://agentsite.app/brand/og-square.png">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="1200">
  <meta property="og:image:alt" content="Claude can't read your SPA. AgentSite is middleware that fixes that — get your score, free.">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title" content="Features — install patterns — agentsite">
  <meta name="twitter:description" content="AgentSite ships nginx, Express, Express-sidecar, Edge, and streaming-SSR SDK installs. Per-page markdown mirrors, /llms.txt, FAQPage schema, and request cache.">
  <meta name="twitter:image" content="https://agentsite.app/brand/og-card.png">
  <script src="/env.js"></script>
  <script>
    function loadScript(src, async) {var script = document.createElement("script");script.setAttribute('src', src);if (async) script.setAttribute('async', "");document.head.appendChild(script);}
    if (window.env.GOOGLE_ID) {
      loadScript("https://www.googletagmanager.com/gtag/js?id=" + window.env.GOOGLE_ID, true);
    }
  </script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag() {
      dataLayer.push(arguments);
    }
    if (window.env.GOOGLE_ID) {
      gtag('js', new Date());
      gtag('config', window.env.GOOGLE_ID);
    }
    // todo: uncomment consent when analytics tests complete
    // const consent = localStorage.getItem('consentParams');
    // gtag('consent', 'default', consent ? JSON.parse(consent) : {ad_storage: 'denied', analytics_storage: 'denied'});
  </script>
  <script type="module" crossorigin src="/assets/index-Wz56DZf_.js"></script>
  <link rel="modulepreload" crossorigin href="/assets/naive-ui-bij2l7m4.js">
  <link rel="modulepreload" crossorigin href="/assets/markdown-CBjZTZqh.js">
  <link rel="stylesheet" crossorigin href="/assets/index-CLD4np5n.css">
  <link rel="canonical" href="https://agentsite.app/features">
  <script type="application/ld+json" data-agentsite="bundle" data-agentsite-version="0.3.0">{"source":"agentsite","engine":"playwright","cacheStatus":"hit","url":"https://agentsite.app/features","renderedAt":"2026-06-16T20:50:56.101Z","expiresAt":"2026-06-17T20:50:56.101Z"}</script>
  <script type="application/ld+json" data-agentsite="schema" data-type="Organization">{"@id":"https://agentsite.app/#organization","url":"https://agentsite.app","name":"agentsite","@type":"Organization","sameAs":["https://www.linkedin.com/in/dathan-guiley/"],"@context":"https://schema.org"}</script>
  <script type="application/ld+json" data-agentsite="schema" data-type="WebPage">{"@id":"https://agentsite.app/features#webpage","url":"https://agentsite.app/features","name":"Features — install patterns — agentsite","@type":"WebPage","@context":"https://schema.org","isPartOf":{"@id":"https://agentsite.app/#website"},"description":"AgentSite's features ship across install patterns: nginx, Express, Express-sidecar, Edge, and streaming-SSR SDK. Each install gets the same render bundle — markdown body, schema graph, OpenGraph meta — plus per-page .md mirrors, an authoritative /llms.txt index, FAQPage schema synthesis from question headings, and a request cache. Pick the install pattern that matches your stack.","primaryImageOfPage":{"url":"https://agentsite.app/brand/og-card.png","@type":"ImageObject"}}</script>
  <script type="application/ld+json" data-agentsite="schema" data-type="WebSite">{"@id":"https://agentsite.app/#website","url":"https://agentsite.app/","name":"agentsite","@type":"WebSite","@context":"https://schema.org","publisher":{"@id":"https://agentsite.app/#organization"}}</script>
  <script data-agentsite="preboot-toggle">document.documentElement.setAttribute('data-agentsite-js','1')</script>
  <style data-agentsite="preboot-style">html[data-agentsite-js="1"] #agentsite-preboot{display:none}</style>
</head>
<body>
<div id="agentsite-preboot" aria-hidden="true">
<pre data-content-type="text/markdown" data-source="agentsite">
Features

# What you get when you install AgentSite.

AgentSite's features ship across install patterns: nginx, Express, Express-sidecar, Edge, and streaming-SSR SDK. Each install gets the same render bundle — markdown body, schema graph, OpenGraph meta — plus per-page `.md` mirrors, an authoritative `/llms.txt` index, FAQPage schema synthesis from question headings, and a request cache. Pick the install pattern that matches your stack.

More organic traffic from AI search

Agents that can read your site cite your site. Citations send users back. SPAs that ship an empty shell don't get cited — they get skipped.

Trust with agent-first users

People navigating with ChatGPT, Claude, Perplexity notice which sites their agents handle cleanly. Those are the sites they remember — and prefer.

Stop worrying about AEO.

We take what your site naturally produces and make every agent contact point better through our generated agent version — llms.txt, schema, markdown, the lot. You install once; we keep up with the drift.

Three things you get out of the box: agent-readable content generated on demand, standards-compliant docs that stay current as the standards drift, and intelligent merging with the meta and schema you already wrote. Pick the install pattern that matches your deploy — Nginx, Express, Express-Sidecar, Edge, or a streaming-SSR SDK — and the same render bundle lands in your response.

## 1 · Dynamic generation of content for agents

Every page on your SPA gets agent-readable content rendered when it's first asked for — not authored by you, not stale, not frozen at build time. Headless Chromium runs your shell, waits for content, and captures the title, description, og:image, JSON-LD graph, and markdown body that an actual user would see. On cold miss the snippet serves your unmodified shell immediately and renders in the background; first agent to hit a path warms the cache for everyone after.

![Clean markdown body served at agentsite.app/install.md — the exact bytes an agent extracts.](/brand/features/feature-1-markdown.png)

`agentsite.app/install.md` — the same markdown body an agent reads when it fetches your page. Add `.md` to any path; same content, no HTML chrome.

-   **Preboot hidden-div default.** The markdown body lands inside `&lt;div id="agentsite-preboot" aria-hidden="true"&gt;&lt;pre data-content-type="text/markdown"&gt;` just before `&lt;/body&gt;`. A toggle script + style in `&lt;head&gt;` hides it the moment JS boots, so humans never see it; agents and extractors that strip `&lt;noscript&gt;` (Claude.ai's web tool, most readability libs) read it cleanly. Per-site override switches to legacy `&lt;noscript&gt;` mode for tools that honor that (Claude Code's WebFetch).
-   **Wait-for-generation: `robots-only` by default.** Bots are usually the first requester of a page; they don't retry. So bots block on the first render and get real content. Humans get the unmodified shell + an async render — they never pay the scan-and-generate latency. Switchable per-site to `always` or `never`.
-   **TL;DR extraction per page.** 40–60-word direct answer drives meta descriptions + article descriptions when your static defaults are too generic.
-   **Content-hash dedupe.** When nothing on the page changed, we extend the cache expiry without re-running the renderer — `dateModified` stays truthful instead of refreshing to "now" on every request.
-   **Per-page markdown.** Same content as the preboot body, in a denser format. Reachable via `Accept: text/markdown` or by adding `.md` to any path.

## 2 · Best-practice documents that stay current

Every standards-compliant doc an AI crawler expects on your domain — generated, served, kept current as the standards drift. You ship zero static files; the snippet serves them all dynamically from your live cached bundles.

![agentsite.app/llms.txt rendering — site overview with page list and TL;DRs.](/brand/features/feature-2-llms-txt.png)![agentsite.app/robots.txt rendering — granular AI-bot allow-list with comments.](/brand/features/feature-2-robots-txt.png)![agentsite.app/sitemap.xml rendering — walked from cached routes, standard urlset.](/brand/features/feature-2-sitemap-xml.png)

Live on `agentsite.app`: `/llms.txt` · `/robots.txt` · `/sitemap.xml`. Generated, not authored. Customer files in `dist/` win.

-   **`/llms.txt` + `/llms-full.txt`** per Jeremy Howard's spec — a pointer overview at `/llms.txt`, with detail in `/install.md` and `/docs.md` for agents arriving with no prior context.
-   **`/sitemap.xml`** walks your cached routes, drops auth/admin paths, emits standard sitemaps.org `&lt;urlset&gt;`.
-   **`/robots.txt`** with a granular AI-bot allow-list: citation bots allowed, training bots policy explicit, heavily commented so you can audit.
-   **Per-page `.md` mirrors.** Mintlify-style content negotiation: `Accept: text/markdown` or `.md` path suffix returns the markdown body without HTML chrome.
-   **Customer overrides win.** Ship `dist/llms.txt` and your file beats ours via static-route precedence. We're the default, not the ceiling.
-   **Schema.org drift handled.** Our generator updates as standards evolve; customer-shipped JSON-LD freezes on the day it's written. Install-stays-fresh is the live argument here.

## 3 · Intelligent merging with what you already have

Your existing meta, schema, and per-page overrides are preserved verbatim — we fill gaps, we don't overwrite. The page reads as "yours plus ours," not "ours instead of yours."

![JSON-LD blocks pulled from agentsite.app/pricing — Article, Organization, WebPage, FAQPage emitted via @id-linked nodes.](/brand/features/feature-3-jsonld.png)

Real JSON-LD blocks from `agentsite.app/pricing` — multiple `@type`s cross-linked via `@id`. Customer-shipped schema wins; ours fills the gaps.

-   **Meta refreshed in place.** Your indentation, comments, and per-page overrides survive. Hand-rolled `og:type=article`, custom canonicals, alternate languages — pass through untouched.
-   **JSON-LD only-if-absent.** Existing `&lt;script type="application/ld+json"&gt;` blocks are parsed; we emit ONLY the `@type`s not already present. Per-page hand-rolled JSON-LD always wins; we cross-link new nodes to your existing ones via `@id` so the graph resolves into one coherent description.
-   **LLM-assisted FAQ extraction** refines `FAQPage` schema from prose that doesn't follow the `## Question?` heading convention. We won't name a specific model — we iterate on what scores best on our own renders.
-   **Customer files in `dist/` win** over our generated versions of the same path (llms.txt, robots.txt, sitemap.xml). Our default is the floor; you can always go higher.

## 4 · Drops into your stack

Same render bundle, different injection point — pick the shape your deploy already supports.

![Terminal showing the Express install pattern — curl the snippet, three lines of glue code, set the token, ship.](/brand/features/feature-4-install.png)

Express install pattern end-to-end: curl the snippet, three lines of glue, set `AGENTSITE_TOKEN`, ship. About five minutes start to finish.

Nginx

Our favorite

Thin nginx in front of a static SPA. Add a handful of `location` + `proxy_pass` directives; agentsite owns the HTML byte stream. No Node sidecar, no edge function, no code in your deploy.

Express

Static SPA in a Node container. The snippet runs in your Express middleware, splices the render bundle into your `index.html` before responding. One CJS file, audit-able line by line.

Express-Sidecar

Non-streaming SSR framework (Next.js pages router, Nuxt 2, Rails, Django, PHP-FPM, etc.). Snippet runs as a reverse-proxy sidecar in front of your framework's existing server.

Edge

Cloudflare Pages, Vercel edge, Netlify, or any platform that runs Fetch-API edge functions instead of arbitrary Node. Drop in `agentsite-edge.mjs` + the platform's edge-middleware shell.

SDK — streaming SSR

Framework SDK for streaming SSR — Next.js App Router (RSC), Nuxt 3 streaming, SvelteKit streaming, Suspense streaming. In-process render hooks instead of a proxy in front of your framework.

**Latency-sensitive.** Cold miss responds with your unmodified shell in milliseconds and renders in the background. Warm hits read the cached bundle from Postgres + edge cache. Sites that need first-render freshness on bot traffic flip wait-for-generation to `always`; sites that prioritize human TTFB above all keep the default. `Cache-Control: no-cache` forces a fresh render on any request.

**Further out.** Native nginx-njs port, CloudFront Lambda@Edge, Python (Django/Flask/FastAPI), PHP (PHP-FPM / WordPress). No build-time pre-render CLI — SPAs are runtime-rendered by design.

## 5 · Tunable from the dashboard

Per-site controls for the behaviors that matter, plus the AEO Report — the same scan we use to grade our own renders, run against any URL.

![AgentSite dashboard per-site overview — snippet health, hit rate, generated files (llms.txt, llms-full.txt, sitemap.xml, robots.txt) with per-file re-crawl, and the AI-bot citation + training allow toggles.](/brand/features/feature-5-dashboard.png)

Per-site overview at [/dashboard](/dashboard) — snippet health, hit rate, the four generated files with per-file re-crawl, and the AI-bot citation + training allow toggles. Settings tab adds wait-for-generation, render-mode, and skip patterns covered in the bullets below.

-   **Wait-for-generation policy.**`robots-only` (default) · `always` · `never`. Decides who blocks for the first render on a cold path.
-   **Render-mode override.** Preboot hidden-div (default) or legacy `&lt;noscript&gt;`. Switch per-site for tools that honor one but not the other.
-   **Skip patterns.** Glob-match paths you don't want rendered (admin, search, attack probes). Copy-paste textarea; common probes auto-add as they're detected.
-   **AEO Report.** Run an 8-dimension citability scan on any URL at [/score](/score). Free, no signup. The same yardstick we grade our own output on.
-   **Per-site API tokens.** `asit_…` opaque strings, hashed with SHA-256. Pinned to one registered domain — leaked tokens are useless off-domain. Rotate any time.
-   **Usage tracking.** One row per `(site, day_utc)` with cache-hit / cache-miss / forced-sync / auth-failure counters. 30 days of history per site in the dashboard.

## 6 · What you didn't have to build yourself

Each row below is something AgentSite replaces. The alternative imposes the cost in the left column; the feature is that you don't pay it.

Second parallel deployment (Chromium fleet on your infra)

Render fleet runs on ours. Your container is just Node + your SPA + a small snippet.

Build-time pre-rendering of every route

We render on demand and cache. First agent to hit a path warms the cache for everyone after.

Periodic snapshot drift between rebuilds

Content-hash dedupe + 24h TTL with `Cache-Control: no-cache` bypass. Snapshots stay current without nightly rebuilds.

UA-switching / cloaking-adjacent config

Same bytes to humans and bots. The agent-readable layer lives in a preboot div + JSON-LD blocks — a real user never sees a different DOM than a crawler does.

Framework migration to SSR

Snippet drops into your existing nginx, Express server, or sidecar. Streaming-SSR shops drop in the framework SDK without rewriting. Your component tree, routing, and build pipeline are untouched.

Maintaining your own LLM pipeline for content gen

TL;DR extraction, FAQ refinement, schema detection — we run the LLM hops; you pay per render at our rate, not per token at theirs.

Tracking schema.org standard drift

Our generator updates; customer-shipped frozen JSON-LD decays silently. Install-stays-fresh is the live argument.

An npm SDK / opaque library

Snippet is plain CJS or Fetch-API, audit-able, lives in your codebase. Curl + drop.

## What we deliberately don't do

-   **No User-Agent switching.** If two visitors get different bytes for the same URL, that's cloaking. We don't. The snippet is UA-blind; bot identification is telemetry only.
-   **No mailbox / mirror site.** AgentSite never becomes the public destination — your domain stays canonical.
-   **No retry storms.** If our API errors, the middleware serves your unchanged HTML and moves on. Fail-open is non-negotiable.
-   **No tracking pixels in the bundle.** The injected payload is meta tags, markdown, and standards-compliant schema.org JSON-LD. Nothing else.
-   **No build-time pre-render CLI.** SPAs are runtime-rendered by design. A "build and walk every route" step is against the grain of why you shipped a SPA.
-   **No LLM-brand promise.** We iterate on which model scores best for FAQ extraction and TL;DR generation; we won't name one in marketing because we'll swap it the moment a better one ships.

[Pick your install pattern →](/getting-started)

## Easy install. Optimized to not impact your performance.

Five minutes start to finish. Cold misses respond with your unmodified shell in milliseconds while we render in the background — humans never pay scan-and-generate latency, bots get the enriched response on the next fetch. Warm hits read the cached bundle.

### Sign up and get a token.

[Sign up](/auth/sign-up), pick a plan, register your domain. The kickoff allowance lets you try without a card.

### Tell Claude to set it up.

Paste this into Claude Code (or Cursor, Copilot, any coding agent). One prompt informs, instructs, and configures:

```
Set up agentsite on my server. My token is asit_xxxxxxxx. Read https://api.agentsite.app/llms.txt and follow the install instructions for an Express app serving a static SPA from `./dist`.
```

### Deploy and enjoy.™

Push your branch. The token usually needs to land in your CI/CD secrets or deploy environment (Claude will do this when it sets you up). The dashboard flips to live on the first agent fetch.

**Done.** Your SPA now serves real content to agents and share-card scrapers — in the same response real users get.

**No UA tricks. No bot routing.** Every visitor — human, GPTBot, ClaudeBot, Perplexity, share-card scraper — gets the same bytes.

Need more information? [Ask your agent if agentsite.app is cool.](https://claude.ai/new?q=Is%20agentsite.app%20cool%3F)

## Ways to get started, depending on your role.

Three doors into the same product — pick the one that matches who you are today.

[Building it yourself?

Sign up and let an agent install it.

Get a token. Paste one line into Claude Code, Cursor, or Copilot. Pick the install pattern that matches your stack — Nginx, Express, Sidecar, Edge, or a streaming-SSR SDK — about five minutes start to finish.

Sign up →](/auth/sign-up)

[Built it with Lovable, v0, or Bolt?

Your shipped SPA can still be agent-readable.

The AI tool generated a single-page app and called it done. We add the layer that makes ChatGPT, Claude, and Gemini able to read it — no rebuild, no second tool. Lovable's default Cloudflare deploy works out of the box via our Edge install.

Sign up →](/auth/sign-up)

Running marketing or growth?

Run the report, bring it to your dev team.

Same scan, framed for hand-off. We'll show you exactly where to point them — or talk it through with the founder before you do.

[Run the report →](/score?audience=marketer)  
[Talk to the founder →](mailto:[email protected]?subject=agentsite%20chat)

## Common questions

**Do AI engines actually run JavaScript when they crawl?**

Overwhelmingly no. Vercel's analysis of half a billion GPTBot fetches found zero JavaScript execution. ChatGPT, Claude, Perplexity, Bing Chat, AI Overviews — they all read the raw HTML response. If your site is a SPA, all of them see `<div id="app"></div>` where your content was supposed to be.

**How is AgentSite different from AEO graders and mention-monitoring tools?**

Those tools diagnose. AgentSite diagnoses AND fixes — measures the same way they do, then installs the actual middleware that makes your content citable. The whole loop in one product.

**Why can't I just do this myself?**

You can. v1 is a weekend. What burns is the ongoing tail — bot UAs shift quarterly, `llms.txt` schema is still moving, attack-probes mutate, freshness scans need cluster-scheduling. Citation rates regress invisibly when any of it drifts, and you can't tell without scanning from outside. We treat that tail as the product — server-injected agent-readable markdown that LLMs read directly.

**Will this break my site?**

No. The snippet is fail-open — if our cloud is unreachable, it falls back to your unmodified `index.html`. No exception bubbles up to visitors. Removing the snippet is one line of code; everything goes back to before.