@caprail-dev/agent-pages 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,21 +1,15 @@
1
1
  # @caprail-dev/agent-pages
2
2
 
3
3
  Markdown-first pages for AI agents in Next.js: co-locate a `page.md` next to
4
- each `page.tsx` and serve it to AI crawlers and fetchers automatically
4
+ each `page.tsx` and serve it via `Accept`-header content negotiation
5
5
  plus generated `/llms.txt` and `/llms-full.txt`.
6
6
 
7
- Real agent traffic (ClaudeBot, GPTBot, Claude Code, …) mostly does **not**
8
- send `Accept: text/markdown`, so Accept-header-only negotiation misses it.
9
- This package decides per request, in order:
10
-
11
- 1. **Accept q-values** `text/markdown` listed with `q > 0` and ≥ HTML;
12
- 2. **User-agent classification** (via [`@caprail-dev/analytics`](https://www.npmjs.com/package/@caprail-dev/analytics)) — AI
13
- crawlers/fetchers get markdown; search bots and agentic browsers keep
14
- HTML (serving indexers different content is cloaking);
15
- 3. **`Signature-Agent` header** (RFC 9421) — signed agents get markdown even
16
- with a browser-like UA;
17
- 4. **Heuristic fallback** — no `sec-fetch-mode` (real browsers always send
18
- it) + a bot-like UA, except search/link-preview bots that need the HTML.
7
+ A `GET`/`HEAD` request is served the markdown twin when its `Accept` header
8
+ lists `text/markdown` with `q > 0` and at least as strongly as `text/html`
9
+ (a bare `*/*` is not a preference — browsers send it). Everything else gets
10
+ HTML. A negotiated response `Vary`s on `Accept` so caches key the two
11
+ representations separately. A direct `.md` URL (`/terms.md`) and the
12
+ `/llms.txt` / `/llms-full.txt` aggregates are served unconditionally.
19
13
 
20
14
  ## Install
21
15
 
@@ -32,7 +26,7 @@ npm i @caprail-dev/agent-pages # or bun add / pnpm add / yarn add
32
26
  import { withAgentPages } from "@caprail-dev/agent-pages/config";
33
27
 
34
28
  export default withAgentPages(nextConfig, {
35
- siteUrl: "https://example.com",
29
+ siteUrl: process.env.BASE_URL ?? "http://localhost:3000"
36
30
  });
37
31
  ```
38
32
 
@@ -54,48 +48,89 @@ description: One-liner shown in /llms.txt.
54
48
  # Example — the markdown twin
55
49
  ```
56
50
 
57
- **3. Add the middleware:**
51
+ **3. Add the middleware** — spread the generated `AGENT_PAGES` bundle straight
52
+ into the helper. The file is `proxy.ts` (Next's current naming;
53
+ `middleware.ts` on older Next), exporting `proxy` / `middleware` respectively:
58
54
 
59
55
  ```ts
60
- // middleware.ts
56
+ // proxy.ts
61
57
  import { createAgentPagesMiddleware } from "@caprail-dev/agent-pages/next";
62
- import { MD_REWRITES } from "@/app/_agent-pages/rewrites";
58
+ import { AGENT_PAGES } from "@/app/_agent-pages/manifest";
63
59
 
64
- export const middleware = createAgentPagesMiddleware({ rewrites: MD_REWRITES });
60
+ export const proxy = createAgentPagesMiddleware({ ...AGENT_PAGES });
65
61
  export const config = {
66
62
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
67
63
  };
68
64
  ```
69
65
 
70
- Apps with existing middleware compose via the decision object instead:
66
+ The helper serves every doc *inline* from the manifest a direct `.md` URL
67
+ (`/terms.md`), an HTML page whose twin an agent wants as markdown (`/terms`),
68
+ and the `/llms.txt` / `/llms-full.txt` aggregates — and HTML (with `Vary`)
69
+ otherwise.
70
+
71
+ ### Composing with analytics or other middleware
72
+
73
+ `observe` runs developer-provided middleware for its side effects alongside
74
+ serving. It's any Next-middleware-shaped function — analytics, a logger, a
75
+ feature-flag tap — and its return value is ignored (the helper owns the
76
+ response). Each observer receives the request whose pathname is *what was
77
+ actually served* (the `.md` twin on the markdown branch), so a beacon records
78
+ the served path without you cloning the URL by hand:
79
+
80
+ ```ts
81
+ import { createAgentPagesMiddleware } from "@caprail-dev/agent-pages/next";
82
+ import { createCaprailMiddleware } from "@caprail-dev/analytics/next";
83
+ import { AGENT_PAGES } from "@/app/_agent-pages/manifest";
84
+
85
+ export const proxy = createAgentPagesMiddleware({
86
+ ...AGENT_PAGES,
87
+ observe: createCaprailMiddleware(), // or [collector, logger, …]
88
+ });
89
+ ```
90
+
91
+ ### Composing with a routing middleware (next-intl, …)
92
+
93
+ `observe` is for middleware that only watches. A **routing** middleware like
94
+ next-intl's `createMiddleware(routing)` *owns the response* (locale
95
+ redirect/rewrite, `NEXT_LOCALE` cookie), so it goes in the `html` slot — it
96
+ runs instead of `NextResponse.next()` on the HTML branch:
71
97
 
72
98
  ```ts
73
- import { decideAgentPages } from "@caprail-dev/agent-pages/next";
74
- import { MD_REWRITES } from "@/app/_agent-pages/rewrites";
75
-
76
- export function middleware(req: NextRequest) {
77
- const d = decideAgentPages(req, MD_REWRITES);
78
- // d.kind is "rewrite" or "html"; d.response has Vary set correctly.
79
- return d.response;
80
- }
99
+ import { createAgentPagesMiddleware } from "@caprail-dev/agent-pages/next";
100
+ import { createCaprailMiddleware } from "@caprail-dev/analytics/next";
101
+ import createMiddleware from "next-intl/middleware";
102
+ import { routing } from "@/i18n/routing";
103
+ import { AGENT_PAGES } from "@/app/_agent-pages/manifest";
104
+
105
+ export const proxy = createAgentPagesMiddleware({
106
+ ...AGENT_PAGES,
107
+ observe: createCaprailMiddleware(), // side effects (analytics, logging)
108
+ html: createMiddleware(routing), // owns the HTML response (i18n routing)
109
+ });
81
110
  ```
82
111
 
112
+ Agent-pages decides **first**, on the unprefixed path, so AI agents get the one
113
+ canonical markdown twin while humans fall through to localized HTML — a router
114
+ that rewrites `/terms` → `/en/terms` never hides a twin. The negotiation `Vary`
115
+ is *appended* to the router's response, so its own `Vary` / `Link` survive.
116
+
117
+ Need full control? Compose by hand with the `decideAgentPages` /
118
+ `serveAgentPages` primitives — `createAgentPagesMiddleware` is just their
119
+ batteries-included form.
120
+
83
121
  ## What gets generated
84
122
 
85
- Inside your app dir (commit these — deterministic output keeps diffs
123
+ A single file inside your app dir (commit it — deterministic output keeps diffs
86
124
  meaningful and shows exactly what agents will read):
87
125
 
88
- - `_agent-pages/rewrites.ts` — HTML path markdown twin record. Edge-safe
89
- strings only; the **only** file the middleware imports.
90
- - `_agent-pages/manifest.ts` full doc registry (content inlined). Imported
91
- only by route handlers; never reaches the edge bundle.
92
- - `<path>.md/route.ts` per `page.md` `force-static` markdown routes.
93
- - `llms.txt/route.ts` + `llms-full.txt/route.ts` (disable with
94
- `llms: { enabled: false }`).
126
+ - `_agent-pages/manifest.ts` — the full doc registry with each `page.md`'s
127
+ content inlined. Exports `AGENT_DOCS` (the docs), `SITE_URL` / `LLMS_INTRO`,
128
+ and the `AGENT_PAGES` bundle (`{ docs, llms }`) you spread into the
129
+ middleware. There are **no** per-page `.md` route handlers and no separate
130
+ rewrites file everything is served inline from this manifest.
95
131
 
96
- Every generated file is marker-headed; the codegen **refuses to overwrite**
97
- files without the marker and cleans up generated files whose `page.md` was
98
- deleted.
132
+ The file is marker-headed; the codegen **refuses to overwrite** a manifest
133
+ without the marker and removes generated entries whose `page.md` was deleted.
99
134
 
100
135
  ## Options
101
136
 
@@ -104,7 +139,6 @@ withAgentPages(nextConfig, {
104
139
  siteUrl: "https://example.com",
105
140
  appDir: "src/app", // default: src/app, else app
106
141
  llms: {
107
- enabled: true, // default
108
142
  intro: "# Example\n\n> …", // /llms.txt preamble before "## Docs"
109
143
  },
110
144
  extraDocs: [
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,0EAA0E;AAC1E,MAAM,MAAM,QAAQ,GAAG;IACrB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf;;mCAE+B;IAC/B,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,kFAAkF;IAClF,IAAI,EAAE,KAAK,CAAC;QACV,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,gDAAgD;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AA6KF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,cAAc,CAgGxE"}
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAcH,0EAA0E;AAC1E,MAAM,MAAM,QAAQ,GAAG;IACrB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf;;mCAE+B;IAC/B,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,kFAAkF;IAClF,IAAI,EAAE,KAAK,CAAC;QACV,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,gDAAgD;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAwLF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,cAAc,CAgGxE"}
package/dist/codegen.js CHANGED
@@ -14,6 +14,7 @@
14
14
  import fs from "node:fs";
15
15
  import path from "node:path";
16
16
  import { parseFrontmatter } from "./frontmatter.js";
17
+ import { mdxToMarkdownTwin } from "./mdx-twin.js";
17
18
  /** First line of every generated file — the overwrite/cleanup sentinel. */
18
19
  const MARKER = "// @generated by @caprail-dev/agent-pages";
19
20
  const HEADER = `${MARKER} — do not edit; regenerated on every \`next dev\`/\`next build\`.
@@ -35,10 +36,12 @@ function scan(appDir) {
35
36
  const abs = path.join(dir, entry.name);
36
37
  if (entry.isDirectory()) {
37
38
  if (entry.name.includes("[")) {
38
- const pageMd = path.join(abs, "page.md");
39
- if (fs.existsSync(pageMd)) {
40
- console.warn(`[agent-pages] skipping ${rel(pageMd)}: dynamic segments are unsupported in v1`);
41
- skipped.push(rel(pageMd));
39
+ for (const name of ["page.md", "page.mdx"]) {
40
+ const page = path.join(abs, name);
41
+ if (fs.existsSync(page)) {
42
+ console.warn(`[agent-pages] skipping ${rel(page)}: dynamic segments are unsupported in v1`);
43
+ skipped.push(rel(page));
44
+ }
42
45
  }
43
46
  continue;
44
47
  }
@@ -60,7 +63,7 @@ function scan(appDir) {
60
63
  path.basename(dir) === "llms-full.txt")) {
61
64
  candidates.push(abs);
62
65
  }
63
- if (entry.name !== "page.md")
66
+ if (entry.name !== "page.md" && entry.name !== "page.mdx")
64
67
  continue;
65
68
  const htmlPath = "/" + segments.join("/");
66
69
  const mdPath = htmlPath === "/" ? "/index.md" : `${htmlPath}.md`;
@@ -71,7 +74,9 @@ function scan(appDir) {
71
74
  mdPath,
72
75
  title: fm.title || mdPath,
73
76
  description: fm.description,
74
- markdown: fm.body,
77
+ // A page.mdx is the HTML page itself (compiled by @next/mdx); its
78
+ // markdown twin is derived by stripping ESM/JSX.
79
+ markdown: entry.name === "page.mdx" ? mdxToMarkdownTwin(fm, rel(abs)) : fm.body,
75
80
  });
76
81
  }
77
82
  };
@@ -139,6 +144,12 @@ ${fit("", "export const LLMS_INTRO =", quote(intro), ";")}
139
144
  export const AGENT_DOCS: AgentDoc[] = [
140
145
  ${entries}
141
146
  ];
147
+
148
+ /** Spread straight into \`createAgentPagesMiddleware\` / \`decideAgentPages\`. */
149
+ export const AGENT_PAGES = {
150
+ docs: AGENT_DOCS,
151
+ llms: { siteUrl: SITE_URL, intro: LLMS_INTRO },
152
+ };
142
153
  `;
143
154
  }
144
155
  export function generateAgentPages(opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * `next.config.js` wrapper: runs codegen when the config is evaluated (every
3
3
  * `next dev` start and `next build` — plain Node, no bundler hooks, so it is
4
- * Turbopack-safe by construction) and, in dev, watches for `page.md` changes.
4
+ * Turbopack-safe by construction) and, in dev, watches for `page.md`/`page.mdx`
5
+ * changes.
5
6
  *
6
7
  * Note for fresh clones: this module is consumed from the package's compiled
7
8
  * `dist/` — build the package before running bare `next dev`/`next build`.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;2DACuD;IACvD,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AAYF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,UAAU,EAAE,CAAC,EACb,IAAI,EAAE,iBAAiB,GACtB,CAAC,CAuCH"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;2DACuD;IACvD,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AAYF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,UAAU,EAAE,CAAC,EACb,IAAI,EAAE,iBAAiB,GACtB,CAAC,CA6CH"}
package/dist/config.js CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * `next.config.js` wrapper: runs codegen when the config is evaluated (every
3
3
  * `next dev` start and `next build` — plain Node, no bundler hooks, so it is
4
- * Turbopack-safe by construction) and, in dev, watches for `page.md` changes.
4
+ * Turbopack-safe by construction) and, in dev, watches for `page.md`/`page.mdx`
5
+ * changes.
5
6
  *
6
7
  * Note for fresh clones: this module is consumed from the package's compiled
7
8
  * `dist/` — build the package before running bare `next dev`/`next build`.
@@ -39,8 +40,11 @@ export function withAgentPages(nextConfig, opts) {
39
40
  slots[WATCHER_KEY] = true;
40
41
  let timer;
41
42
  const watcher = fs.watch(appDir, { recursive: true }, (_event, filename) => {
42
- if (!filename || path.basename(filename) !== "page.md")
43
+ if (!filename ||
44
+ (path.basename(filename) !== "page.md" &&
45
+ path.basename(filename) !== "page.mdx")) {
43
46
  return;
47
+ }
44
48
  clearTimeout(timer);
45
49
  timer = setTimeout(() => {
46
50
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,kBAAkB,GAGnB,MAAM,cAAc,CAAC;AAatB,iFAAiF;AACjF,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAEnE,SAAS,MAAM,CAAC,MAAsB;IACpC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IAC9E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAa,EACb,IAAuB;IAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,GAAG,EAAE,CACf,kBAAkB,CAAC;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IAEL,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAEd,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,UAAqC,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;YAC1B,IAAI,KAAiC,CAAC;YACtC,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CACtB,MAAM,EACN,EAAE,SAAS,EAAE,IAAI,EAAE,EACnB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;gBACnB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,SAAS;oBAAE,OAAO;gBAC/D,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACtB,IAAI,CAAC;wBACH,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;oBAChB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,oEAAoE;wBACpE,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;oBACtD,CAAC;gBACH,CAAC,EAAE,GAAG,CAAC,CAAC;gBACR,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC,CACF,CAAC;YACF,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,kBAAkB,GAGnB,MAAM,cAAc,CAAC;AAatB,iFAAiF;AACjF,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAEnE,SAAS,MAAM,CAAC,MAAsB;IACpC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IAC9E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAa,EACb,IAAuB;IAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,GAAG,EAAE,CACf,kBAAkB,CAAC;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IAEL,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAEd,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,UAAqC,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;YAC1B,IAAI,KAAiC,CAAC;YACtC,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CACtB,MAAM,EACN,EAAE,SAAS,EAAE,IAAI,EAAE,EACnB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;gBACnB,IACE,CAAC,QAAQ;oBACT,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,SAAS;wBACpC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC,EACzC,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACtB,IAAI,CAAC;wBACH,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;oBAChB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,oEAAoE;wBACpE,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;oBACtD,CAAC;gBACH,CAAC,EAAE,GAAG,CAAC,CAAC;gBACR,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC,CACF,CAAC;YACF,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
package/dist/core.d.ts CHANGED
@@ -19,27 +19,13 @@ export declare function prefersMarkdown(accept: string | null): boolean;
19
19
  export type MarkdownRequest = {
20
20
  method: string;
21
21
  accept: string | null;
22
- userAgent: string | null;
23
- signatureAgent?: string | null;
24
- secFetchMode?: string | null;
25
22
  };
26
23
  /**
27
24
  * Whether this client should be served markdown instead of HTML (path-agnostic
28
- * — the caller decides the page has a markdown twin). Markdown wins when, in
29
- * order:
30
- *
31
- * 1. the client asks for it (`Accept: text/markdown`);
32
- * 2. the UA classifies as an AI crawler/fetcher — the consumers that want
33
- * markdown. `search` engines (Googlebot, Bingbot, OAI-SearchBot, …) are
34
- * excluded on purpose: serving indexers different content than humans is
35
- * cloaking. `browser` agents (ChatGPT Agent / Atlas) render real pages,
36
- * so they get HTML too — both verdicts are final and skip the heuristics;
37
- * 3. the request carries a `Signature-Agent` header (RFC 9421) — AI agents
38
- * that sign their requests (e.g. ChatGPT's) identify themselves this way
39
- * even when their UA looks like a plain browser;
40
- * 4. heuristic fallback for agents our classifier doesn't know yet: no
41
- * `sec-fetch-mode` header (real browsers always send it) and a bot-like
42
- * UA — except search/preview bots that need the HTML (see NEEDS_HTML).
25
+ * — the caller decides the page has a markdown twin). Markdown wins when the
26
+ * client asks for it: a `GET`/`HEAD` whose `Accept` header lists `text/markdown`
27
+ * at least as strongly as HTML (see `prefersMarkdown`). Everything else — every
28
+ * UA, signed or not gets HTML.
43
29
  */
44
30
  export declare function clientWantsMarkdown(input: MarkdownRequest): boolean;
45
31
  /**
@@ -52,11 +38,12 @@ export declare function resolveMarkdownRewrite(input: MarkdownRequest & {
52
38
  pathname: string;
53
39
  }, rewrites: MarkdownRewrites): string | null;
54
40
  /**
55
- * The negotiation headers every markdown-negotiated response varies on —
56
- * set on both the rewritten and the HTML branch of a negotiated path so
57
- * non-Vercel intermediaries cache them separately.
41
+ * The negotiation header every markdown-negotiated response varies on — set on
42
+ * both the rewritten and the HTML branch of a negotiated path so non-Vercel
43
+ * intermediaries cache the two representations separately. Negotiation keys
44
+ * solely off `Accept`.
58
45
  */
59
- export declare const AGENT_PAGES_VARY = "Accept, User-Agent, Signature-Agent, Sec-Fetch-Mode";
46
+ export declare const AGENT_PAGES_VARY = "Accept";
60
47
  /** One agent-readable doc — drives the rewrite map, llms.txt, and routes. */
61
48
  export type AgentDoc = {
62
49
  /** The HTML page this doc twins, or null when the doc is markdown-only. */
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CA4B9D;AAmBD,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAkBnE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC7C,QAAQ,EAAE,gBAAgB,GACzB,MAAM,GAAG,IAAI,CAQf;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,wDAC0B,CAAC;AAExD,6EAA6E;AAC7E,MAAM,MAAM,QAAQ,GAAG;IACrB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wDAAwD;AACxD,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC3B,GAAG,MAAM,CAQT;AAED,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAE7D;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAOvD"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CA4B9D;AAED,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAInE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC7C,QAAQ,EAAE,gBAAgB,GACzB,MAAM,GAAG,IAAI,CAQf;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,WAAW,CAAC;AAEzC,6EAA6E;AAC7E,MAAM,MAAM,QAAQ,GAAG;IACrB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wDAAwD;AACxD,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC3B,GAAG,MAAM,CAQT;AAED,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAE7D;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAOvD"}
package/dist/core.js CHANGED
@@ -6,7 +6,6 @@
6
6
  * Pure and edge-safe — no request objects, no Node APIs, just primitives —
7
7
  * so it is unit-testable and runs unchanged in the Edge runtime.
8
8
  */
9
- import { classify } from "@caprail-dev/analytics";
10
9
  /**
11
10
  * Whether the `Accept` header asks for markdown at least as strongly as HTML.
12
11
  * Minimal q-value parse: `text/markdown` must be listed explicitly (a bare
@@ -42,52 +41,17 @@ export function prefersMarkdown(accept) {
42
41
  }
43
42
  return qMd !== null && qMd > 0 && qMd >= qHtml;
44
43
  }
45
- /**
46
- * Bot-like UA pattern for the heuristic fallback: generic bot vocabulary plus
47
- * the HTTP client libraries agent frameworks ride on. Deliberately loose —
48
- * it only fires when `sec-fetch-mode` is also absent, and serving markdown
49
- * to a misjudged non-AI bot is low-harm.
50
- */
51
- const BOT_LIKE = /bot|crawler|spider|scraper|python-requests|python-httpx|aiohttp|go-http-client|node-fetch|axios|libwww/i;
52
- /**
53
- * Bot-like UAs that must keep getting HTML: search indexers our classifier
54
- * doesn't know (serving them markdown is cloaking) and link-preview bots
55
- * that read OpenGraph tags from the HTML head.
56
- */
57
- const NEEDS_HTML = /yandex|baidu|duckduckbot|applebot|seznambot|naver|sogou|petalbot|msnbot|slackbot|twitterbot|facebookexternalhit|facebot|discordbot|linkedinbot|whatsapp|telegrambot|pinterest|skypeuripreview|embedly|redditbot/i;
58
44
  /**
59
45
  * Whether this client should be served markdown instead of HTML (path-agnostic
60
- * — the caller decides the page has a markdown twin). Markdown wins when, in
61
- * order:
62
- *
63
- * 1. the client asks for it (`Accept: text/markdown`);
64
- * 2. the UA classifies as an AI crawler/fetcher — the consumers that want
65
- * markdown. `search` engines (Googlebot, Bingbot, OAI-SearchBot, …) are
66
- * excluded on purpose: serving indexers different content than humans is
67
- * cloaking. `browser` agents (ChatGPT Agent / Atlas) render real pages,
68
- * so they get HTML too — both verdicts are final and skip the heuristics;
69
- * 3. the request carries a `Signature-Agent` header (RFC 9421) — AI agents
70
- * that sign their requests (e.g. ChatGPT's) identify themselves this way
71
- * even when their UA looks like a plain browser;
72
- * 4. heuristic fallback for agents our classifier doesn't know yet: no
73
- * `sec-fetch-mode` header (real browsers always send it) and a bot-like
74
- * UA — except search/preview bots that need the HTML (see NEEDS_HTML).
46
+ * — the caller decides the page has a markdown twin). Markdown wins when the
47
+ * client asks for it: a `GET`/`HEAD` whose `Accept` header lists `text/markdown`
48
+ * at least as strongly as HTML (see `prefersMarkdown`). Everything else — every
49
+ * UA, signed or not gets HTML.
75
50
  */
76
51
  export function clientWantsMarkdown(input) {
77
52
  if (input.method !== "GET" && input.method !== "HEAD")
78
53
  return false;
79
- if (prefersMarkdown(input.accept))
80
- return true;
81
- const agent = classify(input.userAgent);
82
- if (agent.isAgent) {
83
- return agent.type === "fetcher" || agent.type === "crawler";
84
- }
85
- if (input.signatureAgent)
86
- return true;
87
- return (!input.secFetchMode &&
88
- !!input.userAgent &&
89
- BOT_LIKE.test(input.userAgent) &&
90
- !NEEDS_HTML.test(input.userAgent));
54
+ return prefersMarkdown(input.accept);
91
55
  }
92
56
  /**
93
57
  * Resolve the markdown rewrite target for a request, or null to serve the page
@@ -106,11 +70,12 @@ export function resolveMarkdownRewrite(input, rewrites) {
106
70
  return clientWantsMarkdown(input) ? target : null;
107
71
  }
108
72
  /**
109
- * The negotiation headers every markdown-negotiated response varies on —
110
- * set on both the rewritten and the HTML branch of a negotiated path so
111
- * non-Vercel intermediaries cache them separately.
73
+ * The negotiation header every markdown-negotiated response varies on — set on
74
+ * both the rewritten and the HTML branch of a negotiated path so non-Vercel
75
+ * intermediaries cache the two representations separately. Negotiation keys
76
+ * solely off `Accept`.
112
77
  */
113
- export const AGENT_PAGES_VARY = "Accept, User-Agent, Signature-Agent, Sec-Fetch-Mode";
78
+ export const AGENT_PAGES_VARY = "Accept";
114
79
  /** `/llms.txt` index per the llmstxt.org convention. */
115
80
  export function llmsTxt(opts) {
116
81
  const links = opts.docs
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,9 @@ export type Frontmatter = {
9
9
  description: string;
10
10
  /** The markdown with the frontmatter block (and leading blank lines) stripped. */
11
11
  body: string;
12
+ /** Every raw `key: value` pair from the block — extra keys (e.g. a blog's
13
+ * `publishedAt`, `tags`) are the caller's to interpret. */
14
+ fields: Record<string, string>;
12
15
  };
13
16
  /**
14
17
  * Parse a `page.md` file. Frontmatter is only recognized when the first line
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAcF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAwC7E"}
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAcF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAwC7E"}
@@ -53,6 +53,6 @@ export function parseFrontmatter(raw, sourcePath) {
53
53
  if (!description) {
54
54
  console.warn(`[agent-pages] ${sourcePath}: no "description" frontmatter — its /llms.txt entry will have no summary`);
55
55
  }
56
- return { title, description, body };
56
+ return { title, description, body, fields };
57
57
  }
58
58
  //# sourceMappingURL=frontmatter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,+EAA+E;AAC/E,SAAS,OAAO,CAAC,KAAa;IAC5B,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;QACjB,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EACzB,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,UAAkB;IAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,IAAI,GAAG,GAAG,CAAC;IAEf,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;QACzE,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,KAAK,KAAK,CAAC,CAAC;oBAAE,SAAS;gBAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACpD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC/B,CAAC;YACD,IAAI,GAAG,KAAK;iBACT,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;iBACd,IAAI,CAAC,IAAI,CAAC;iBACV,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CACV,iBAAiB,UAAU,wEAAwE,CACpG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CACV,iBAAiB,UAAU,2EAA2E,CACvG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,+EAA+E;AAC/E,SAAS,OAAO,CAAC,KAAa;IAC5B,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;QACjB,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EACzB,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,UAAkB;IAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,IAAI,GAAG,GAAG,CAAC;IAEf,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;QACzE,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,KAAK,KAAK,CAAC,CAAC;oBAAE,SAAS;gBAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACpD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC/B,CAAC;YACD,IAAI,GAAG,KAAK;iBACT,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;iBACd,IAAI,CAAC,IAAI,CAAC;iBACV,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CACV,iBAAiB,UAAU,wEAAwE,CACpG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CACV,iBAAiB,UAAU,2EAA2E,CACvG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Derive a plain-markdown twin from a `page.mdx` body. Zero deps, line-based:
3
+ * MDX is markdown plus ESM statements, JSX components, and `{expressions}` —
4
+ * the twin strips the first two and keeps everything else verbatim.
5
+ *
6
+ * Authoring convention this relies on (enforced here only loosely): components
7
+ * are presentational extras written as blank-line-delimited blocks with no
8
+ * internal blank lines, and the prose must stand alone without them. A JSX
9
+ * block that violates this leaves fragments in the twin — the codegen tests
10
+ * pin the supported shapes.
11
+ */
12
+ import type { Frontmatter } from "./frontmatter.js";
13
+ export declare function mdxToMarkdownTwin(fm: Frontmatter, sourcePath: string): string;
14
+ //# sourceMappingURL=mdx-twin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdx-twin.d.ts","sourceRoot":"","sources":["../src/mdx-twin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AASpD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA+C7E"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Derive a plain-markdown twin from a `page.mdx` body. Zero deps, line-based:
3
+ * MDX is markdown plus ESM statements, JSX components, and `{expressions}` —
4
+ * the twin strips the first two and keeps everything else verbatim.
5
+ *
6
+ * Authoring convention this relies on (enforced here only loosely): components
7
+ * are presentational extras written as blank-line-delimited blocks with no
8
+ * internal blank lines, and the prose must stand alone without them. A JSX
9
+ * block that violates this leaves fragments in the twin — the codegen tests
10
+ * pin the supported shapes.
11
+ */
12
+ const FENCE = /^(```|~~~)/;
13
+ const ESM_START = /^(import|export)\s/;
14
+ /** JSX flow block: an uppercase component tag opening at column 0. */
15
+ const JSX_START = /^<[A-Z]/;
16
+ /** Inline component tags — strip the tag, keep any children text. */
17
+ const INLINE_TAG = /<\/?[A-Z][\w.]*(\s[^>]*)?\/?>/g;
18
+ export function mdxToMarkdownTwin(fm, sourcePath) {
19
+ const lines = fm.body.split("\n");
20
+ const kept = [];
21
+ let inFence = false;
22
+ let skipUntilBlank = false;
23
+ for (const line of lines) {
24
+ if (inFence) {
25
+ kept.push(line);
26
+ if (FENCE.test(line))
27
+ inFence = false;
28
+ continue;
29
+ }
30
+ if (skipUntilBlank) {
31
+ if (line.trim() === "")
32
+ skipUntilBlank = false;
33
+ continue;
34
+ }
35
+ if (FENCE.test(line)) {
36
+ inFence = true;
37
+ kept.push(line);
38
+ continue;
39
+ }
40
+ if (ESM_START.test(line) || JSX_START.test(line)) {
41
+ skipUntilBlank = true;
42
+ continue;
43
+ }
44
+ kept.push(line.replace(INLINE_TAG, ""));
45
+ }
46
+ const body = kept
47
+ .join("\n")
48
+ .replace(/\n{3,}/g, "\n\n")
49
+ .replace(/^\n+/, "")
50
+ .replace(/\n+$/, "\n");
51
+ const publishedAt = fm.fields.publishedAt ?? "";
52
+ if (!publishedAt) {
53
+ throw new Error(`[agent-pages] ${sourcePath}: page.mdx needs a "publishedAt" frontmatter field (YYYY-MM-DD)`);
54
+ }
55
+ const tags = fm.fields.tags ?? "";
56
+ const meta = `_${publishedAt}${tags ? ` · ${tags}` : ""}_`;
57
+ // Posts do not write their own H1 (the HTML page renders one from the
58
+ // frontmatter); synthesize it here — unless the body defensively has one.
59
+ const heading = body.startsWith("# ") ? "" : `# ${fm.title}\n\n`;
60
+ return `${heading}${meta}\n\n${body}`;
61
+ }
62
+ //# sourceMappingURL=mdx-twin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdx-twin.js","sourceRoot":"","sources":["../src/mdx-twin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,KAAK,GAAG,YAAY,CAAC;AAC3B,MAAM,SAAS,GAAG,oBAAoB,CAAC;AACvC,sEAAsE;AACtE,MAAM,SAAS,GAAG,SAAS,CAAC;AAC5B,qEAAqE;AACrE,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD,MAAM,UAAU,iBAAiB,CAAC,EAAe,EAAE,UAAkB;IACnE,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO,GAAG,KAAK,CAAC;YACtC,SAAS;QACX,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,cAAc,GAAG,KAAK,CAAC;YAC/C,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,cAAc,GAAG,IAAI,CAAC;YACtB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,IAAI,GAAG,IAAI;SACd,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEzB,MAAM,WAAW,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iBAAiB,UAAU,iEAAiE,CAC7F,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IAE3D,sEAAsE;IACtE,0EAA0E;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IACjE,OAAO,GAAG,OAAO,GAAG,IAAI,OAAO,IAAI,EAAE,CAAC;AACxC,CAAC"}
package/dist/next.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * fly. The middleware therefore imports the manifest content; keep doc sets
12
12
  * reasonable (this is the trade for "author only `page.md`, no route files").
13
13
  */
14
- import { NextResponse, type NextRequest } from "next/server";
14
+ import { NextRequest, NextResponse, type NextFetchEvent } from "next/server";
15
15
  import { type AgentDoc } from "./core.js";
16
16
  export type AgentPagesDecision = {
17
17
  kind: "markdown";
@@ -50,9 +50,41 @@ export declare function decideAgentPages(req: NextRequest, docs: readonly AgentD
50
50
  export declare function serveAgentPages(decision: Extract<AgentPagesDecision, {
51
51
  kind: "markdown";
52
52
  }>): Response;
53
- /** Batteries-included middleware for apps with no other middleware work. */
53
+ /**
54
+ * A middleware run for its side effects (analytics, logging, a feature-flag
55
+ * tap, …) alongside agent-pages serving. It is any Next-middleware-shaped
56
+ * function — `createCaprailMiddleware()` is one example, but nothing here is
57
+ * analytics-specific. Its return value is ignored: the agent-pages middleware
58
+ * owns the final response.
59
+ */
60
+ export type AgentPagesObserver = (req: NextRequest, ev: NextFetchEvent) => unknown;
61
+ /**
62
+ * A middleware that *owns the response* for the HTML branch — run instead of
63
+ * `NextResponse.next()` when the request is not served markdown. This is the
64
+ * slot for a routing middleware like next-intl's `createMiddleware(routing)`
65
+ * (locale redirect/rewrite) or any middleware that produces the response.
66
+ * Returned headers are preserved; the negotiation `Vary` is appended, not set.
67
+ */
68
+ export type AgentPagesHtmlMiddleware = (req: NextRequest, ev: NextFetchEvent) => Response | NextResponse;
69
+ /**
70
+ * Batteries-included middleware: decide and serve markdown vs HTML, run
71
+ * developer-provided `observe` middleware for its side effects, and optionally
72
+ * hand the HTML branch off to an `html` routing middleware.
73
+ *
74
+ * - `observe` — side-effect middleware (analytics, logging). Each is called
75
+ * with the request whose pathname is *what was actually served* — the `.md`
76
+ * twin on the markdown branch, the request as-is otherwise — so a beacon
77
+ * records the served path without the caller cloning the URL. One or an array.
78
+ * - `html` — owns the response when markdown is *not* served. Use it to compose
79
+ * a routing middleware (e.g. next-intl). Defaults to `NextResponse.next()`.
80
+ *
81
+ * Agent-pages decides first, on the unprefixed path, so an `html` router that
82
+ * rewrites paths (e.g. `/terms` → `/en/terms`) never hides a markdown twin.
83
+ */
54
84
  export declare function createAgentPagesMiddleware(opts: {
55
85
  docs: readonly AgentDoc[];
56
86
  llms?: LlmsOption;
57
- }): (req: NextRequest) => Response | NextResponse;
87
+ observe?: AgentPagesObserver | readonly AgentPagesObserver[];
88
+ html?: AgentPagesHtmlMiddleware;
89
+ }): (req: NextRequest, ev: NextFetchEvent) => Response | NextResponse;
58
90
  //# sourceMappingURL=next.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,kBAAkB,GAC1B;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,UAAU,EAAE,OAAO,CAAC;CACrB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEN,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,GAC3B,kBAAkB,CAyDpB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,GAC1D,QAAQ,CAIV;AAED,4EAA4E;AAC5E,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,IACS,KAAK,WAAW,KAAG,QAAQ,GAAG,YAAY,CAOnD"}
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,kBAAkB,GAC1B;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,UAAU,EAAE,OAAO,CAAC;CACrB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEN,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,GAC3B,kBAAkB,CAsDpB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,GAC1D,QAAQ,CAIV;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,cAAc,KACf,OAAO,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,CACrC,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,cAAc,KACf,QAAQ,GAAG,YAAY,CAAC;AAE7B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,kBAAkB,EAAE,CAAC;IAC7D,IAAI,CAAC,EAAE,wBAAwB,CAAC;CACjC,IASS,KAAK,WAAW,EAAE,IAAI,cAAc,KAAG,QAAQ,GAAG,YAAY,CAsBvE"}
package/dist/next.js CHANGED
@@ -11,7 +11,7 @@
11
11
  * fly. The middleware therefore imports the manifest content; keep doc sets
12
12
  * reasonable (this is the trade for "author only `page.md`, no route files").
13
13
  */
14
- import { NextResponse } from "next/server";
14
+ import { NextRequest, NextResponse } from "next/server";
15
15
  import { AGENT_PAGES_VARY, clientWantsMarkdown, llmsFullTxt, llmsTxt, markdownResponse, } from "./core.js";
16
16
  /**
17
17
  * Decide what to serve for a request, sourcing content from the manifest docs:
@@ -60,9 +60,6 @@ export function decideAgentPages(req, docs, opts) {
60
60
  const wantsMarkdown = clientWantsMarkdown({
61
61
  method: req.method,
62
62
  accept: req.headers.get("accept"),
63
- userAgent: req.headers.get("user-agent"),
64
- signatureAgent: req.headers.get("signature-agent"),
65
- secFetchMode: req.headers.get("sec-fetch-mode"),
66
63
  });
67
64
  if (wantsMarkdown) {
68
65
  return {
@@ -86,15 +83,50 @@ export function serveAgentPages(decision) {
86
83
  res.headers.set("vary", AGENT_PAGES_VARY);
87
84
  return res;
88
85
  }
89
- /** Batteries-included middleware for apps with no other middleware work. */
86
+ /**
87
+ * Batteries-included middleware: decide and serve markdown vs HTML, run
88
+ * developer-provided `observe` middleware for its side effects, and optionally
89
+ * hand the HTML branch off to an `html` routing middleware.
90
+ *
91
+ * - `observe` — side-effect middleware (analytics, logging). Each is called
92
+ * with the request whose pathname is *what was actually served* — the `.md`
93
+ * twin on the markdown branch, the request as-is otherwise — so a beacon
94
+ * records the served path without the caller cloning the URL. One or an array.
95
+ * - `html` — owns the response when markdown is *not* served. Use it to compose
96
+ * a routing middleware (e.g. next-intl). Defaults to `NextResponse.next()`.
97
+ *
98
+ * Agent-pages decides first, on the unprefixed path, so an `html` router that
99
+ * rewrites paths (e.g. `/terms` → `/en/terms`) never hides a markdown twin.
100
+ */
90
101
  export function createAgentPagesMiddleware(opts) {
91
- return (req) => {
102
+ // `typeof` rather than `Array.isArray`: the latter narrows a readonly
103
+ // array union to `any[]`, losing the element type.
104
+ const observers = !opts.observe
105
+ ? []
106
+ : typeof opts.observe === "function"
107
+ ? [opts.observe]
108
+ : opts.observe;
109
+ return (req, ev) => {
92
110
  const decision = decideAgentPages(req, opts.docs, { llms: opts.llms });
93
- if (decision.kind === "markdown")
111
+ if (decision.kind === "markdown") {
112
+ if (observers.length) {
113
+ // Hand observers the served `.md` path, not the requested one, so a
114
+ // beacon grades this request as markdown.
115
+ const url = req.nextUrl.clone();
116
+ url.pathname = decision.mdPath;
117
+ const served = new NextRequest(url, { method: req.method });
118
+ for (const observe of observers)
119
+ observe(served, ev);
120
+ }
94
121
  return serveAgentPages(decision);
95
- const res = NextResponse.next();
122
+ }
123
+ for (const observe of observers)
124
+ observe(req, ev);
125
+ // The `html` middleware owns the response when set; otherwise pass through.
126
+ const res = opts.html ? opts.html(req, ev) : NextResponse.next();
127
+ // Append (don't set) so an `html` router's own Vary/Link survive.
96
128
  if (decision.negotiated)
97
- res.headers.set("vary", AGENT_PAGES_VARY);
129
+ res.headers.append("vary", AGENT_PAGES_VARY);
98
130
  return res;
99
131
  };
100
132
  }
package/dist/next.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@caprail-dev/agent-pages",
3
- "version": "0.2.0",
4
- "description": "Markdown-first pages for AI agents — co-located page.md twins served inline via UA-based content negotiation for Next.js.",
3
+ "version": "0.4.0",
4
+ "description": "Markdown-first pages for AI agents — co-located page.md twins served inline via Accept-header content negotiation for Next.js.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "license": "MIT",
@@ -23,6 +23,10 @@
23
23
  "./config": {
24
24
  "types": "./dist/config.d.ts",
25
25
  "default": "./dist/config.js"
26
+ },
27
+ "./frontmatter": {
28
+ "types": "./dist/frontmatter.d.ts",
29
+ "default": "./dist/frontmatter.js"
26
30
  }
27
31
  },
28
32
  "publishConfig": {
@@ -40,8 +44,5 @@
40
44
  "next": {
41
45
  "optional": true
42
46
  }
43
- },
44
- "dependencies": {
45
- "@caprail-dev/analytics": "^0.5.0"
46
47
  }
47
48
  }