@publish.os/nextjs 0.0.1-alpha.90 → 0.0.1-alpha.92

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.
Files changed (284) hide show
  1. package/compiler-assets/nextjs/defaults/group/index.tsx +16 -11
  2. package/compiler-assets/nextjs/defaults/group/layout.tsx +6 -6
  3. package/compiler-assets/nextjs/defaults/group/page.tsx +36 -26
  4. package/compiler-assets/nextjs/defaults/project/next.config.mjs +21 -11
  5. package/compiler-assets/nextjs/defaults/project/tsconfig.json.template +10 -0
  6. package/compiler-assets/nextjs/defaults/root/css/components/code-block.css +18 -0
  7. package/compiler-assets/nextjs/defaults/root/index.tsx +16 -11
  8. package/compiler-assets/nextjs/defaults/root/layout.tsx +7 -3
  9. package/compiler-assets/nextjs/shims/agent-user-agents.ts +65 -0
  10. package/compiler-assets/nextjs/shims/document.tsx +46 -0
  11. package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +5 -0
  12. package/compiler-assets/nextjs/shims/global-layout.tsx +8 -42
  13. package/compiler-assets/nextjs/shims/global-not-found.tsx +69 -0
  14. package/compiler-assets/nextjs/shims/markdown-route.ts +2 -0
  15. package/compiler-assets/nextjs/shims/metadata-icons.tsx +39 -0
  16. package/compiler-assets/nextjs/shims/not-found-content.tsx +53 -0
  17. package/compiler-assets/nextjs/shims/not-found-navigation.tsx +60 -0
  18. package/compiler-assets/nextjs/shims/proxy.ts +254 -86
  19. package/compiler-assets/nextjs/shims/site-fenced-code-block.tsx +2 -6
  20. package/compiler-assets/nextjs/shims/site-mdx-components.tsx +28 -16
  21. package/compiler-assets/nextjs/shims/site-mdx.tsx +6 -1
  22. package/dist/{build-operation-2JAYBSKF.js → build-operation-CJDUL4OW.js} +29 -23
  23. package/dist/{button-c3WGnxIj.d.ts → button-D6Xp2HBm.d.ts} +4 -4
  24. package/dist/capture-local-source-WGGDIUU2.js +258 -0
  25. package/dist/chunk-22RSSUNV.js +13 -0
  26. package/dist/chunk-3T4HVDSC.js +426 -0
  27. package/dist/{chunk-WKTEO6RS.js → chunk-4BC2L2KA.js} +46 -12
  28. package/dist/{chunk-WDY4IK6Z.js → chunk-5J3YUNRY.js} +3 -10
  29. package/dist/chunk-5KAD7W53.js +248 -0
  30. package/dist/{chunk-DWA3ZRGW.js → chunk-6C65KV7O.js} +2 -2
  31. package/dist/{chunk-GGKFQ3MA.js → chunk-6D2E6UMD.js} +144 -70
  32. package/dist/{chunk-7OGTPSKI.js → chunk-7NY22B5U.js} +8 -3
  33. package/dist/chunk-DX7PXFCM.js +2519 -0
  34. package/dist/{chunk-726GV2NF.js → chunk-DZ3VWEV5.js} +950 -632
  35. package/dist/chunk-EFO6AWXN.js +19 -0
  36. package/dist/chunk-IL4RJOKI.js +186 -0
  37. package/dist/{chunk-H6XILMZX.js → chunk-NHSLTARU.js} +2588 -1493
  38. package/dist/{chunk-DLDFHU7Y.js → chunk-NNBJZPFM.js} +4 -2
  39. package/dist/{chunk-VO2I7MTM.js → chunk-SBMDONTV.js} +10 -7
  40. package/dist/{chunk-YLTOLYWM.js → chunk-WL75GQ5M.js} +6 -18
  41. package/dist/compiler.d.ts +15 -2
  42. package/dist/compiler.js +111 -23
  43. package/dist/components/blocks/agent-actions.d.ts +81 -0
  44. package/dist/components/blocks/agent-actions.js +563 -0
  45. package/dist/components/blocks/toc.d.ts +43 -0
  46. package/dist/components/blocks/toc.js +136 -0
  47. package/dist/components/ui/button.d.ts +4 -0
  48. package/dist/components/ui/button.js +94 -0
  49. package/dist/compose-44GJSMXD.js +16 -0
  50. package/dist/config/createNextConfig.js +19 -3
  51. package/dist/{dev-operation-TZDVJCN7.js → dev-operation-WNECBHZ5.js} +134 -84
  52. package/dist/{framework-selection-X4U6Y6QC.js → framework-selection-ZVO323PK.js} +3 -2
  53. package/dist/ide-support-TG74L4FF.js +16 -0
  54. package/dist/index.d.ts +151 -95
  55. package/dist/index.js +25 -0
  56. package/dist/jsx-dev-runtime.d.ts +6 -0
  57. package/dist/jsx-dev-runtime.js +100 -0
  58. package/dist/jsx-runtime.d.ts +7 -0
  59. package/dist/jsx-runtime.js +97 -0
  60. package/dist/kernel/components/blocks/AgentActions.d.ts +37 -8
  61. package/dist/kernel/components/blocks/AgentActions.js +384 -174
  62. package/dist/kernel/components/blocks/agent-actions.d.ts +4 -0
  63. package/dist/kernel/components/blocks/agent-actions.js +563 -0
  64. package/dist/kernel/components/blocks/animated-icon-swap.d.ts +2 -2
  65. package/dist/kernel/components/blocks/animated-icon-swap.js +1 -1
  66. package/dist/kernel/components/blocks/color-palette.d.ts +2 -2
  67. package/dist/kernel/components/blocks/color-palette.js +4 -4
  68. package/dist/kernel/components/blocks/logo-block.d.ts +2 -2
  69. package/dist/kernel/components/blocks/logo-block.js +1 -1
  70. package/dist/kernel/components/blocks/nav-breadcrumb.d.ts +6 -5
  71. package/dist/kernel/components/blocks/nav-breadcrumb.js +21 -15
  72. package/dist/kernel/components/blocks/navbar.d.ts +5 -4
  73. package/dist/kernel/components/blocks/navbar.js +79 -59
  74. package/dist/kernel/components/blocks/navigation-progress.d.ts +2 -2
  75. package/dist/kernel/components/blocks/navigation-progress.js +2 -2
  76. package/dist/kernel/components/blocks/next-prev.d.ts +4 -4
  77. package/dist/kernel/components/blocks/next-prev.js +30 -7
  78. package/dist/kernel/components/blocks/page-list.d.ts +4 -4
  79. package/dist/kernel/components/blocks/page-list.js +32 -9
  80. package/dist/kernel/components/blocks/search.d.ts +9 -15
  81. package/dist/kernel/components/blocks/search.js +16 -17
  82. package/dist/kernel/components/blocks/sidebar-node.d.ts +3 -5
  83. package/dist/kernel/components/blocks/sidebar-node.js +13 -3
  84. package/dist/kernel/components/blocks/sidebar.d.ts +6 -7
  85. package/dist/kernel/components/blocks/sidebar.js +137 -28
  86. package/dist/kernel/components/blocks/theme-toggle.d.ts +3 -4
  87. package/dist/kernel/components/blocks/theme-toggle.js +5 -5
  88. package/dist/kernel/components/blocks/toc-client.d.ts +40 -0
  89. package/dist/kernel/components/blocks/toc-client.js +495 -0
  90. package/dist/kernel/components/blocks/toc.d.ts +20 -2
  91. package/dist/kernel/components/blocks/toc.js +121 -179
  92. package/dist/kernel/components/mdx/components/blockquote.d.ts +2 -2
  93. package/dist/kernel/components/mdx/components/blockquote.js +1 -1
  94. package/dist/kernel/components/mdx/components/callout.d.ts +3 -3
  95. package/dist/kernel/components/mdx/components/callout.js +1 -1
  96. package/dist/kernel/components/mdx/components/code-block.d.ts +2 -2
  97. package/dist/kernel/components/mdx/components/code-block.js +2 -2
  98. package/dist/kernel/components/mdx/components/copy-code-button.d.ts +2 -2
  99. package/dist/kernel/components/mdx/components/copy-code-button.js +5 -4
  100. package/dist/kernel/components/mdx/components/figure-caption.d.ts +3 -3
  101. package/dist/kernel/components/mdx/components/figure-caption.js +3 -2
  102. package/dist/kernel/components/mdx/components/figure.d.ts +8 -4
  103. package/dist/kernel/components/mdx/components/figure.js +23 -13
  104. package/dist/kernel/components/mdx/components/footnotes.d.ts +2 -2
  105. package/dist/kernel/components/mdx/components/footnotes.js +1 -1
  106. package/dist/kernel/components/mdx/components/heading-copy-link.d.ts +2 -2
  107. package/dist/kernel/components/mdx/components/heading-copy-link.js +1 -1
  108. package/dist/kernel/components/mdx/components/heading.d.ts +2 -2
  109. package/dist/kernel/components/mdx/components/heading.js +6 -3
  110. package/dist/kernel/components/mdx/components/hr.d.ts +4 -4
  111. package/dist/kernel/components/mdx/components/hr.js +2 -2
  112. package/dist/kernel/components/mdx/components/image-zoom.d.ts +3 -3
  113. package/dist/kernel/components/mdx/components/image-zoom.js +4 -3
  114. package/dist/kernel/components/mdx/components/image.d.ts +2 -2
  115. package/dist/kernel/components/mdx/components/image.js +22 -17
  116. package/dist/kernel/components/mdx/components/inline-code.d.ts +2 -2
  117. package/dist/kernel/components/mdx/components/inline-code.js +1 -1
  118. package/dist/kernel/components/mdx/components/kbd.d.ts +3 -3
  119. package/dist/kernel/components/mdx/components/kbd.js +2 -2
  120. package/dist/kernel/components/mdx/components/link.d.ts +6 -6
  121. package/dist/kernel/components/mdx/components/link.js +2 -2
  122. package/dist/kernel/components/mdx/components/paragraph.d.ts +2 -2
  123. package/dist/kernel/components/mdx/components/paragraph.js +1 -1
  124. package/dist/kernel/components/mdx/components/strikethrough.d.ts +2 -2
  125. package/dist/kernel/components/mdx/components/strikethrough.js +1 -1
  126. package/dist/kernel/components/mdx/components/table.d.ts +7 -7
  127. package/dist/kernel/components/mdx/components/table.js +2 -2
  128. package/dist/kernel/components/mdx/components/task-list.d.ts +3 -3
  129. package/dist/kernel/components/mdx/components/task-list.js +1 -1
  130. package/dist/kernel/components/mdx/components/video-player.d.ts +8 -4
  131. package/dist/kernel/components/mdx/components/video-player.js +6 -2
  132. package/dist/kernel/components/mdx/components/video.d.ts +5 -4
  133. package/dist/kernel/components/mdx/components/video.js +7 -5
  134. package/dist/kernel/components/mdx/error-boundary.d.ts +3 -4
  135. package/dist/kernel/components/mdx/error-boundary.js +2 -2
  136. package/dist/kernel/components/mdx/error-fallback.d.ts +2 -2
  137. package/dist/kernel/components/mdx/error-fallback.js +1 -1
  138. package/dist/kernel/components/mdx/mdx.d.ts +57 -16
  139. package/dist/kernel/components/mdx/mdx.js +232 -35
  140. package/dist/kernel/components/mdx/rehype-heading-ids.d.ts +1 -0
  141. package/dist/kernel/components/mdx/rehype-heading-ids.js +5 -3
  142. package/dist/kernel/components/mdx/types.d.ts +1 -1
  143. package/dist/kernel/components/next-image.d.ts +12 -0
  144. package/dist/kernel/components/next-image.js +61 -0
  145. package/dist/kernel/components/ui/accordion.d.ts +7 -7
  146. package/dist/kernel/components/ui/accordion.js +1 -1
  147. package/dist/kernel/components/ui/breadcrumb-trail.d.ts +3 -4
  148. package/dist/kernel/components/ui/breadcrumb-trail.js +2 -2
  149. package/dist/kernel/components/ui/breadcrumb.d.ts +14 -14
  150. package/dist/kernel/components/ui/breadcrumb.js +4 -4
  151. package/dist/kernel/components/ui/button-group.d.ts +6 -6
  152. package/dist/kernel/components/ui/button-group.js +3 -3
  153. package/dist/kernel/components/ui/button.d.ts +59 -7
  154. package/dist/kernel/components/ui/button.js +43 -39
  155. package/dist/kernel/components/ui/card.d.ts +7 -7
  156. package/dist/kernel/components/ui/card.js +1 -1
  157. package/dist/kernel/components/ui/dialog.d.ts +10 -10
  158. package/dist/kernel/components/ui/dialog.js +1 -1
  159. package/dist/kernel/components/ui/drawer.d.ts +12 -12
  160. package/dist/kernel/components/ui/drawer.js +1 -1
  161. package/dist/kernel/components/ui/input.d.ts +2 -2
  162. package/dist/kernel/components/ui/input.js +1 -1
  163. package/dist/kernel/components/ui/kbd.d.ts +4 -4
  164. package/dist/kernel/components/ui/kbd.js +1 -1
  165. package/dist/kernel/components/ui/link.d.ts +11 -5
  166. package/dist/kernel/components/ui/link.js +2 -2
  167. package/dist/kernel/components/ui/menu.d.ts +22 -22
  168. package/dist/kernel/components/ui/menu.js +1 -1
  169. package/dist/kernel/components/ui/mod-key.d.ts +2 -3
  170. package/dist/kernel/components/ui/mod-key.js +2 -2
  171. package/dist/kernel/components/ui/navigation-menu.d.ts +15 -15
  172. package/dist/kernel/components/ui/navigation-menu.js +1 -1
  173. package/dist/kernel/components/ui/popover.d.ts +11 -11
  174. package/dist/kernel/components/ui/popover.js +1 -1
  175. package/dist/kernel/components/ui/progress.d.ts +7 -7
  176. package/dist/kernel/components/ui/progress.js +1 -1
  177. package/dist/kernel/components/ui/scroll-area.d.ts +9 -10
  178. package/dist/kernel/components/ui/scroll-area.js +1 -1
  179. package/dist/kernel/components/ui/select.d.ts +16 -16
  180. package/dist/kernel/components/ui/select.js +1 -1
  181. package/dist/kernel/components/ui/separator.d.ts +3 -3
  182. package/dist/kernel/components/ui/separator.js +1 -1
  183. package/dist/kernel/components/ui/table.d.ts +7 -7
  184. package/dist/kernel/components/ui/table.js +1 -1
  185. package/dist/kernel/components/ui/tabs.d.ts +12 -12
  186. package/dist/kernel/components/ui/tabs.js +1 -1
  187. package/dist/kernel/components/ui/tag.d.ts +3 -3
  188. package/dist/kernel/components/ui/tag.js +1 -1
  189. package/dist/kernel/components/ui/text.d.ts +4 -4
  190. package/dist/kernel/components/ui/text.js +1 -1
  191. package/dist/kernel/components/ui/toast.d.ts +11 -11
  192. package/dist/kernel/components/ui/toast.js +1 -1
  193. package/dist/kernel/components/ui/tooltip.d.ts +9 -9
  194. package/dist/kernel/components/ui/tooltip.js +1 -1
  195. package/dist/kernel/defaults.registry.d.ts +4 -17
  196. package/dist/kernel/defaults.registry.js +4 -19
  197. package/dist/kernel/routes/agent/markdown.d.ts +7 -0
  198. package/dist/kernel/routes/agent/markdown.js +229 -54
  199. package/dist/kernel/routes/layouts/group.d.ts +1 -1
  200. package/dist/kernel/routes/layouts/group.js +5 -7
  201. package/dist/kernel/routes/metadata/feed.d.ts +1 -2
  202. package/dist/kernel/routes/metadata/feed.js +119 -88
  203. package/dist/kernel/routes/metadata/llms.d.ts +3 -23
  204. package/dist/kernel/routes/metadata/llms.js +2 -103
  205. package/dist/kernel/routes/metadata/og-image.js +1 -1
  206. package/dist/kernel/routes/metadata/robots.d.ts +5 -3
  207. package/dist/kernel/routes/metadata/robots.js +4 -25
  208. package/dist/kernel/routes/metadata/sitemap.d.ts +36 -3
  209. package/dist/kernel/routes/metadata/sitemap.js +277 -49
  210. package/dist/kernel/routes/not-found.d.ts +34 -0
  211. package/dist/kernel/routes/not-found.js +213 -0
  212. package/dist/kernel/routes/pages/group.d.ts +5 -5
  213. package/dist/kernel/routes/pages/group.js +11 -5
  214. package/dist/kernel/routes/pages/leaf.d.ts +38 -6
  215. package/dist/kernel/routes/pages/leaf.js +21 -12
  216. package/dist/kernel/routes/pages/root.d.ts +5 -5
  217. package/dist/kernel/routes/pages/root.js +21 -6
  218. package/dist/keyboard-shortcuts.d.ts +2 -2
  219. package/dist/keyboard-shortcuts.js +1 -1
  220. package/dist/manifest-types-CcVPH_jh.d.ts +83 -0
  221. package/dist/resolvers/manifest-resolver.d.ts +2 -2
  222. package/dist/resolvers/manifest-resolver.js +65 -35
  223. package/dist/route-metadata-og-image-BeKKFHg7.d.ts +58 -0
  224. package/dist/search.d.ts +2 -9
  225. package/dist/search.js +9 -16
  226. package/dist/sidebar-types-CMrMM0Nj.d.ts +105 -0
  227. package/dist/theme-scope.d.ts +2 -2
  228. package/dist/theme-scope.js +1 -1
  229. package/dist/types-BbqmOzLC.d.ts +168 -0
  230. package/dist/types-TjH1ek0X.d.ts +22 -0
  231. package/dist/types-sM2g9nW0.d.ts +12 -0
  232. package/dist/types.d.ts +117 -91
  233. package/dist/utils/heading-ids.js +30 -11
  234. package/dist/utils/toc-selection.d.ts +7 -0
  235. package/dist/utils/toc-selection.js +14 -0
  236. package/dist/validate-local-source-EN2GW4FR.js +16 -0
  237. package/dist/validate-publish-os-source-OEWQDB7B.js +14 -0
  238. package/init/seed/minimal/publish.os/assets/blog/hello-world.svg +13 -0
  239. package/init/seed/minimal/publish.os/assets/favicon.dark.svg +13 -0
  240. package/init/seed/minimal/publish.os/assets/favicon.svg +13 -0
  241. package/init/seed/minimal/publish.os/blog/content/hello-world.mdx +48 -0
  242. package/init/seed/minimal/publish.os/blog/content/series-a.mdx +11 -0
  243. package/init/seed/minimal/publish.os/blog/index.tsx +85 -0
  244. package/init/seed/minimal/publish.os/blog/layout.tsx +13 -0
  245. package/init/seed/minimal/publish.os/blog/page.tsx +91 -0
  246. package/init/seed/minimal/publish.os/components/blog/copy-link.tsx +64 -0
  247. package/init/seed/minimal/publish.os/components/blog/frontmatter.ts +41 -0
  248. package/init/seed/minimal/publish.os/docs/content/get-started.mdx +2 -3
  249. package/init/seed/minimal/publish.os/docs/content/groups.mdx +5 -6
  250. package/init/seed/minimal/publish.os/publish.os.config.json +17 -2
  251. package/init/seed/minimal/publish.os/theme.css +3 -3
  252. package/init/seed/minimal/seed.json +12 -4
  253. package/init/seed/scratch/publish.os/docs/content/get-started.mdx +1 -1
  254. package/init/seed/scratch/publish.os/publish.os.config.json +1 -1
  255. package/package.json +48 -23
  256. package/release/app/phosphor/package.json +4 -4
  257. package/release/app/phosphor/pnpm-lock.yaml.template +123 -184
  258. package/release/compiler/package.json +5 -3
  259. package/release/compiler/pnpm-lock.yaml.template +153 -183
  260. package/release/release.json +6 -6
  261. package/dist/button-CtzUJB8u.d.ts +0 -11
  262. package/dist/chunk-535TM4A5.js +0 -1455
  263. package/dist/chunk-B2V22WRT.js +0 -297
  264. package/dist/chunk-NECL5IBJ.js +0 -318
  265. package/dist/chunk-SVYGXXYR.js +0 -36
  266. package/dist/chunk-UF6ATARM.js +0 -1100
  267. package/dist/compose-NN23UJGC.js +0 -13
  268. package/dist/ide-support-ZNW7ODFY.js +0 -15
  269. package/dist/kernel/components/blocks/design-system-preview.d.ts +0 -61
  270. package/dist/kernel/components/blocks/design-system-preview.js +0 -667
  271. package/dist/kernel/components/blocks/link-playground.d.ts +0 -5
  272. package/dist/kernel/components/blocks/link-playground.js +0 -744
  273. package/dist/kernel/components/blocks/navigation-progress-playground.d.ts +0 -5
  274. package/dist/kernel/components/blocks/navigation-progress-playground.js +0 -629
  275. package/dist/kernel/components/ui/theme-toggle.d.ts +0 -24
  276. package/dist/kernel/components/ui/theme-toggle.js +0 -53
  277. package/dist/sidebar-types-DKpR27II.d.ts +0 -25
  278. package/dist/types-BzkZty3r.d.ts +0 -147
  279. package/dist/types-CJWRG05y.d.ts +0 -76
  280. package/dist/types-CUtrppxt.d.ts +0 -69
  281. package/dist/validate-local-source-XRL2Y7XE.js +0 -14
  282. package/dist/validate-publish-os-source-DAPZ4QGE.js +0 -12
  283. package/init/seed/minimal/publish.os/assets/favicon/favicon.dark.png +0 -0
  284. package/init/seed/minimal/publish.os/assets/favicon/favicon.png +0 -0
