Skip to main content
The Bluemoon Agent Edge Network (AEN) installs as a Next.js middleware — either the @trybluemoon/aen npm package (two lines) or a single self-contained middleware.ts file you paste in. Either way it runs on Vercel Edge. This page covers both install paths, the settings you can change, and troubleshooting.
This is an edge middleware you install in your own app, not a reverse proxy in front of your site. On Cloudflare, use the Cloudflare Worker instead.

Prerequisites

  • A Next.js project deployed on Vercel (or running locally with next dev)
  • An edge token (format aen_...) from Agent Analytics in the Bluemoon app: choose Next.js / Vercel and click Connect edge, or open Setup if the site is already connected. It works for one site and can be replaced.

Install

Existing middleware

Already running a middleware — next-intl, auth, redirects? Don’t replace it. The package exports a composable handle() that returns a Response when it served a verified AI crawler, or null to fall through to your own code. Add two lines at the top of your middleware:
middleware.ts (next-intl example)
handle() reports crawler hits in every mode and returns null in shadow mode, so your site behaves exactly as before until you set AEN_SERVE_MODE=default. Running npx @trybluemoon/aen init in a project that already has a middleware prints this recipe automatically instead of overwriting your file.

The complete middleware.ts

Paste this entire file at the root of your Next.js project, then set AEN_EDGE_TOKEN as an environment variable (see the step above). This is the drop-in — zero dependencies beyond next/server, running on Vercel Edge.
middleware.ts

Configuration constants

All configuration lives at the top of middleware.ts. You do not need to touch anything else in the file.
middleware.ts (configuration section)
This file supports shadow and default only. See Serve modes for what each mode does.

The config matcher

This tells Next.js to run the middleware on every public page route while skipping:
  • /_next/ — Next.js build assets and hot-reload
  • /api/ — your API routes
  • /favicon.ico — the favicon
You should not need to change the matcher. If you have additional paths that must never be intercepted, add them to the negative lookahead.

What the middleware does

On every page request, the middleware:
  • Does nothing if AEN_EDGE_TOKEN is empty — your site behaves as if the file weren’t there.
  • Passes through anything that isn’t a known AI crawler.
  • Never touches search bots — Googlebot, Bingbot and Applebot always get your real page (the cloaking firewall).
  • Serves verified answer-engine crawlers the optimized version of the page when the serve mode is default (AEN_SERVE_MODE for the npm package, SERVE_MODE in the copy-paste file), the crawler’s purpose is enabled, and Bluemoon has an optimized version of that URL. In every other case the crawler gets your normal page.
  • Reports every crawler hit to Agent Analytics without delaying the response.
A served response has Content-Type: text/markdown and the header x-aen-served: variant, so you can tell it apart from your normal page.
In shadow mode every hit is recorded as Passthrough, even for crawlers that would be served. This lets you see how many crawlers would get the optimized version before you switch to "default".

Verified and unverified crawlers

Agent Analytics shows whether each hit was verified: See Detection & verification for more.

Troubleshooting

  1. Confirm the middleware.ts file is at the project root, not inside src/ or app/.
  2. Confirm AEN_EDGE_TOKEN is set in your Vercel environment and you have redeployed after adding it.
  3. Make sure you triggered a real AI crawler (ChatGPT or Perplexity with browsing), not your own browser. Unverified (UA_ONLY) requests are not shown as verified hits.
Check that the serve mode is default, not shadow (AEN_SERVE_MODE=default for the npm package, SERVE_MODE = "default" in the copy-paste file), and that you redeployed after the change. Also confirm Bluemoon has an optimized version of the URL you are testing — you can check this in Agent Analytics.
This means the request was not Verified (IP_VERIFIED), the crawler’s purpose is not in ENABLED, or there is no optimized version of that URL yet. Verified USER_TRIGGERED / RETRIEVAL crawlers get the optimized version when one exists. The copy-paste file only verifies crawlers that connect over IPv4; a crawler that reaches you over IPv6 is recorded as Unverified (UA_ONLY).
The file uses the NextRequest / NextResponse API and the Web Crypto API (crypto.subtle). Vercel Edge is the supported target for this file. For Cloudflare, use the Cloudflare Worker; for other stacks, see Custom integration.