fix: respect explicit Accept: text/html from AI bot user agents#70
fix: respect explicit Accept: text/html from AI bot user agents#70abhay-codes07 wants to merge 1 commit into
Conversation
Per AEO spec section 5, UA-based markdown negotiation must not override an explicit Accept. Every edge and framework adapter served the markdown twin for any known bot UA, even when the request asked for Accept: text/html, so a crawler sending a bot UA plus Accept: text/html received text/markdown with X-Robots-Tag: noindex on the canonical URL. Add shouldServeMarkdown(accept, isBot) to @dualmark/core and use it in the cloudflare, deno, fastly, netlify, nextjs, sveltekit, vercel and nuxt adapters. A bot UA now stays on HTML when it explicitly requests text/html, while Accept: */*, no Accept, and Accept: text/markdown are unchanged.
|
@abhay-codes07 is attempting to deploy a commit to the Dodo Payments Team on Vercel. A member of the Team first needs to authorize it. |
|
@dodo-squirrels review |
Review: looks good, approving the approachI reviewed the change end-to-end and it's well-implemented and correct. Core logic — Edge cases verified:
Consistency — all 8 edge/framework adapters (cloudflare, deno, fastly, netlify, nextjs, nuxt ×2, sveltekit, vercel) were updated identically and each passes the raw Versioning — changeset is appropriate: Validation — checked out the branch and ran the suites locally:
No changes required. LGTM. |
Summary
Bot user agents currently get the markdown twin even when they explicitly ask for
Accept: text/html. The AEO spec says the opposite should happen, so this fixes the adapters to honor an explicit Accept while keeping the existing bot behavior for everything else.Closes #69.
Changes
shouldServeMarkdown(accept, isBot)to@dualmark/core. It serves markdown when RFC 7231 negotiation already picks markdown, or when the request is from a known bot and markdown is at least as acceptable as HTML. It checks the second case by negotiating with markdown listed first, so a tie (wildcard or empty Accept) resolves to markdown for bots, while an explicitAccept: text/htmlkeeps the bot on HTML.bot.isBot || fmt === "markdown"check that ignored the Accept header for bots.GPTBot/1.0UA withAccept: text/htmlnow receives HTML, not a noindex markdown body.@dualmark/core.Behavior is unchanged for
Accept: */*, noAccept, andAccept: text/markdown, so the existing conformance scores and bot handling stay the same.Type
AEO_SPEC_VERSION)Verification
bun run buildpassesbun run testpasses (541 tests across the packages)bun run typecheckpassesdualmark verifyagainst the example end-to-end (no examples touched)/spec/: ran sync-spec and committed the mirror (no spec files touched)Changeset
@dualmark/coreminor, adapters patch)cc @thepushkaraj @aagarwal1012 for a look when you have a minute(file change might look scary but indeed needed have a look). Happy to adjust the approach if you would rather keep the decision logic inside each adapter instead of a shared core helper.