@@ -0,0 +1,39 @@
1
+ import { faviconsAndLogos } from "@source/.publishos/favicons-and-logos.generated";
2
+ import type { Metadata } from "next";
3
+
4
+ type GeneratedMetadataIcons = {
5
+ icon?: readonly {
6
+ media?: string;
7
+ sizes?: string;
8
+ type?: string;
9
+ url: string;
10
+ }[];
11
+ apple?: readonly {
12
+ sizes?: string;
13
+ type?: string;
14
+ url: string;
15
+ }[];
16
+ };
17
+
18
+ const generated = faviconsAndLogos.metadataIcons as GeneratedMetadataIcons;
19
+
20
+ export const metadataIcons = Object.keys(generated).length
21
+ ? ({
22
+ ...(generated.icon ? { icon: [...generated.icon] } : {}),
23
+ ...(generated.apple ? { apple: [...generated.apple] } : {}),
24
+ } satisfies Metadata["icons"])
25
+ : undefined;
26
+
27
+ /** Global errors bypass Next's layout metadata but use the same resolved icons. */
28
+ export function MetadataIcons() {
29
+ return (
30
+ <>
31
+ {metadataIcons?.icon?.map(({ url, ...attributes }) => (
32
+ <link href={url} key={url} rel="icon" {...attributes} />
33
+ ))}
34
+ {metadataIcons?.apple?.map(({ url, ...attributes }) => (
35
+ <link href={url} key={url} rel="apple-touch-icon" {...attributes} />
36
+ ))}
37
+ </>
38
+ );
39
+ }
@@ -0,0 +1,53 @@
1
+ import { Link } from "@components/ui/link";
2
+ import type { NotFoundScope } from "@publish.os/nextjs/kernel/routes/not-found";
3
+
4
+ export default function NotFoundContent({ scope }: { scope: NotFoundScope }) {
5
+ const sections = [
6
+ { title: "Recommendations", links: scope.recommendations },
7
+ { title: "For crawlers and agents", links: scope.indexes },
8
+ ];
9
+ return (
10
+ <section
11
+ className="mx-auto flex w-full max-w-xl flex-1 flex-col items-center justify-center px-6 py-16 font-main sm:px-8 sm:py-24"
12
+ data-publishos-not-found={scope.id}
13
+ >
14
+ <h1 className="text-center font-mono text-8xl leading-none font-medium tracking-tight text-foreground-1 sm:text-9xl">
15
+ 404<span className="sr-only"> — Page not found</span>
16
+ </h1>
17
+ <p className="mt-6 max-w-md text-center text-sm leading-6 text-pretty text-foreground-3">
18
+ This page does not exist. Please check the URL and try again.
19
+ </p>
20
+ <div className="mt-10 w-full space-y-8">
21
+ {sections.map(({ title, links }) =>
22
+ links.length ? (
23
+ <section aria-label={title} key={title}>
24
+ <h2 className="text-xs font-medium text-foreground-3">{title}</h2>
25
+ <ul className="mt-2 space-y-0">
26
+ {links.map((link) => (
27
+ <li className="flex items-baseline gap-3" key={link.href}>
28
+ <span
29
+ aria-hidden="true"
30
+ className="shrink-0 text-sm text-foreground-3"
31
+ >
32
+ -
33
+ </span>
34
+ <Link
35
+ className="inline-flex min-h-10 min-w-0 max-w-full items-center py-1 text-start wrap-anywhere"
36
+ href={link.href}
37
+ prefetch={false}
38
+ size="sm"
39
+ target="_self"
40
+ variant="link.inline"
41
+ >
42
+ {link.title}
43
+ </Link>
44
+ </li>
45
+ ))}
46
+ </ul>
47
+ </section>
48
+ ) : null,
49
+ )}
50
+ </div>
51
+ </section>
52
+ );
53
+ }
@@ -0,0 +1,60 @@
1
+ "use client";
2
+
3
+ import type { MouseEvent, ReactNode } from "react";
4
+
5
+ /** Next's routing-level error document has no app-router tree to navigate from. */
6
+ export default function NotFoundNavigation({
7
+ children,
8
+ }: {
9
+ children: ReactNode;
10
+ }) {
11
+ function navigate(event: MouseEvent<HTMLDivElement>) {
12
+ if (
13
+ event.defaultPrevented ||
14
+ event.button !== 0 ||
15
+ event.altKey ||
16
+ event.ctrlKey ||
17
+ event.metaKey ||
18
+ event.shiftKey
19
+ )
20
+ return;
21
+
22
+ const target = event.target as Node;
23
+ const element =
24
+ target.nodeType === 1 ? (target as Element) : target.parentElement;
25
+ const link = element?.closest<HTMLAnchorElement>("a[href]");
26
+ const view = event.currentTarget.ownerDocument.defaultView;
27
+ if (
28
+ !link ||
29
+ !view ||
30
+ link.hasAttribute("download") ||
31
+ (link.target && link.target !== "_self")
32
+ )
33
+ return;
34
+
35
+ let destination: URL;
36
+ try {
37
+ destination = new URL(link.href, view.location.href);
38
+ } catch {
39
+ return;
40
+ }
41
+ if (
42
+ !["http:", "https:"].includes(destination.protocol) ||
43
+ destination.origin !== view.location.origin ||
44
+ (destination.pathname === view.location.pathname &&
45
+ destination.search === view.location.search &&
46
+ destination.hash)
47
+ )
48
+ return;
49
+
50
+ event.preventDefault();
51
+ event.stopPropagation();
52
+ view.location.assign(destination.href);
53
+ }
54
+
55
+ return (
56
+ <div className="contents" onClickCapture={navigate}>
57
+ {children}
58
+ </div>
59
+ );
60
+ }
@@ -1,14 +1,19 @@
1
+ import { isMarkdownClient } from "@app/agent-user-agents";
2
+ import {
3
+ createNotFoundTextResponse,
4
+ resolveNotFoundScope,
5
+ } from "@publish.os/nextjs/kernel/routes/not-found";
1
6
  import { agentRouteConfig } from "@source/.publishos/agent-route-config.generated";
