Skip to content

feat(agent-readiness): Markdown for Agents — return markdown when Accept: text/markdown #3315

@koala73

Description

@koala73

Part of epic #3306.

Problem

Agents parse markdown far more reliably than they parse our rendered HTML (heavy JS, panels, ARIA). Cloudflare's Markdown for Agents spec describes the response-side contract: if the client sends Accept: text/markdown, return a markdown representation of the page with Content-Type: text/markdown. Browsers still get HTML.

Fix

Implement per-route Accept-based content negotiation for our HTML surfaces. For any route that returns HTML today:

  1. If the request has Accept: text/markdown (and that is higher priority than text/html), return a markdown rendering of the same logical content.
  2. Otherwise, default to HTML.
  3. Response MUST set Content-Type: text/markdown; charset=utf-8 on the markdown branch. If/when we tokenise, also emit x-markdown-tokens.
  4. Vary: Accept on all responses to prevent CDN cache poisoning.

Which routes are in scope

Home (/), country pages (/country/[iso] if those exist), /docs/*, /pro, /about. Panel-heavy dashboard routes probably return "dashboard overview + link to data API" rather than trying to serialise widgets to markdown — keep it informative, not mechanical.

Implementation

WorldMonitor ships as a Vite + hybrid app; there isn't a single server-rendered Next-style layout per route. Two realistic paths:

  1. Build-time markdown siblings. Generate a markdown version of each static route at build time (from the canonical source, e.g. MDX/CMS), then have middleware.ts rewrite the request to the .md sibling when Accept: text/markdown wins. Works today for static content; useless for panels.
  2. Edge function that fetches and converts. An edge fn that takes a URL, pulls the HTML, strips chrome, pipes through turndown or similar. Expensive per-request; consider caching.

Prefer (1) for docs / static pages, and for dynamic pages accept that the markdown branch might return a summary + "use the API (<catalog link>) for structured data" message instead of a full conversion.

Acceptance criteria

  • curl -H 'Accept: text/markdown' https://worldmonitor.app/ returns 200 with Content-Type: text/markdown and a sensible markdown body.
  • curl -H 'Accept: text/html' https://worldmonitor.app/ returns HTML as today.
  • Vary: Accept present on both.
  • isitagentready.com "Markdown for Agents" check passes.
  • No regression in homepage Lighthouse score (HTML branch unchanged).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium priority, schedule when capacity allowsagent-readinessAgent-discoverability standards (well-known, RFC 8288/9727/9728, WebMCP, x402, etc.)enhancementNew feature or requestplatform: webWeb/browser-specific

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions