Content Negotiation

Product, collection, and search pages serve structured markdown to AI agents via Accept header content negotiation.

Content Negotiation

Product, collection, and search pages serve structured markdown when clients send Accept: text/markdown. Browsers continue to receive HTML; AI agents and crawlers get clean, parseable markdown from the same URL.

This is a built-in feature that requires no configuration.

How it works

GET /products/speaker        (Accept: text/markdown)
GET /collections/speakers    (Accept: text/markdown)
GET /search?q=speaker        (Accept: text/markdown)
    ↓
next.config.ts rewrite
    ↓
/products/md/[handle]
/collections/md/[handle]
/search/md
    ↓
Route handler response: text/markdown

Browsers that don't send Accept: text/markdown are unaffected — the rewrite only fires when the header matches.

Testing

bash
# Returns structured markdown
curl -H "Accept: text/markdown" http://localhost:3000/products/speaker

# Returns collection markdown with products, filters, and pagination
curl -H "Accept: text/markdown" http://localhost:3000/collections/speakers

# Returns search markdown with query, filters, and result summaries
curl -H "Accept: text/markdown" "http://localhost:3000/search?q=speaker&sort=price-low-to-high"

# Returns the normal HTML page
curl http://localhost:3000/products/speaker

The Vary: Accept header ensures CDNs cache markdown and HTML responses separately.

What's included in the markdown

The markdown representation includes:

  • Product pages — handle, brand, category, pricing, options, variants, specs, images, tags, and SEO metadata
  • Collection pages — collection metadata, description, applied filters, available filters, products, pagination, image, and SEO metadata
  • Search pages — query metadata, active collection filter, applied filters, available filters, products, and pagination state

Key files

FilePurpose
next.config.tsRewrite rules matching Accept: text/markdown
app/products/md/[handle]/route.tsProduct markdown route handler
app/collections/md/[handle]/route.tsCollection markdown route handler
app/search/md/route.tsSearch markdown route handler
lib/markdown/product.tsproductToMarkdown() converter
lib/markdown/collection.tscollectionToMarkdown() converter
lib/markdown/search.tssearchResultsToMarkdown() converter
lib/markdown/catalog.tsShared product/filter/pagination formatting helpers
lib/markdown/utils.tsFormatting helpers (prices, tables, escaping)

Multi-locale

If you have enabled Shopify Markets, the rewrite fires before locale routing — no additional configuration is needed. Pass a ?locale= query parameter to the markdown endpoint for locale-specific pricing and collection/search context.

Chat

Tip: You can open and close chat with I

0 / 1000