2
7
  import type { NextRequest } from "next/server";
3
8
  import { NextResponse } from "next/server";
4
9
 
5
- const AGENT_USER_AGENT_PATTERN =
6
- /\b(?:axios|got|node-fetch|undici|curl|wget|python-requests|httpx|aiohttp|claude-code|claudebot|claude|cursor|chatgpt|openai|perplexity|anthropic-ai)\b/i;
7
10
  const INTERNAL_MARKDOWN_PREFIX = "/__publishos/md";
8
11
  const FRAMEWORK_PREFIX = "__PUBLISHOS_FRAMEWORK_PREFIX__";
9
- const PUBLIC_FILE_PATTERN = /\.[a-z0-9]{1,12}$/i;
10
12
  const TEXT_METHODS = new Set(["GET", "HEAD"]);
11
13
  const PUBLIC_PATHS = new Set<string>(agentRouteConfig.publicPaths);
14
+ const MARKDOWN_PATHS = new Set<string>(agentRouteConfig.markdownPaths);
15
+ const OUTPUT_PATHS = new Set<string>(agentRouteConfig.outputPaths);
16
+ const NOT_FOUND_SCOPE_HEADER = "x-publishos-not-found-scope";
12
17
 
13
18
  function debugAgentRoute(
14
19
  event: string,
@@ -30,11 +35,15 @@ function normalizePagePath(pathname: string): string {
30
35
  return pathname.replace(/\/+$/, "");
31
36
  }
32
37
 
33
- function markdownRoutePath(pathname: string): string {
38
+ function markdownRoutePath(
39
+ pathname: string,
40
+ reason: "accept" | "extension",
41
+ ): string {
34
42
  const normalized = normalizePagePath(pathname);
35
- const pagePath = normalized.endsWith(".md")
36
- ? normalized.slice(0, -".md".length)
37
- : normalized;
43
+ const pagePath =
44
+ reason === "extension" && normalized.endsWith(".md")
45
+ ? normalized.slice(0, -".md".length)
46
+ : normalized;
38
47
  return pagePath === "/"
39
48
  ? INTERNAL_MARKDOWN_PREFIX
40
49
  : `${INTERNAL_MARKDOWN_PREFIX}${pagePath}`;
@@ -45,36 +54,21 @@ function markdownAlternatePath(pathname: string): string {
45
54
  if (normalized === "/") {
46
55
  return agentRouteConfig.discoveryLinks.sitemap ?? "/sitemap.md";
47
56
  }
48
- return normalized.endsWith(".md") ? normalized : `${normalized}.md`;
57
+ return `${normalized}.md`;
49
58
  }
50
59
 
51
- function markdownNotFoundBody(): string {
52
- const links = [
53
- agentRouteConfig.discoveryLinks.home
54
- ? `> Home: ${agentRouteConfig.discoveryLinks.home}`
55
- : undefined,
56
- agentRouteConfig.discoveryLinks.sitemap
57
- ? `> Sitemap: ${agentRouteConfig.discoveryLinks.sitemap}`
58
- : undefined,
59
- agentRouteConfig.discoveryLinks.llms
60
- ? `> LLMS index: ${agentRouteConfig.discoveryLinks.llms}`
61
- : undefined,
62
- ].filter((line): line is string => Boolean(line));
63
-
64
- return [
65
- "# Not found",
66
- "",
67
- ...links,
68
- "",
69
- "The requested Markdown page was not found.",
70
- "",
71
- ].join("\n");
60
+ function rootMarkdownSitemapPath(requestUrl: URL): string {
61
+ return new URL(
62
+ agentRouteConfig.discoveryLinks.sitemap ?? "/sitemap.md",
63
+ requestUrl,
64
+ ).pathname;
72
65
  }
73
66
 
74
67
  function explicitAcceptQuality(accept: string, mimeType: string): number {
75
- if (!accept) return 0;
68
+ if (!accept.trim()) return 1;
76
69
 
77
70
  const [targetType, targetSubtype] = mimeType.toLowerCase().split("/");
71
+ let bestSpecificity = -1;
78
72
  let bestQuality = 0;
79
73
 
80
74
  for (const entry of accept.split(",")) {
@@ -86,63 +80,131 @@ function explicitAcceptQuality(accept: string, mimeType: string): number {
86
80
  if (!rawType) continue;
87
81
 
88
82
  const [type, subtype] = rawType.split("/");
89
- if (type !== targetType || subtype !== targetSubtype) continue;
83
+ const specificity =
84
+ type === targetType && subtype === targetSubtype
85
+ ? 2
86
+ : type === targetType && subtype === "*"
87
+ ? 1
88
+ : type === "*" && subtype === "*"
89
+ ? 0
90
+ : -1;
91
+ if (specificity < 0) continue;
90
92
 
91
93
  let quality = 1;
92
94
  for (const param of rawParams) {
93
95
  const [key, value] = param.split("=").map((part) => part.trim());
94
96
  if (key !== "q") continue;
95
- const parsed = Number.parseFloat(value);
96
- quality = Number.isFinite(parsed) ? parsed : 0;
97
+ const parsed = Number(value);
98
+ quality =
99
+ Number.isFinite(parsed) && parsed >= 0 && parsed <= 1 ? parsed : 0;
97
100
  }
98
101
 
99
- if (quality > bestQuality) bestQuality = quality;
102
+ if (specificity > bestSpecificity) {
103
+ bestSpecificity = specificity;
104
+ bestQuality = quality;
105
+ } else if (specificity === bestSpecificity) {
106
+ bestQuality = Math.max(bestQuality, quality);
107
+ }
100
108
  }
101
109
 
102
110
  return bestQuality;
103
111
  }
104
112
 
105
- function wantsMarkdown(request: NextRequest): boolean {
113
+ function negotiatedTextType(
114
+ request: NextRequest,
115
+ ): "text/markdown; charset=utf-8" | "text/html; charset=utf-8" | undefined {
116
+ const accept = request.headers.get("accept") ?? "";
117
+ const markdownQuality = agentRouteConfig.markdownAccept
118
+ ? explicitAcceptQuality(accept, "text/markdown")
119
+ : 0;
120
+ const htmlQuality = explicitAcceptQuality(accept, "text/html");
121
+
122
+ if (markdownQuality === 0 && htmlQuality === 0) return undefined;
123
+ if (markdownQuality > htmlQuality) return "text/markdown; charset=utf-8";
124
+ if (markdownQuality < htmlQuality) return "text/html; charset=utf-8";
125
+ if (looksLikeAgent(request)) return "text/markdown; charset=utf-8";
126
+ return htmlQuality > 0 && markdownQuality > 0
127
+ ? "text/html; charset=utf-8"
128
+ : undefined;
129
+ }
130
+
131
+ function negotiatedPlainNotFound(request: NextRequest): boolean {
106
132
  if (!TEXT_METHODS.has(request.method)) return false;
107
133
 
108
134
  const accept = request.headers.get("accept") ?? "";
135
+ const plainQuality = explicitAcceptQuality(accept, "text/plain");
109
136
  const markdownQuality = agentRouteConfig.markdownAccept
110
137
  ? explicitAcceptQuality(accept, "text/markdown")
111
138
  : 0;
112
- const plainQuality = agentRouteConfig.plainTextAccept
113
- ? explicitAcceptQuality(accept, "text/plain")
114
- : 0;
115
139
  const htmlQuality = explicitAcceptQuality(accept, "text/html");
116
140
 
117
- if (markdownQuality > 0 && markdownQuality >= htmlQuality) return true;
118
- if (plainQuality > 0 && htmlQuality === 0 && markdownQuality === 0) {
119
- return true;
120
- }
141
+ return plainQuality > Math.max(markdownQuality, htmlQuality);
142
+ }
121
143
 
122
- return false;
144
+ function removeDisabledDiscoveryHeaders(response: Response): Response {
145
+ if (!agentRouteConfig.enabled || !agentRouteConfig.discoveryHeaders) {
146
+ for (const name of ["link", "x-publishos-llms", "x-publishos-sitemap"])
147
+ response.headers.delete(name);
148
+ }
149
+ return response;
123
150
  }
124
151
 
125
152
  function looksLikeAgent(request: NextRequest): boolean {
126
153
  if (!TEXT_METHODS.has(request.method)) return false;
127
154
  if (!agentRouteConfig.agentDetection) return false;
128
- if (explicitAcceptQuality(request.headers.get("accept") ?? "", "text/html")) {
129
- return false;
155
+ return isMarkdownClient(request.headers.get("user-agent") ?? "");
156
+ }
157
+
158
+ function mergeVary(response: Response, values: string[]): void {
159
+ const existing = (response.headers.get("vary") ?? "")
160
+ .split(",")
161
+ .map((value) => value.trim())
162
+ .filter(Boolean);
163
+ if (existing.some((value) => value === "*")) return;
164
+ const merged = [...existing];
165
+ for (const value of values) {
166
+ if (!merged.some((item) => item.toLowerCase() === value.toLowerCase()))
167
+ merged.push(value);
130
168
  }
131
- return AGENT_USER_AGENT_PATTERN.test(request.headers.get("user-agent") ?? "");
169
+ if (merged.length) response.headers.set("vary", merged.join(", "));
170
+ }
171
+
172
+ function negotiationVary(): string[] {
173
+ if (!agentRouteConfig.enabled || !agentRouteConfig.markdownAccept) return [];
174
+ return ["Accept", ...(agentRouteConfig.agentDetection ? ["User-Agent"] : [])];
175
+ }
176
+
177
+ function isNextNavigationRequest(request: NextRequest): boolean {
178
+ return [
179
+ "rsc",
180
+ "next-router-prefetch",
181
+ "next-router-state-tree",
182
+ "next-router-segment-prefetch",
183
+ ].some((name) => request.headers.has(name));
132
184
  }
133
185
 
134
186
  function markdownRequestReason(
135
187
  request: NextRequest,
136
- ): "accept" | "agent" | "extension" | undefined {
188
+ ): "accept" | "extension" | undefined {
137
189
  if (!agentRouteConfig.enabled) return undefined;
190
+ if (!TEXT_METHODS.has(request.method) || isNextNavigationRequest(request))
191
+ return undefined;
138
192
  if (
139
193
  agentRouteConfig.markdownRoutes &&
140
194
  request.nextUrl.pathname.endsWith(".md")
141
195
  ) {
142
- return "extension";
196
+ let decoded: string;
197
+ try {
198
+ decoded = normalizePagePath(
199
+ decodeURIComponent(request.nextUrl.pathname),
200
+ ).normalize("NFC");
201
+ } catch {
202
+ decoded = request.nextUrl.pathname;
203
+ }
204
+ if (!PUBLIC_PATHS.has(decoded)) return "extension";
143
205
  }
144
- if (wantsMarkdown(request)) return "accept";
145
- if (looksLikeAgent(request)) return "agent";
206
+ const selectedType = negotiatedTextType(request);
207
+ if (selectedType === "text/markdown; charset=utf-8") return "accept";
146
208
  return undefined;
147
209
  }
148
210
 
@@ -154,6 +216,7 @@ function isInternalMarkdownRoute(pathname: string): boolean {
154
216
  }
155
217
 
156
218
  function isStaticOrMetadataRoute(pathname: string): boolean {
219
+ if (OUTPUT_PATHS.has(normalizePagePath(pathname))) return true;
157
220
  if (
158
221
  pathname === FRAMEWORK_PREFIX ||
159
222
  pathname.startsWith(`${FRAMEWORK_PREFIX}/`) ||
@@ -175,21 +238,29 @@ function isStaticOrMetadataRoute(pathname: string): boolean {
175
238
  return true;
176
239
  }
177
240
 
178
- return PUBLIC_FILE_PATTERN.test(pathname) && !pathname.endsWith(".md");
241
+ return false;
179
242
  }
180
243
 
181
- function rewriteToMarkdown(
182
- request: NextRequest,
183
- reason: "accept" | "agent" | "extension",
184
- ): NextResponse {
185
- const url = request.nextUrl.clone();
244
+ function rewriteToMarkdown({
245
+ request,
246
+ reason,
247
+ requestHeaders,
248
+ }: {
249
+ request: NextRequest;
250
+ reason: "accept" | "extension";
251
+ requestHeaders: Headers;
252
+ }): NextResponse {
253
+ const url = new URL(request.url);
186
254
  url.pathname =
187
255
  normalizePagePath(url.pathname) === "/"
188
- ? "/sitemap.md"
189
- : markdownRoutePath(url.pathname);
256
+ ? rootMarkdownSitemapPath(url)
257
+ : markdownRoutePath(url.pathname, reason);
258
+ const revision = request.nextUrl.searchParams.get("publishos_revision");
259
+ url.search = "";
260
+ url.hash = "";
261
+ if (revision) url.searchParams.set("publishos_revision", revision);
190
262
 
191
- const requestHeaders = new Headers(request.headers);
192
- requestHeaders.set("x-publishos-agent-route", "markdown");
263
+ requestHeaders.set("accept", "text/markdown");
193
264
 
194
265
  debugAgentRoute("md", {
195
266
  accept: request.headers.get("accept") ?? undefined,
@@ -200,20 +271,25 @@ function rewriteToMarkdown(
200
271
  userAgent: request.headers.get("user-agent") ?? undefined,
201
272
  });
202
273
 
203
- return NextResponse.rewrite(url, {
274
+ const response = NextResponse.rewrite(url, {
204
275
  request: {
205
276
  headers: requestHeaders,
206
277
  },
207
278
  });
279
+ if (reason !== "extension") mergeVary(response, negotiationVary());
280
+ return response;
208
281
  }
209
282
 
210
283
  function withDiscoveryHeaders(
211
284
  response: NextResponse,
212
285
  pathname: string,
213
286
  ): NextResponse {
287
+ mergeVary(response, negotiationVary());
214
288
  const markdownUrl = markdownAlternatePath(pathname);
215
289
  const links = [
216
- `<${markdownUrl}>; rel="alternate"; type="text/markdown"`,
290
+ agentRouteConfig.markdownRoutes
291
+ ? `<${markdownUrl}>; rel="alternate"; type="text/markdown"`
292
+ : undefined,
217
293
  agentRouteConfig.discoveryLinks.llms
218
294
  ? `<${agentRouteConfig.discoveryLinks.llms}>; rel="llms-txt"; type="text/plain"`
219
295
  : undefined,
@@ -221,8 +297,9 @@ function withDiscoveryHeaders(
221
297
  ? `<${agentRouteConfig.discoveryLinks.sitemap}>; rel="alternate"; type="text/markdown"; title="Markdown sitemap"`
222
298
  : undefined,
223
299
  ].filter((link): link is string => Boolean(link));
224
- response.headers.set("link", links.join(", "));
225
- response.headers.set("x-publishos-markdown", markdownUrl);
300
+ if (links.length) response.headers.set("link", links.join(", "));
301
+ if (agentRouteConfig.markdownRoutes)
302
+ response.headers.set("x-publishos-markdown", markdownUrl);
226
303
  if (agentRouteConfig.discoveryLinks.llms) {
227
304
  response.headers.set(
228
305
  "x-publishos-llms",
@@ -241,20 +318,28 @@ function withDiscoveryHeaders(
241
318
 
242
319
  export function proxy(request: NextRequest) {
243
320
  const { pathname } = request.nextUrl;
321
+ const requestHeaders = new Headers(request.headers);
322
+ requestHeaders.delete(NOT_FOUND_SCOPE_HEADER);
323
+ requestHeaders.delete("x-publishos-agent-route");
244
324
 
245
- if (pathname === "/_not-found") return NextResponse.next();
325
+ if (pathname === "/_not-found") {
326
+ requestHeaders.set(NOT_FOUND_SCOPE_HEADER, "none");
327
+ const response = NextResponse.next({
328
+ request: { headers: requestHeaders },
329
+ });
330
+ response.headers.set("x-robots-tag", "noindex");
331
+ response.headers.set("vary", "Accept, User-Agent");
332
+ return response;
333
+ }
246
334
 
247
335
  if (isInternalMarkdownRoute(pathname)) {
248
- if (request.headers.get("x-publishos-agent-route") === "markdown") {
249
- return NextResponse.next();
250
- }
251
336
  if (!agentRouteConfig.blockInternalMarkdownRoute) {
252
337
  debugAgentRoute("pass", {
253
338
  method: request.method,
254
339
  path: pathname,
255
340
  reason: "allowed-internal",
256
341
  });
257
- return NextResponse.next();
342
+ return NextResponse.next({ request: { headers: requestHeaders } });
258
343
  }
259
344
 
260
345
  debugAgentRoute("md", {
@@ -264,15 +349,7 @@ export function proxy(request: NextRequest) {
264
349
  status: 404,
265
350
  });
266
351
 
267
- return new Response(markdownNotFoundBody(), {
268
- status: 404,
269
- headers: {
270
- "cache-control": "public, max-age=60, s-maxage=300",
271
- "content-type": "text/markdown; charset=utf-8",
272
- "x-content-type-options": "nosniff",
273
- "x-robots-tag": "noindex",
274
- },
275
- });
352
+ return createNotFoundTextResponse({ method: request.method });
276
353
  }
277
354
 
278
355
  if (isStaticOrMetadataRoute(pathname)) {
@@ -281,25 +358,109 @@ export function proxy(request: NextRequest) {
281
358
  path: pathname,
282
359
  reason: "static-or-metadata",
283
360
  });
284
- return NextResponse.next();
361
+ return NextResponse.next({ request: { headers: requestHeaders } });
285
362
  }
286
363
 
287
364
  const markdownReason = markdownRequestReason(request);
288
365
  if (markdownReason) {
289
- return rewriteToMarkdown(request, markdownReason);
366
+ let htmlPath: string | undefined;
367
+ try {
368
+ const decoded = normalizePagePath(decodeURIComponent(pathname)).normalize(
369
+ "NFC",
370
+ );
371
+ htmlPath =
372
+ markdownReason === "extension" && decoded.endsWith(".md")
373
+ ? decoded.slice(0, -3) || "/"
374
+ : decoded;
375
+ } catch {
376
+ htmlPath = undefined;
377
+ }
378
+ const scope = resolveNotFoundScope({
379
+ scopes: agentRouteConfig.notFoundScopes,
380
+ pathname,
381
+ });
382
+ const hasArtifact =
383
+ htmlPath === "/"
384
+ ? OUTPUT_PATHS.has(rootMarkdownSitemapPath(new URL(request.url)))
385
+ : htmlPath !== undefined && MARKDOWN_PATHS.has(htmlPath);
386
+ if (!scope || !hasArtifact) {
387
+ const response = createNotFoundTextResponse({
388
+ scope,
389
+ pathname,
390
+ method: request.method,
391
+ contentType:
392
+ markdownReason === "accept" ? negotiatedTextType(request) : undefined,
393
+ vary: markdownReason !== "extension",
394
+ });
395
+ return removeDisabledDiscoveryHeaders(response);
396
+ }
397
+ return rewriteToMarkdown({
398
+ request,
399
+ reason: markdownReason,
400
+ requestHeaders,
401
+ });
290
402
  }
291
403
 
292
404
  let pagePath: string;
293
405
  try {
294
- pagePath = normalizePagePath(decodeURIComponent(pathname));
406
+ pagePath = normalizePagePath(decodeURIComponent(pathname)).normalize("NFC");
295
407
  } catch {
296
408
  pagePath = pathname;
297
409
  }
298
410
  if (!PUBLIC_PATHS.has(pagePath)) {
299
- // Use Next's static 404 before an unknown catch-all reaches error recovery.
300
- const url = request.nextUrl.clone();
411
+ // Select Next's error route before an unknown catch-all can stream.
412
+ const scope = resolveNotFoundScope({
413
+ scopes: agentRouteConfig.notFoundScopes,
414
+ pathname,
415
+ });
416
+ if (negotiatedPlainNotFound(request)) {
417
+ return removeDisabledDiscoveryHeaders(
418
+ createNotFoundTextResponse({
419
+ scope,
420
+ pathname,
421
+ method: request.method,
422
+ contentType: "text/plain; charset=utf-8",
423
+ vary: true,
424
+ }),
425
+ );
426
+ }
427
+ requestHeaders.set(NOT_FOUND_SCOPE_HEADER, scope?.id ?? "none");
428
+ const url = new URL(request.url);
301
429
  url.pathname = "/_not-found";
302
- return NextResponse.rewrite(url, { status: 404 });
430
+ url.search = "";
431
+ url.hash = "";
432
+ const response = NextResponse.rewrite(url, {
433
+ status: 404,
434
+ request: { headers: requestHeaders },
435
+ });
436
+ const recoveryHeaders = createNotFoundTextResponse({
437
+ scope,
438
+ pathname,
439
+ method: request.method,
440
+ vary: true,
441
+ }).headers;
442
+ for (const name of [
443
+ "x-robots-tag",
444
+ "vary",
445
+ ...(agentRouteConfig.enabled && agentRouteConfig.discoveryHeaders
446
+ ? ["link", "x-publishos-llms", "x-publishos-sitemap"]
447
+ : []),
448
+ ]) {
449
+ const value = recoveryHeaders.get(name);
450
+ if (value) response.headers.set(name, value);
451
+ }
452
+ return response;
453
+ }
454
+
455
+ if (
456
+ agentRouteConfig.enabled &&
457
+ TEXT_METHODS.has(request.method) &&
458
+ !isNextNavigationRequest(request) &&
459
+ !negotiatedTextType(request)
460
+ ) {
461
+ const response = new NextResponse(null, { status: 406 });
462
+ mergeVary(response, negotiationVary());
463
+ return response;
303
464
  }
304
465
 
305
466
  if (!agentRouteConfig.enabled || !agentRouteConfig.discoveryHeaders) {
@@ -310,7 +471,11 @@ export function proxy(request: NextRequest) {
310
471
  ? "discovery-disabled"
311
472
  : "agent-routes-disabled",
312
473
  });
313
- return NextResponse.next();
474
+ const response = NextResponse.next({
475
+ request: { headers: requestHeaders },
476
+ });
477
+ mergeVary(response, negotiationVary());
478
+ return response;
314
479
  }
315
480
 
316
481
  debugAgentRoute("html", {
@@ -321,7 +486,10 @@ export function proxy(request: NextRequest) {
321
486
  userAgent: request.headers.get("user-agent") ?? undefined,
322
487
  });
323
488
 
324
- return withDiscoveryHeaders(NextResponse.next(), pathname);
489
+ return withDiscoveryHeaders(
490
+ NextResponse.next({ request: { headers: requestHeaders } }),
491
+ pathname,
492
+ );
325
493
  }
326
494
 
327
495
  export const config = {
@@ -1,9 +1,5 @@
1
1
  import { CodeBlock } from "@components/mdx/code-block";
2
- import {
3
- type ComponentPropsWithoutRef,
4
- isValidElement,
5
- type ReactNode,
6
- } from "react";
2
+ import { type HTMLAttributes, isValidElement, type ReactNode } from "react";
7
3
 
8
4
  type CodeChildProps = {
9
5
  children?: ReactNode;
@@ -15,7 +11,7 @@ export function FencedCodeBlock({
15
11
  children,
16
12
  title,
17
13
  ...props
18
- }: ComponentPropsWithoutRef<"pre">) {
14
+ }: HTMLAttributes<HTMLElement>) {
19
15
  const codeElement = isValidElement<CodeChildProps>(children)
20
16
  ? children
21
17
  : null;