diff --git a/AI_AGENT_DEVELOPER_GUIDE.md b/AI_AGENT_DEVELOPER_GUIDE.md index 661a655d87..466d9323be 100644 --- a/AI_AGENT_DEVELOPER_GUIDE.md +++ b/AI_AGENT_DEVELOPER_GUIDE.md @@ -212,6 +212,68 @@ When working on this project: --- +## Production Configuration for Agent Readiness + +### Content Negotiation (text/markdown) + +Every page — including the homepage — generates a markdown version at `{path}index.html.md` +(e.g. `/develop/index.html.md`). The `` element is +already present in every page's `` (generated by Hugo's `AlternativeOutputFormats` loop +in `baseof.html`). + +To enable HTTP-level content negotiation so `Accept: text/markdown` returns the markdown file +with `Content-Type: text/markdown`, configure nginx as follows: + +```nginx +# Honour q-values: match only when text/markdown appears without q=0. +# This is still a heuristic — full RFC 7231 q-value parsing requires Lua +# or a compiled module. For most clients this is sufficient. +map $http_accept $use_markdown { + "~*text/markdown(?!;q=0)" 1; + default 0; +} + +server { + # Declare the .md extension → MIME mapping so the type is set from the + # types table, not via add_header (which can't override Content-Type on + # files nginx serves directly). + types { + text/markdown md; + } + default_type application/octet-stream; + + # .html.md files served directly: MIME comes from the types block above. + # add_header always ensures Vary is sent on error responses too. + location ~ \.html\.md$ { + add_header Vary "Accept" always; + } + + location / { + add_header Vary "Accept" always; + + # Content negotiation: rewrite to .html.md when Accept: text/markdown. + # The first rewrite handles trailing-slash paths (/develop/). + # The second handles slash-terminated paths without a dot segment. + # Paths containing a dot (e.g. index.html, version dirs like 7.4/) + # are intentionally left to try_files so they resolve normally. + if ($use_markdown) { + rewrite ^(.*/)$ $1index.html.md last; + rewrite ^(/[^.]*[^/])$ $1/index.html.md last; + } + + try_files $uri $uri/ =404; + } +} +``` + +**`hugo serve` note:** The `[server]` config in `config.toml` sets `Vary: Accept` and the +correct `Content-Type` for `.html.md` files during local development, but it does **not** +perform Accept-based rewriting. Requesting a page with `Accept: text/markdown` against +`hugo serve` still returns HTML. Full content negotiation requires the nginx config above +(or equivalent CDN rules) in production. + +--- + **Last Updated**: 2026-01-08 **Purpose**: Help AI agents discover and understand Redis documentation architecture diff --git a/config.toml b/config.toml index 2752ff5264..0d62ccc8ec 100644 --- a/config.toml +++ b/config.toml @@ -123,5 +123,21 @@ rdi_current_version = "1.18.1" # Comment out if you don't want the "print entire section" link enabled. [outputs] +home = ["HTML", "RSS", "Markdown", "JSON"] section = ["HTML", "RSS", "Markdown", "JSON"] -page = ["HTML", "Markdown", "JSON"] \ No newline at end of file +page = ["HTML", "Markdown", "JSON"] + +# Content negotiation headers (hugo serve only). +# For production nginx config see AI_AGENT_DEVELOPER_GUIDE.md. +# Must be at end of file — TOML [table] sections apply to all following keys. +[server] + [[server.headers]] + for = "/**" + [server.headers.values] + Vary = "Accept" + + [[server.headers]] + for = "**.html.md" + [server.headers.values] + Content-Type = "text/markdown; charset=utf-8" + Vary = "Accept" \ No newline at end of file