> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trybluesky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect to the Agent Edge Network

> Connect your Next.js / Vercel site to the Bluesky Agent Edge Network — detect verified AI crawlers and serve them citation-optimized pages.

Bluesky's Agent Edge Network (AEN) runs as **edge middleware inside your own Next.js
app on Vercel**. It detects AI answer-engine crawlers — ChatGPT, Perplexity,
Claude, and more — by their user-agent, then verifies them against the vendor's
published IP ranges. By the end of this
guide you'll have the middleware live in **shadow mode**, logging every AI agent visit
to Agent Analytics, plus a single-constant change to start serving those crawlers a
clean, citation-optimized version of each page — without touching your application code
or risking your classic search rankings.

<Note>
  Classic search bots (Googlebot, Bingbot, Applebot) are **never** branched. The
  middleware carries a hard cloaking firewall that always passes them straight through
  to your normal page — serving Google's index different content would be cloaking
  Search itself.
</Note>

## Prerequisites

<Note>
  You need a **Next.js project already deployed on Vercel** and a
  [Bluesky account](https://app.trybluesky.com) with at least one domain connected.
  No other dependencies or build-step changes are required.
</Note>

***

## Setup

<Steps>
  <Step title="Provision the edge in Agent Analytics">
    1. Open [app.trybluesky.com](https://app.trybluesky.com) and go to **Agent Analytics**.
    2. Select your domain, then click **Connect**.
    3. Copy the **edge token** that appears — it is returned **once**, on provision.
       If you lose it, click **Connect** again to mint a fresh one (re-provisioning
       rotates the token).

    The token is scoped to a single site and is fully revocable. It is **not** your
    account API key, so a leaked edge token can be rotated without touching the rest
    of your account.

    ```
    aen_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ```

    <Warning>
      Store the token before leaving the page. The same token cannot be retrieved
      after the dialog closes — you can only mint a new one.
    </Warning>
  </Step>

  <Step title="Add AEN_EDGE_TOKEN to Vercel">
    In the Vercel dashboard, go to your project → **Settings** →
    **Environment Variables** and add:

    ```bash theme={null}
    AEN_EDGE_TOKEN=aen_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ```

    Replace the placeholder with the token from Step 1. Enable it for the
    **Production** environment (and **Preview** if you want to test on preview
    deployments). The middleware reads this as `process.env.AEN_EDGE_TOKEN`; if it's
    unset, the middleware passes every request through untouched.
  </Step>

  <Step title="Install middleware.ts at the project root">
    Follow the [Next.js Middleware guide](/guides/nextjs-middleware) — run
    `npx @trybluesky/aen init` or copy the self-contained `middleware.ts`, and place it at the
    **root** of your Next.js project (the same level as `package.json`).

    The file is self-contained with **zero dependencies** and runs on the Vercel Edge
    runtime — no `npm install` required.

    Three parts of the file are worth knowing:

    <CodeGroup>
      ```typescript Route matcher (config) theme={null}
      // Covers every public page; skips Next.js internals, API routes, and favicon.
      export const config = { matcher: ["/((?!_next/|api/|favicon.ico).*)"] };
      ```

      ```typescript Serve mode constant theme={null}
      // The drop-in middleware supports two modes via this constant:
      //   "shadow"  = log AI agent visits, always serve the normal page (safe default)
      //   "default" = serve the citation-optimized artifact to verified answer engines
      const SERVE_MODE: "shadow" | "default" = "shadow"; // ← flip to "default" to serve

      // Only these agent purposes are ever eligible for the variant.
      const ENABLED = new Set(["USER_TRIGGERED", "RETRIEVAL"]);
      ```

      ```typescript Detection + cloaking firewall theme={null}
      const bot = matchBot(ua, bots);       // user-agent token match against the botset
      if (!bot) return NextResponse.next();

      // CLOAKING FIREWALL: search-index bots always get the human page.
      if (bot.isSearchIndex) return NextResponse.next();

      const verified = ipInCidrs(ip, bot.cidrs); // published vendor IP ranges (CIDR)
      // eligible = verified && ENABLED.has(bot.purpose)
      ```
    </CodeGroup>

    Commit and push to trigger a Vercel deployment.

    <Note>
      The file ships with `SERVE_MODE = "shadow"`. In shadow mode the middleware
      **logs every AI agent visit** but always serves your normal page, so it is safe
      to deploy to production immediately — no visitor ever sees a different response.
    </Note>
  </Step>

  <Step title="Test with a browsing AI">
    Once your deployment is live, trigger a real AI crawler:

    1. Open **ChatGPT** (with browsing) or **Perplexity** (web search on).
       ChatGPT is the most reliable first test, because OpenAI publishes
       per-agent IP ranges that the drop-in can verify.
    2. Ask something that makes it look up a page on your domain — e.g.
       *"What does \[your-domain.com] say about X?"*
    3. The crawler fetches your page. The middleware matches the user-agent
       against the botset and checks the source IP against the vendor's published
       CIDR ranges. If the IP falls inside a published range, the hit is recorded
       as `IP_VERIFIED`; otherwise — including agents whose vendor does not
       publish IP ranges the drop-in can check — it's recorded as `UA_ONLY`. Only
       `IP_VERIFIED` hits are ever eligible for the variant.
    4. Open **Agent Analytics**. The hit should appear shortly, broken down by
       **purpose class** and **verification (trust) level**.

    <Note>
      If no hits appear, confirm that `AEN_EDGE_TOKEN` is set in Vercel, that the
      deployment containing `middleware.ts` is the active one, and that the AI tool
      actually fetched a page (some prompts trigger a web search but not a full
      page fetch).
    </Note>
  </Step>

  <Step title="Go live — flip SERVE_MODE to default">
    Once you've seen verified hits in Agent Analytics and you're ready for AI crawlers
    to receive the optimized pages, change the single constant:

    ```typescript theme={null}
    // Before
    const SERVE_MODE: "shadow" | "default" = "shadow";

    // After
    const SERVE_MODE: "shadow" | "default" = "default";
    ```

    Commit, push, and redeploy. From then on, a request is served the variant only when
    **all** of these hold: the source IP is verified (`IP_VERIFIED`), the agent's
    purpose is `USER_TRIGGERED` or `RETRIEVAL`, and a generated artifact exists for that
    URL. The middleware fetches the pre-generated artifact and returns it as
    `text/markdown`. Everyone else — humans, search-index bots, and unverified
    user-agents — continues to get your normal page unchanged.
  </Step>
</Steps>

***

## Serve modes

The drop-in middleware exposes two modes through the `SERVE_MODE` constant:

| Mode      | Behavior                                                                                        |
| --------- | ----------------------------------------------------------------------------------------------- |
| `shadow`  | Detects and logs AI agent visits; always serves the normal page. **Safe default for installs.** |
| `default` | Serves the pre-generated artifact to verified, purpose-eligible answer-engine agents.           |

<Note>
  The full serve-mode vocabulary — `off`, `shadow`, `canary:<pct>`, and `default` —
  lives in the control plane and is exposed by the serve-mode picker in Agent
  Analytics. The zero-dependency Next.js middleware in this guide is limited to
  `shadow` and `default`. See the [serve modes guide](/guides/serve-modes) for the
  full vocabulary.
</Note>

<Warning>
  Search-index bots (Googlebot, Bingbot, Applebot) are **never** branched, regardless
  of serve mode. The cloaking firewall in the middleware is unconditional.
</Warning>

***

## What's next

<CardGroup cols={2}>
  <Card title="Agent Analytics" icon="chart-bar" href="/guides/agent-analytics">
    Read the served-vs-cited breakdowns — total hits, variants served, served URLs,
    cited share, and splits by purpose and trust level.
  </Card>

  <Card title="Optimized pages" icon="file-lines" href="/guides/optimized-pages">
    Learn how Bluesky generates AEO artifacts offline from your existing page content
    and how the citability score is computed.
  </Card>
</CardGroup>
