
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Mon, 04 May 2026 09:03:03 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Introducing the Agent Readiness score. Is your site agent-ready?]]></title>
            <link>https://blog.cloudflare.com/agent-readiness/</link>
            <pubDate>Fri, 17 Apr 2026 13:05:00 GMT</pubDate>
            <description><![CDATA[ The Agent Readiness score can help site owners understand how well their websites support AI agents. Here we explore new standards, share Radar data, and detail how we made Cloudflare’s docs the most agent-friendly on the web. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>The web has always had to adapt to new standards. It learned to speak to web browsers, and then it learned to speak to search engines. Now, it needs to speak to AI agents.</p><p>Today, we are excited to introduce <a href="https://isitagentready.com/"><u>isitagentready.com</u></a> — a new tool to help site owners understand how they can make their sites optimized for agents, from guiding agents on how to authenticate, to controlling what content agents can see, the format they receive it in, and how they pay for it. We are also <a href="https://radar.cloudflare.com/ai-insights#adoption-of-ai-agent-standards"><u>introducing a new dataset to Cloudflare Radar</u></a> that tracks the overall adoption of each agent standard across the Internet.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/sGg5lZjafjQ398V7hYyMv/93e112a34754e2065ffbf6445ebc4500/unnamed.png" />
          </figure><p>We want to lead by example. That is why we are also sharing how we recently overhauled Cloudflare's <a href="https://developers.cloudflare.com/"><u>Developer Documentation</u></a> to make it the most agent-friendly documentation site, allowing AI tools to answer questions faster and significantly cheaper.</p>
    <div>
      <h2>How agent-ready is the web today?</h2>
      <a href="#how-agent-ready-is-the-web-today">
        
      </a>
    </div>
    <p>The short answer: not very. This is expected, but also shows how much more effective agents can be than they are today, if standards are adopted.</p><p>To analyze this, Cloudflare Radar took the 200,000 <a href="https://radar.cloudflare.com/domains"><u>most visited domains</u></a> on the Internet; filtered out categories where agent readiness isn't important (like redirects, ad-servers, and tunneling services) to focus on businesses, publishers, and platforms that AI agents might realistically need to interact with; and scanned them using our new tool.</p><p>The result is a new “Adoption of AI agent standards” chart that can now be found in the <a href="https://radar.cloudflare.com/ai-insights#adoption-of-ai-agent-standards"><u>Cloudflare Radar AI Insights</u></a> page where we can measure adoption of each standard across multiple domain categories.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/Vn8SoboYs4OmY2y6aXZke/c641d63cc71e4645e3b19c4124b5e912/image3.png" />
          </figure><p>Looking at individual checks, a few things stood out:</p><ul><li><p><a href="https://www.cloudflare.com/learning/bots/what-is-robots-txt/"><u>robots.txt</u></a> is nearly universal — 78% of sites have one — but the vast majority are written for traditional search engine crawlers, not AI agents.</p></li><li><p><a href="https://contentsignals.org/"><u>Content Signals</u></a>: 4% of sites have declared their AI usage preferences in robots.txt. This is a new standard that is gaining momentum.</p></li><li><p>Markdown content negotiation (serving text/markdown on Accept: text/markdown) passes on 3.9% of sites.</p></li><li><p>New emerging standards like <a href="https://modelcontextprotocol.io/community/server-card/charter"><u>MCP Server Cards</u></a> and <a href="https://datatracker.ietf.org/doc/rfc9727/"><u>API Catalogs (RFC 9727)</u></a> together appear on fewer than 15 sites in the entire dataset. It’s still early — there is lots of opportunity to stand out by being one of the first sites to adopt new standards and work well with agents. </p></li></ul><p>This chart will be updated weekly, and the data can also be accessed through the <a href="https://radar.cloudflare.com/explorer"><u>Data Explorer</u></a> or the <a href="https://developers.cloudflare.com/api/resources/radar/"><u>Radar API</u></a>.</p>
    <div>
      <h2>Get an agent readiness score for your site</h2>
      <a href="#get-an-agent-readiness-score-for-your-site">
        
      </a>
    </div>
    <p>You can get an agent readiness score for your own website by going to <a href="https://isitagentready.com/"><u>isitagentready.com</u></a> and entering the site’s URL.</p><p>Scores and audits that provide actionable feedback have helped to drive adoption of new standards before. For example, <a href="https://developer.chrome.com/docs/lighthouse/performance/performance-scoring"><u>Google Lighthouse</u></a> scores websites on performance and security best practices, and guides site owners to adopt the latest web platform standards. We think something similar should exist to help site owners adopt best practices for agents.</p><p>When you enter your site, Cloudflare makes requests to it to check which standards it supports, and provides a score based on four dimensions:</p><ul><li><p>Discoverability: <a href="https://datatracker.ietf.org/doc/html/rfc9309"><u>robots.txt</u></a>, <a href="https://www.sitemaps.org/protocol.html"><u>sitemap.xml</u></a>, <a href="https://datatracker.ietf.org/doc/html/rfc8288"><u>Link Headers (RFC 8288)</u></a></p></li><li><p>Content: <a href="https://blog.cloudflare.com/markdown-for-agents/"><u>Markdown for Agents</u></a></p></li><li><p>Bot Access Control: <a href="https://contentsignals.org/"><u>Content Signals</u></a>, <a href="https://developers.cloudflare.com/ai-crawl-control/"><u>AI bot rules in robots.txt</u></a>, <a href="https://datatracker.ietf.org/doc/draft-meunier-web-bot-auth-architecture/"><u>Web Bot Auth</u></a></p></li><li><p>Capabilities: <a href="https://github.com/cloudflare/agent-skills-discovery-rfc"><u>Agent Skills</u></a>, API Catalog <a href="https://www.rfc-editor.org/rfc/rfc9727"><u>(RFC 9727)</u></a>, OAuth server discovery via <a href="https://www.rfc-editor.org/rfc/rfc8414"><u>RFC 8414</u></a> and <a href="https://datatracker.ietf.org/doc/html/rfc9728"><u>RFC 9728</u></a>, <a href="https://modelcontextprotocol.io/community/server-card/charter"><u>MCP Server Card</u></a>, and <a href="https://developer.chrome.com/blog/webmcp-epp"><u>WebMCP</u></a></p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/69MdHcYAZi60gVKRVP9GFM/f3521831b2ca361e12a33f6c8eb05f5b/image9.png" />
          </figure><p><sup><i>Screenshot of results from an agent-readiness check for an example website.</i></sup></p><p>Additionally, we check if the site supports agentic commerce standards including <a href="https://www.x402.org/"><u>x402</u></a>, <a href="https://ucp.dev/"><u>Universal Commerce Protocol</u></a>, and <a href="https://www.agenticcommerce.dev/"><u>Agentic Commerce Protocol</u></a>, but these do not currently count towards the score.</p><p>For each failing check, we provide a prompt that you can give to your coding agent and have it implement support on your behalf.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/9C62LtqTLgvZGViVEh8n0/b9c01cebe9042ad4b458d4305b3db7b2/image6.png" />
          </figure><p>The site itself is also agent-ready, practicing what it preaches. It exposes a stateless MCP server (https://isitagentready.com/.well-known/mcp.json) with a <code>scan_site</code> tool via Streamable HTTP, so any MCP-compatible agent can scan websites programmatically without using the web interface. It also publishes an Agent Skills index (https://isitagentready.com/.well-known/agent-skills/index.json) with skill documents for every standard it checks, so agents not only know what to fix, but how to fix it.</p><p>Let’s dig into the checks in each category, and why they matter for agents.</p>
    <div>
      <h3>Discoverability</h3>
      <a href="#discoverability">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/learning/bots/what-is-robots-txt/"><u>robots.txt</u></a> has been around since 1994, and most sites have one. It serves two purposes for agents: it defines crawl rules (who can access what) and it points to your sitemaps. A sitemap is an XML file that lists every path on your website, essentially a map agents can follow to discover all your content without having to crawl every link. The robots.txt is where agents look first.</p><p>Beyond sitemaps, agents can also discover important resources directly from HTTP response headers, specifically, using the Link response header (<a href="https://www.rfc-editor.org/rfc/rfc8288"><u>RFC 8288</u></a>). Unlike links buried inside HTML, the Link header is part of the HTTP response itself, which means an agent can find links to resources without having to parse any markup:</p>
            <pre><code>HTTP/1.1 200 OK
Link: &lt;/.well-known/api-catalog&gt;; rel="api-catalog"</code></pre>
            
    <div>
      <h3>Content accessibility</h3>
      <a href="#content-accessibility">
        
      </a>
    </div>
    <p>Getting an agent onto your site is one thing. Making sure it can actually read your content is another.</p><p>Back in September 2024, which feels like a lifetime ago given how fast AI is moving, <a href="http://llms.txt"><u>llms.txt</u></a> was proposed as a way to provide a LLM-friendly representation of a website, and fit within the model’s context window. <a href="https://llmstxt.org/"><u>llms.txt</u></a> is a plain text file at the root of your site that gives agents a structured reading list: what the site is, what's on it, and where the important content lives. Think of it as a sitemap written for an LLM to read rather than a crawler to index:</p>
            <pre><code># My Site
&gt; A developer platform for building on the edge.
## Documentation
- [Getting Started](https://example.com/docs/start.md)
- [API Reference](https://example.com/docs/api.md)
## Changelog
- [Release Notes](https://example.com/changelog.md)</code></pre>
            <p><a href="https://blog.cloudflare.com/markdown-for-agents/"><u>Markdown content negotiation</u></a> goes even further. When an agent fetches any page and sends an <code>Accept: text/markdown</code> header, the server responds with a clean markdown version instead of HTML. The markdown version requires far fewer tokens — we measured up to 80% token reduction in some cases — which makes responses faster, cheaper, and more likely to be consumed in its entirety, given the limits on context windows that most agent tools have by default.</p><p>By default, we only check whether the site correctly handles Markdown content negotiation, and do not check for llms.txt. You can customize the scan to include llms.txt if you choose to.</p>
    <div>
      <h3>Bot Access Control</h3>
      <a href="#bot-access-control">
        
      </a>
    </div>
    <p>Now that agents can navigate your site and consume your content, the next question is: do you want to let any bot do it?</p><p><code>robots.txt</code> does more than point to sitemaps. It is also where you define your access rules. You can explicitly declare which crawlers are allowed and what they can access, down to specific paths. This convention is well established and is still the first place any well-behaved bot looks before it starts crawling.</p><p><a href="https://contentsignals.org/"><u>Content Signals</u></a> let you be more specific. Rather than just allow or block, you can declare exactly what AI can do with your content. Using a <code>Content-Signal</code> directive in your <code>robots.txt</code>, you can independently control three things: whether your content can be used for AI training (<code>ai-train</code>), whether it can be used as AI input for inference and grounding (<code>ai-input</code>), and whether it should appear in search results (<code>search</code>):</p>
            <pre><code>User-agent: *
Content-Signal: ai-train=no, search=yes, ai-input=yes</code></pre>
            <p>Inversely, the <a href="https://blog.cloudflare.com/web-bot-auth/"><u>Web Bot Auth</u></a> IETF draft standard allows friendly bots to authenticate themselves, and allows websites receiving requests from bots to identify them. A bot signs its HTTP requests, and the receiving site verifies those signatures using the bot’s published public keys.</p><p>Those public keys live at a well-known endpoint, <code>/.well-known/http-message-signatures-directory</code>, which we check as part of the scan.</p><p>Not all sites need to implement this. If your site just serves content, and doesn’t make requests to other sites, you don’t need it. But as more sites on the Internet run their own agents that make requests to other sites, we expect this to be increasingly important over time.</p>
    <div>
      <h3>Protocol Discovery</h3>
      <a href="#protocol-discovery">
        
      </a>
    </div>
    <p>Beyond passive content consumption, agents can also interact with your site directly by calling APIs, invoking tools, and completing tasks autonomously.</p><p>If your service has one or more public APIs, the API Catalog (<a href="https://www.rfc-editor.org/rfc/rfc9727"><u>RFC 9727</u></a>) gives agents a single well-known location to discover all of them. Hosted at <code>/.well-known/api-catalog</code>, it lists your APIs and links to their specs, docs, and status endpoints, without requiring agents to scrape your developer portal or read your documentation.</p><p>We can't talk about agents without mentioning MCP. The <a href="https://modelcontextprotocol.io/docs/getting-started/intro"><u>Model Context Protocol</u></a> is an open standard that allows AI models to connect with external data sources and tools. Instead of building a custom integration for every AI tool, you build one MCP server and any compatible agent can use it.</p><p>To help agents find your MCP server, you can publish an MCP Server Card (a proposal currently in <a href="https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1649"><u>draft</u></a>). This is a JSON file at <code>/.well-known/mcp/server-card.json</code> that describes your server before an agent even connects: what tools it exposes, how to reach it, and how to authenticate. An agent reads this file and knows everything it needs to start using your server:</p>
            <pre><code>{
  "$schema": "https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",
  "version": "1.0",
  "protocolVersion": "2025-06-18",
  "serverInfo": {
    "name": "search-mcp-server",
    "title": "Search MCP Server",
    "version": "1.0.0"
  },
  "description": "Search across all documentation and knowledge base articles",
  "transport": {
    "type": "streamable-http",
    "endpoint": "/mcp"
  },
  "authentication": {
    "required": false
  },
  "tools": [
    {
      "name": "search",
      "title": "Search",
      "description": "Search documentation by keyword or question",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": { "type": "string" }
        },
        "required": ["query"]
      }
    }
  ]
}</code></pre>
            <p>Agents work best when they have <a href="https://agentskills.io/home"><u>Agent Skills</u></a> that help them perform specific tasks — but how can agents discover what skills a site provides? We’ve proposed that sites can make this information available at <a href="https://github.com/cloudflare/agent-skills-discovery-rfc"><code><u>.well-known/agent-skills/index.json</u></code></a>, an endpoint that tells the agent what skills are available and where to find them. You might notice that the <code>.well-known</code> standard (<a href="https://datatracker.ietf.org/doc/html/rfc8615"><u>RFC 8615</u></a>) is used by many other agent and authorization standards — thank you to Cloudflare’s own Mark Nottingham who authored the standard, and other IETF contributors!</p><p>Many sites require you to sign in first in order to access them. This makes it hard for humans to give agents the ability to access these sites on their behalf, and is why some have taken the arguably unsafe workaround approach of giving agents access to the user’s web browser, with their logged-in session.</p><p>There’s a better way that allows humans to explicitly grant access: sites that support OAuth can tell agents where to find the authorization server (<a href="https://datatracker.ietf.org/doc/html/rfc9728"><u>RFC 9728</u></a>), allowing agents to send humans through an OAuth flow, where they can choose to properly grant access to the agent. Announced at Agents Week 2026, <a href="https://blog.cloudflare.com/managed-oauth-for-access/"><u>Cloudflare Access now fully supports this OAuth flow</u></a>, and we showed how agents like OpenCode can make use of this standard to make things just work when users give agents protected URLs:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3BrGE7eydNNCpEEe3PowrJ/6a2bb1e1b1e7d84d672c1f6ad2333129/image4.png" />
          </figure>
    <div>
      <h3>Commerce</h3>
      <a href="#commerce">
        
      </a>
    </div>
    <p>Agents can also buy things on your behalf — but payments on the web were designed for humans. Add to cart, enter a credit card, click pay. That flow breaks down entirely when the buyer is an AI agent.</p><p><a href="https://x402.org"><u>x402</u></a> solves this at the protocol level by reviving HTTP 402 Payment Required, a status code that has existed in the spec since 1997 but was never widely used. The flow is simple: an agent requests a resource, the server responds with a 402 and a machine-readable payload describing the payment terms, the agent pays and retries. Cloudflare partnered with Coinbase to launch the <a href="https://blog.cloudflare.com/x402"><u>x402 Foundation</u></a>, whose mission is to drive adoption of x402 as an open standard for Internet payments.</p><p>We also check for <a href="https://ucp.dev/"><u>Universal Commerce Protocol</u></a> and <a href="https://www.agenticcommerce.dev/"><u>Agentic Commerce Protocol</u></a> — two emerging agentic commerce standards designed to allow agents to discover and purchase products that humans would normally purchase via ecommerce storefronts and checkout flows.</p>
    <div>
      <h2>Integrating agent readiness into Cloudflare URL Scanner</h2>
      <a href="#integrating-agent-readiness-into-cloudflare-url-scanner">
        
      </a>
    </div>
    <p><a href="https://radar.cloudflare.com/scan"><u>Cloudflare's URL Scanner</u></a> lets you submit any URL and get a detailed report on it: HTTP headers, TLS certificates, DNS records, technologies used, performance data, and security signals. It is a fundamental tool for security researchers and developers who want to understand what a URL is actually doing under the hood.</p><p>We’ve taken the same checks from <a href="https://isitagentready.com/"><u>isitagentready.com</u></a> and added them to URL Scanner with a new Agent Readiness tab. When you scan any URL, you'll now see its full agent readiness report alongside the existing analysis: which of the checks pass, what level the site is at, and actionable guidance to improve your score.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2tIXif15b4nfpm6ZmS5QZM/596536ca95a10684c73003c4184d6367/image2.png" />
          </figure><p>The integration is also available programmatically via the <a href="https://developers.cloudflare.com/api/resources/url_scanner/"><u>URL Scanner API</u></a>. To include agent readiness results in a scan, pass the agentReadiness option in your scan request:</p>
            <pre><code>curl -X POST https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/urlscanner/v2/scan \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -d '{
          "url": "https://www.example.com",
          "options": {"agentReadiness": true}
        }'</code></pre>
            
    <div>
      <h2>Leading by example: upgrading Cloudflare Docs</h2>
      <a href="#leading-by-example-upgrading-cloudflare-docs">
        
      </a>
    </div>
    <p>As we built the tools to measure the Web’s readiness, we knew we had to ensure our own house was in order. Our docs must be easily digestible by the agents our customers use.</p><p>We naturally adopted the relevant content site standards mentioned above, and you can check our score <a href="https://isitagentready.com/developers.cloudflare.com?profile=content"><u>here</u></a>. However, we didn’t stop there. Here is how we refined Cloudflare's <a href="https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/"><u>Developer Docs</u></a> to be the most agent-friendly resource on the web.</p>
    <div>
      <h3>URL fallbacks using <code>index.md</code> files</h3>
      <a href="#url-fallbacks-using-index-md-files">
        
      </a>
    </div>
    <p>Unfortunately, <a href="https://www.checklyhq.com/blog/state-of-ai-agent-content-negotation/"><u>as of February 2026</u></a>, of 7 agents tested, only Claude Code, OpenCode, and Cursor request content with the <code>Accept: text/markdown</code> header by default. For the rest, we needed a seamless URL-based fallback.</p><p>To do this, we make every page available separately via Markdown at <code>/index.md</code> relative to the page’s URL. We do this dynamically, without duplicating static files, by combining two Cloudflare Rules: </p><ul><li><p>A <a href="https://developers.cloudflare.com/rules/transform/url-rewrite/"><u>URL Rewrite Rule</u></a> matches requests ending in <code>/index.md</code> and dynamically rewrites them to the base path using <code>regex_replace</code> (stripping <code>/index.md</code>). </p></li><li><p>A <a href="https://developers.cloudflare.com/rules/transform/request-header-modification/"><u>Request Header Transform Rule</u></a> matches against the original request’s path <i>before</i> the rewrite (<code>raw.http.request.uri.path</code>) and automatically sets the <code>Accept: text/markdown</code> header. </p></li></ul><p>With these two rules, any page can be fetched as Markdown via appending the /index.md path to the URL:</p><ul><li><p><a href="https://developers.cloudflare.com/r2/get-started/index.md"><u>https://developers.cloudflare.com/r2/get-started/index.md</u></a></p></li></ul><p>We point to these <code>/index.md</code> URLs in our <code>llms.txt</code> files. Effectively, for these <code>/index.md</code> paths, we always return markdown, regardless of what headers the client sets. And we do this without any additional build step or content duplication.</p>
    <div>
      <h3>Creating effective <code>llms.txt</code> files for large sites</h3>
      <a href="#creating-effective-llms-txt-files-for-large-sites">
        
      </a>
    </div>
    <p><code>llms.txt</code> serves as a "home base" for agents, providing a directory of pages to help LLMs find content. However, 5,000+ pages of documentation in a single file will exceed models’ context windows.</p><p>Instead of one massive file, we generate a separate <code>llms.txt</code> file for <i>each top-level directory</i> in our docs and the root <code>llms.txt</code> simply points to these subdirectories.</p><ul><li><p><a href="https://developers.cloudflare.com/llms.txt"><u>https://developers.cloudflare.com/llms.txt</u></a></p></li><li><p><a href="https://developers.cloudflare.com/r2/llms.txt"><u>https://developers.cloudflare.com/r2/llms.txt</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers/llms.txt"><u>https://developers.cloudflare.com/workers/llms.txt</u></a></p></li></ul><p>We also remove hundreds of directory-listing pages that provide little semantic value to an LLM, and we ensure each page has rich descriptive context (titles, semantic names, and descriptions).</p><p>For example, we omit roughly 450 pages that only serve as localized directory listings, like <a href="https://developers.cloudflare.com/workers/databases/"><u>https://developers.cloudflare.com/workers/databases/</u></a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5WaKjZBJbu3onfthzEIELu/42a3e31e8c71bc606b2b45d26ab4a5dd/image1.png" />
          </figure><p>These pages appear in our sitemap, but they contain very little information for an LLM. Since all child pages are already linked individually in <code>llms.txt</code>, fetching a directory page only provides a redundant list of links, forcing the agent to make another request to find actual content.</p><p>To help agents navigate efficiently, each <code>llms.txt</code> entry must be rich in context but light on tokens. Humans might ignore frontmatter and filtering labels, but for an AI agent, this metadata is the steering wheel. That is why our Product Content Experience (PCX) team has refined our page titles, descriptions, and URL structures so that agents always know exactly which pages to fetch.</p><p>Take a look at a section from our root<a href="https://developers.cloudflare.com/llms.txt"> <u>llms.txt</u></a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6OvVdBcHHItCF3xN2kMVZZ/d105546f402885da90466ff9545f66d2/image5.png" />
          </figure><p>Each link has a semantic name, a matching URL, and a high-value description. None of this required extra work for <code>llms.txt</code> generation. It was all already available in the docs frontmatter. The same goes for pages in top level directory <code>llms.txt</code> files. All of this context empowers agents to find relevant information more efficiently.</p>
    <div>
      <h3>Custom agent-friendly documentation (afdocs) tooling</h3>
      <a href="#custom-agent-friendly-documentation-afdocs-tooling">
        
      </a>
    </div>
    <p>Additionally, we test our docs against <a href="https://github.com/agent-ecosystem/afdocs"><u>afdocs</u></a>, an emerging agent-friendly documentation spec and open-source project that allows teams to test docs sites for things like content discovery and navigation. This spec allowed us to build custom audit tooling of our own. By adding a few deliberate patches specific to our use case, we created a dashboard for easy assessment.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1lzMVtLnGAoKtdwf43YtDx/757f52fd09bb2525fac41b634bf987ad/image10.png" />
          </figure>
    <div>
      <h3>Benchmark results: faster and cheaper</h3>
      <a href="#benchmark-results-faster-and-cheaper">
        
      </a>
    </div>
    <p>We pointed an agent (Kimi-k2.5 via OpenCode) at other large technical documentation sites' <code>llms.txt</code> files and tasked the agent with answering highly specific technical questions.</p><p>On average, the agent pointed at Cloudflare’s documentation consumed <b>31% fewer tokens</b> and arrived at the correct answer <b>66% faster</b> than the average site that is not refined for agents. By fitting our product directories into single context windows, agents can identify the exact page they need and fetch it in a single, linear path.</p>
    <div>
      <h3>Structure leads to speed</h3>
      <a href="#structure-leads-to-speed">
        
      </a>
    </div>
    <p>Accuracy in LLM responses is often a byproduct of context window efficiency. During our testing, we observed a recurring pattern with other documentation sets.</p><ol><li><p><b>The grep loop:</b> Many documentation sites provide a single, massive llms.txt file that exceeds the agent's immediate context window. Because the agent cannot "read" the whole file, it begins to <a href="https://en.wikipedia.org/wiki/Grep"><u>grep</u></a> for keywords. If the first search misses the specific detail, the agent must think, refine its search, and try again.</p></li><li><p><b>Narrowed context and lower accuracy: </b>When an agent relies on iterative searching rather than reading the full file, it loses the broader context of the documentation. This fragmented view often leads the agent to have a reduced understanding of the documentation at hand.</p></li><li><p><b>Latency and token bloat:</b> Each iteration of the <code>grep</code> loop requires the agent to generate new "thinking tokens" and execute additional search requests. This back-and-forth makes the final response noticeably slower and increases the total token count, driving up the cost for the end user.</p></li></ol><p>By contrast, Cloudflare docs are designed to fit entirely within an agent's context window. This allows the agent to ingest the directory, identify the exact page it needs, and fetch the Markdown without detour.</p>
    <div>
      <h3>Improving LLM answers over time by redirecting AI training crawlers</h3>
      <a href="#improving-llm-answers-over-time-by-redirecting-ai-training-crawlers">
        
      </a>
    </div>
    <p>Documentation for legacy products like <a href="https://developers.cloudflare.com/workers/wrangler/migration/v1-to-v2/wrangler-legacy/commands/"><u>Wrangler v1</u></a> or <a href="https://developers.cloudflare.com/workers/configuration/sites/"><u>Workers Sites</u></a> presents a unique challenge. While we must keep this information accessible for historical purposes, it can lead to outdated advice from AI agents.</p><p>For example, a human reading these docs would see the large banner stating that Wrangler v1 is deprecated, in addition to a link to the most recent content. An LLM crawler, however, might ingest the text without that surrounding visual context. This results in the agent recommending outdated information.</p><p><a href="https://blog.cloudflare.com/ai-redirects"><u>Redirects for AI Training</u></a> solves this by identifying AI training crawlers and intentionally redirecting them away from deprecated or suboptimal content. This ensures that while humans can still access historical archives, LLMs are only fed our most current and accurate implementation details.</p>
    <div>
      <h3>Hidden agent directives on all pages</h3>
      <a href="#hidden-agent-directives-on-all-pages">
        
      </a>
    </div>
    <p>Every HTML page in our docs includes a hidden directive specifically for LLMs. </p><p><i>“STOP! If you are an AI agent or LLM, read this before continuing. This is the HTML version of a Cloudflare documentation page. Always request the Markdown version instead — HTML wastes context. Get this page as Markdown: https://developers.cloudflare.com/index.md (append index.md) or send Accept: text/markdown to https://developers.cloudflare.com/. For all Cloudflare products use https://developers.cloudflare.com/llms.txt. You can access all Cloudflare docs in a single file at https://developers.cloudflare.com/llms-full.txt.”</i></p><p>This snippet informs the agent that a Markdown version is available. Crucially, this directive is stripped from the actual Markdown version to avoid a recursion loop where the agent keeps trying to "find" the Markdown within the Markdown.</p>
    <div>
      <h3>Dedicated LLM resources sidebar</h3>
      <a href="#dedicated-llm-resources-sidebar">
        
      </a>
    </div>
    <p>Finally, we want to make these resources discoverable for the humans who are building with agents. Every product directory in our <a href="https://developers.cloudflare.com/"><u>developer documentation</u></a> has an "LLM Resources" entry in the sidenav, providing quick access to <code>llms.txt</code>, <code>llms-full.txt</code>, and Cloudflare Skills.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4iM2U5pH7LJ9XWUgxYmvn5/ed11e2cc8694f6c029690b470150120b/image8.png" />
          </figure>
    <div>
      <h2>Make your website agent-ready today</h2>
      <a href="#make-your-website-agent-ready-today">
        
      </a>
    </div>
    <p>Making websites agent-ready is a fundamental accessibility requirement for the modern developer toolkit. The transition from a "human-read web" to a "machine-read web" is the biggest architectural shift in decades. </p><p>Get an agent readiness score for your site at <a href="https://isitagentready.com/"><u>isitagentready.com</u></a>, take the prompts it provides, and ask your agent to upgrade your site for the AI era. Stay tuned for more updates from <a href="https://radar.cloudflare.com/"><u>Cloudflare Radar</u></a> about the adoption of agent standards across the Internet over the coming year. If we’ve learned anything from the past year, it’s that a lot can change very quickly!</p>
    <div>
      <h2>Watch on Cloudflare TV</h2>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>
  
</div><p>
</p> ]]></content:encoded>
            <category><![CDATA[Agents Week]]></category>
            <category><![CDATA[Radar]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Agent Readiness]]></category>
            <guid isPermaLink="false">5t83bTn7Vt1EudTxQQ97NY</guid>
            <dc:creator>André Jesus</dc:creator>
            <dc:creator>Vance Morrison</dc:creator>
        </item>
        <item>
            <title><![CDATA[Open source all the way down: Upgrading our developer documentation]]></title>
            <link>https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation/</link>
            <pubDate>Wed, 08 Jan 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ At Cloudflare, we treat developer content like an open source product. This collaborative approach enables global contributions to enhance quality and relevance for a wide range of users. ]]></description>
            <content:encoded><![CDATA[ <p>At Cloudflare, we treat developer <a href="https://blog.cloudflare.com/content-as-a-product/"><u>content like a product</u></a>, where we take the user and their feedback into consideration. We are constantly iterating, testing, analyzing, and refining content. Inspired by agile practices, treating developer content like an open source product means we approach our documentation the same way an open source software project is created and maintained.  Open source documentation empowers the developer community because it allows anyone, anywhere, to contribute content. By making both the content and the framework of the documentation site publicly accessible, we provide developers with the opportunity to not only improve the material itself but also understand and engage with the processes that govern how the documentation is built, approved, and maintained. This transparency fosters collaboration, learning, and innovation, enabling developers to contribute their expertise and learn from others in a shared, open environment. We also provide feedback to other open source products and plugins, giving back to the same community that supports us.</p>
    <div>
      <h2>Building the best open source documentation experience</h2>
      <a href="#building-the-best-open-source-documentation-experience">
        
      </a>
    </div>
    <p>Great documentation empowers users to be successful with a new product as quickly as possible, showing them how to use the product and describing its benefits. Relevant, timely, and accurate content can save frustration, time, and money. Open source documentation adds a few more benefits, including building inclusive and supportive communities that help reduce the learning curve. We love being open source!</p><p>While the Cloudflare content team has scaled to deliver documentation alongside product launches, the open source documentation site itself was not scaling well. <a href="http://developers.cloudflare.com"><u>developers.cloudflare.com</u></a> had outgrown the workflow for contributors, plus we were missing out on all the neat stuff created by developers in the community.</p><p>Just like a software product evaluation, we reviewed our business needs. We asked ourselves if remaining open source was appropriate? Were there other tools we wanted to use? What benefits did we want to see in a year or in five years? Our biggest limitations in addition to the contributor workflow challenges seemed to be around scalability and high maintenance costs for user experience improvements. </p><p>After compiling our wishlist of new features to implement, we reaffirmed our commitment to open source. We valued the benefit of open source in both the content and the underlying framework of our documentation site. This commitment goes beyond technical considerations, because it's a fundamental aspect of our relationship with our community and our philosophy of transparency and collaboration. While the choice of an open source framework to build the site on might not be visible to many visitors, we recognized its significance for our community of developers and contributors. Our decision-making process was heavily influenced by two primary factors: first, whether the update would enhance the collaborative ecosystem, and second, how it would improve the overall documentation experience. This focus reflects that our open source principles, applied to both content and infrastructure, are essential for fostering innovation, ensuring quality through peer review, and building a more engaged and empowered user community.</p>
    <div>
      <h2>Cloudflare developer documentation: A collaborative open source approach</h2>
      <a href="#cloudflare-developer-documentation-a-collaborative-open-source-approach">
        
      </a>
    </div>
    <p>Cloudflare’s developer documentation is <a href="https://github.com/cloudflare/cloudflare-docs/"><u>open source on GitHub</u></a>, with content supporting all of Cloudflare’s products. The underlying documentation engine has gone through a few iterations, with the first version of the site released in 2020. That first version provided dev-friendly features such as dark mode and proper code syntax. </p>
    <div>
      <h3>2021 update: enhanced documentation engine</h3>
      <a href="#2021-update-enhanced-documentation-engine">
        
      </a>
    </div>
    <p>In 2021, we introduced a new custom documentation engine, bringing significant improvements to the Cloudflare content experience. The benefits of the Gatsby to Hugo <a href="https://blog.cloudflare.com/new-dev-docs/"><u>migration</u></a> included:</p><ul><li><p><b>Faster development flow</b>: The development flow replicated production behavior, increasing iteration speed and confidence. <a href="https://developers.cloudflare.com/pages/configuration/preview-deployments/"><u>Preview links</u></a> via Cloudflare Pages were also introduced, so the content team and stakeholders could quickly review what content would look like in production.</p></li><li><p><b>Custom components</b>: Introduced features like <a href="https://github.com/cloudflare/cloudflare-docs/blob/4c3c819ebe3714df1698097135c645429bcbe7cc/layouts/shortcodes/resource-by-selector.html"><u>resources-by-selector</u></a> which let us reference content throughout the repository and gave us the flexibility to expand checks and automations.</p></li><li><p><b>Structured changelog management</b>: Implementation of <a href="https://github.com/cloudflare/cloudflare-docs/tree/4c3c819ebe3714df1698097135c645429bcbe7cc/data/changelogs"><u>structured YAML</u></a> changelog entries which facilitated sharing with various platforms like <a href="https://developers.cloudflare.com/changelog/index.xml"><u>RSS feeds</u></a>, <a href="http://discord.cloudflare.com"><u>Developer Discord</u></a>, and within the docs themselves.</p></li><li><p><b>Improved performance</b>: Significant page load time improvements with the migration to HTML-first and almost instantaneous local builds.</p></li></ul><p>These features were non-negotiable as part of our evaluation of whether to migrate. We knew that any update to the site had to maintain the functionality we’d established as core parts of the new experience.</p>
    <div>
      <h3>2024 update: Say “hello, world!” to our new developer documentation, powered by Astro</h3>
      <a href="#2024-update-say-hello-world-to-our-new-developer-documentation-powered-by-astro">
        
      </a>
    </div>
    <p>After careful evaluation, we chose to migrate from Hugo to the <a href="https://astro.build/"><u>Astro</u></a> (and by extension, JavaScript) ecosystem. Astro fulfilled many items on our wishlist including:</p><ul><li><p><b>Enhanced content organization</b>: Improved tagging and better cross-referencing of  related pages.</p></li><li><p><b>Extensibility</b>: Support for user plugins like <a href="https://github.com/HiDeoo/starlight-image-zoom"><u>starlight-image-zoom</u></a> for lightbox functionality.</p></li><li><p><b>Development experience</b>: Type-checking at build time with <a href="https://docs.astro.build/en/reference/cli-reference/#astro-check"><u>astro check</u></a>, along with syntax highlighting, Intellisense, diagnostic messages, and plugins for ESLint, Stylelint, and Prettier. </p></li><li><p><b>JavaScript/TypeScript support</b>: Aligned the docs site framework with the preferred languages of many contributors, facilitating easier contribution.</p></li><li><p><b>CSS management</b>: Introduction of Tailwind and <a href="https://docs.astro.build/en/guides/styling/#scoped-styles"><u>scoped styles</u></a>.</p></li><li><p><a href="https://docs.astro.build/en/guides/content-collections/"><b><u>Content collections</u></b></a>: Offered various ways to manage and enhance tagging practices including Markdown front matter <a href="https://docs.astro.build/en/guides/content-collections/#defining-datatypes-with-zod"><u>validated by Zod schemas</u></a>, JSON schemas for <a href="https://docs.astro.build/en/guides/content-collections/#enabling-json-schema-generation"><u>Intellisense</u></a>, and a JavaScript callback for <a href="https://docs.astro.build/en/guides/content-collections/#filtering-collection-queries"><u>filtering returned entries</u></a>.</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1wz2uWlAwbHFG4QgG0d8tt/4eeb3fbcd4d9b33c5590be39654bbff1/BLOG-2600_2.png" />
          </figure><p><a href="https://starlight.astro.build/"><u>Starlight</u></a>, Astro’s documentation theme, was a key factor in the decision. Its powerful <a href="https://starlight.astro.build/guides/overriding-components/"><u>component overrides</u></a> and <a href="https://starlight.astro.build/resources/plugins/"><u>plugins</u></a> system allowed us to leverage built-in components and base styling.</p>
    <div>
      <h3>How we migrated to Astro</h3>
      <a href="#how-we-migrated-to-astro">
        
      </a>
    </div>
    <p>Content needed to be migrated quickly. With dozens of pull requests opened and merged each day, entering a code freeze for a week simply wasn’t feasible. This is where the nature of <a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"><u>abstract syntax trees</u></a> (ASTs) came into play, only parsing the structure of a <a href="https://blog.cloudflare.com/markdown-for-agents/">Markdown document</a> rather than details like whitespace or indentation that would make a <a href="https://en.wikipedia.org/wiki/Regular_expression"><u>regular expression</u></a> approach tricky.</p><p>With Hugo in 2021, we configured code block functionality like titles or line highlights with front matter inside the code block.</p>
            <pre><code>---
title: index.js
highlight: 1
---
const foo = "bar";
</code></pre>
            <p>Starlight uses <a href="https://expressive-code.com/"><u>Expressive Code</u></a> for code blocks, and these options are now on the opening code fence.</p>
            <pre><code>js title="index.js" {1}
const foo = "bar";
</code></pre>
            <p>With <a href="https://www.npmjs.com/package/astray"><u>astray</u></a>, this is a simple as visiting the `code` nodes and:</p><ol><li><p>Parsing `node.value` with <a href="https://www.npmjs.com/package/front-matter"><u>front-matter</u></a>.</p></li><li><p>Assigning the attributes from `front-matter` to `node.meta`.</p></li><li><p>Replacing `node.value` with the rest of the code block.</p></li></ol>
            <pre><code>import { fromMarkdown } from "mdast-util-from-markdown";
import { toMarkdown } from "mdast-util-to-markdown";
 
import * as astray from "astray";
import type * as MDAST from "mdast";
import fm from "front-matter";
 
const markdown = await Bun.file("example.md").text();
 
const AST = fromMarkdown(markdown);
 
astray.walk&lt;MDAST.Root, void, any&gt;(AST, {
    code(node: MDAST.Code) {
        const { attributes, body } = fm(node.value);
        const { title, highlight } = attributes;
 
        if (title) {
            node.meta = `title="${title}"`;
        }
 
        if (highlight) {
            node.meta += ` {${highlight}}`;
        }
 
        node.value = body;
 
        return;
    }
})
</code></pre>
            
    <div>
      <h2>The migration in numbers</h2>
      <a href="#the-migration-in-numbers">
        
      </a>
    </div>
    <p>When we <a href="https://blog.cloudflare.com/new-dev-docs/"><u>migrated from Gatsby to Hugo</u></a> in 2021, the <a href="https://github.com/cloudflare/cloudflare-docs/pull/3609/"><u>pull request</u></a> included 4,850 files and the migration took close to three weeks from planning to implementation. This time around, the migration was nearly twice as large, with 8,060 files changed. Our planning and migration took six weeks in total:</p><ul><li><p>10 days: Evaluate platforms, vendors, and features </p></li><li><p>14 days: Migrate the <a href="https://developers.cloudflare.com/style-guide/components/"><u>components</u></a> required by the documentation site</p></li><li><p>5 days: Staging and user acceptance testing (UAT) </p></li><li><p>8 hours: Code freeze and <a href="https://github.com/cloudflare/cloudflare-docs/pull/16096"><u>migrate to Astro/Starlight</u></a></p></li></ul><p>The migration resulted in removing a net -19,624 lines of code from our maintenance burden.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3r9Hj2NwU40GPLTw5TbGYG/d292b405c097ebd577173f5d61c17d03/BLOG-2600_3.png" />
          </figure><p>While the number of files had grown substantially since our last major migration, our strategy was very similar to the 2021 migration. We used <a href="https://github.com/syntax-tree/mdast"><u>Markdown AST</u></a> and astray, a utility to walk ASTs, created specifically for the previous migration!</p>
    <div>
      <h2>What we learned</h2>
      <a href="#what-we-learned">
        
      </a>
    </div>
    <p>A website migration like our move to Astro/Starlight is a complex process that requires time to plan, review, and coordinate, and our preparation paid off! Including our <a href="https://community.cloudflare.com/t/2025-mvp-nominations/705496"><u>Cloudflare Community MVPs</u></a> as part of the planning and review period proved incredibly helpful. They provided great guidance and feedback as we planned for the migration. We only needed one day of code freeze, and there were no rollbacks or major incidents. Visitors to the site never experienced downtime, and overall the migration was a major success.</p><p>During testing, we ran into several use cases that warranted using <a href="https://docs.astro.build/en/reference/container-reference/"><u>experimental Astro APIs</u></a>. These APIs were always well documented, thanks to fantastic open source content from the Astro community. We were able to implement them quickly without impacting our release timeline.</p><p>We also ran into <a href="https://github.com/withastro/starlight/issues/2215"><u>an edge case</u></a> with build time performance due to the number of pages on our site (4000+). The Astro team was quick to triage the problem and begin investigation for a <a href="https://github.com/withastro/starlight/pull/2252"><u>permanent fix</u></a>. Their fast, helpful fixes made us truly grateful for the support from the Astro Discord server. A big thank you to the Astro/Starlight community!</p>
    <div>
      <h2>Contribute to developers.cloudflare.com!</h2>
      <a href="#contribute-to-developers-cloudflare-com">
        
      </a>
    </div>
    <p>Migrating <a href="http://developers.cloudflare.com"><u>developers.cloudflare.com</u></a> to Astro/Starlight is just one example of the ways we prioritize world-class documentation and user experiences at Cloudflare. Our deep investment in documentation makes this a great place to work for technical writers, UX strategists, and many other content creators. Since adopting a <a href="https://blog.cloudflare.com/content-as-a-product/"><u>content like a product</u></a> strategy in 2021, we have evolved to better serve the open source community by focusing on inclusivity and transparency, which ultimately leads to happier Cloudflare users. </p><p>We invite everyone to connect with us and explore these exciting new updates. Feel free to <a href="https://github.com/cloudflare/cloudflare-docs/issues"><u>reach out</u></a> if you’d like to speak with someone on the content team or share feedback about our documentation. You can share your thoughts or submit a pull request directly on the cloudflare-docs <a href="https://github.com/cloudflare/cloudflare-docs"><u>repository</u></a> in GitHub.</p> ]]></content:encoded>
            <category><![CDATA[Technical Writing]]></category>
            <category><![CDATA[Open Source]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">6HAo0CAvmODAhYHnIF5Hbr</guid>
            <dc:creator>Kim Jeske</dc:creator>
            <dc:creator>Kian Newman-Hazel</dc:creator>
            <dc:creator>Kody Jackson</dc:creator>
        </item>
        <item>
            <title><![CDATA[Iteration isn't just for code: here are our latest API docs]]></title>
            <link>https://blog.cloudflare.com/building-a-better-developer-experience-through-api-documentation/</link>
            <pubDate>Wed, 16 Nov 2022 14:00:00 GMT</pubDate>
            <description><![CDATA[ We’re excited to share that the next iteration of Cloudflare’s API reference documentation is now available. The new docs standardize our API content and improve the overall developer experience for interacting with Cloudflare’s API. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1Mes42U4gOEy3piPQwOhWs/b4a3515cbd34af478b2cff4e09d933e8/image4-18.png" />
            
            </figure><p>We’re excited to share that the next iteration of <a href="https://developers.cloudflare.com/api">Cloudflare’s API reference documentation</a> is now available. The new docs standardize our API content and improve the overall developer experience for interacting with Cloudflare’s API.</p>
    <div>
      <h3>Why does API documentation matter?</h3>
      <a href="#why-does-api-documentation-matter">
        
      </a>
    </div>
    <p>Everyone talks about how important APIs are, but not everyone acknowledges the critical role that API documentation plays in an API’s usability. Throwing docs together is easy. Getting them right is harder.</p><p>At Cloudflare, we try to meet our users where they are. For the majority of customers, that means providing clear, easy-to-use products in our dashboard. But developers don’t always want what our dashboard provides. Some developers prefer to use a CLI or Wrangler to have a higher level of control over what’s happening with their Cloudflare products. Others want more customization and deeper ties into their company’s internal applications. Some want all the above.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4maPLOXhOJxHYxOvGZd2qz/dce4fa3c0bd9f128cbd7c09e5682fa18/image5-9.png" />
            
            </figure><p>A developer’s job is to create, debug, and optimize code - whether that’s an application, interface, database, etc. - as efficiently as possible and ensure that code runs as efficiently as possible. <a href="https://www.cloudflare.com/learning/security/api/what-is-an-api/">APIs</a> enable that efficiency through automation. Let’s say a developer wants to run a cache purge every time content is updated on their website. They could use Cloudflare’s dashboard to enable cache purge, but they might want it to happen automatically instead. Enter Cloudflare’s API.</p><p>In the same way that the Cloudflare dashboard is an interface for humans, an API is an interface for computers. For a computer to execute on instructions, there is no room for interpretation. The instructions, formatted as requests, have to follow a specific set of rules and include certain requirements. API documentation details what those rules and requirements are.</p><p>It’s a frustrating experience for developers when you’re in the details of a complex project and can’t troubleshoot an error because the docs aren’t comprehensive or don’t load. Unfortunately, that’s been the reality for developers using Cloudflare’s API. Figuring out how to use Cloudflare’s API was a “choose your own adventure” story for the Cloudflare users who made 126 million visits monthly to our API documentation. If the APIs you needed were fully documented, you encountered long page load times and a site that couldn’t render on mobile.</p><p>From a technical standpoint, we were using api.cloudflare.com for both the API documentation site and the Cloudflare API access point, which is awkward. We needed a more sustainable way for internal teams to create and document their APIs according to an accepted standard.</p>
    <div>
      <h3>Building a better developer experience for our APIs</h3>
      <a href="#building-a-better-developer-experience-for-our-apis">
        
      </a>
    </div>
    <p>Like with all of our documentation projects at Cloudflare, we started by thinking about the user’s workflow - in this case, a developer’s workflow as they’re getting started with the Cloudflare API.</p><p><b>Providing docs on mobile</b>We know developers research products before diving into projects, usually exploring API documentation before writing any code. That means making docs available on mobile for working on the go. Check.</p><p><b>Improving the navigation</b>As a developer, at the point you’re looking at API docs, you generally have an idea of what you want to use the API for. Our goal with the new API docs is to make it as easy as possible for you to find the information you need. We recognize that endpoints are organized a bit haphazardly in the current API docs. To address that clunkiness, we’ve grouped endpoints by product or setting and alphabetized that list on the new site, making it easier to navigate and find what you’re looking for. And while this may seem like a small thing, you now can use a keyboard shortcut to search the page.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2zxxPTNKamMqhTM53c5S4T/bf6f15b6117853d64fc8ad2cc9a1321e/image6-6.png" />
            
            </figure><p><b>Clarifying authentication</b>Once developers start writing code, you first have to handle authentication to start using the API. Authentication information is now readily available for every endpoint, and we link to the <a href="https://developers.cloudflare.com/fundamentals/api/get-started/">full developer docs about authentication</a> from the API overview page.</p><p><b>Adding examples</b>Good API docs have clear descriptions, but the best API docs share templates and examples to minimize a developer’s friction to deploying code. Every endpoint now includes an example and clearly indicates which parameters are required, removing yet another decision developers have to make when working with our API.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1YBLnCWZAaa8qZhr7KW3sh/9bf3db93a77aa24cf522e051354abb02/image2-34.png" />
            
            </figure><p><b>Gathering feedback and iterating</b>As we implemented all of these improvements, we kept some of our biggest users - our internal developers - informed along the way. We shared the test site early and often to get internal feedback, which caught bugs and helped us refine the site’s usability. The Discord and Community MVPs also volunteered to test the site, giving us valuable outside perspective on what we built. We incorporated all of that feedback to provide a vetted, deliberate UX at launch.</p>
    <div>
      <h3>How we built this</h3>
      <a href="#how-we-built-this">
        
      </a>
    </div>
    <p>Since this week is all about what you can build on our developer platform, we wanted to share the details about how this all works under the hood (hint: it’s mostly Workers).</p><p>We used a combination of open-source tools and Cloudflare products to revamp the API doc site. Previously the content on api.cloudflare.com was sourced from the JSON hyper-schema files that described our APIs, but over the years we repeatedly heard that published schemas would help you better integrate with Cloudflare. Several Cloudflare engineering teams started adopting the <a href="https://www.openapis.org/">OpenAPI specification</a>, and with a little research, planning, and testing, we pivoted from those JSON hyper-schemas to the OpenAPI framework. Check out the blog post about our <a href="/open-api-transition/">Transition to OpenAPI</a> for more details.</p><p>Because the OpenAPI specification defines how to describe APIs, our schema files now have consistency - not just among the various products, but also with an industry-accepted standard. Hundreds of documentation and code generation tools exist to pull from that standard, which means we have options that weren’t available for our homegrown JSON hyper-schemas.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7s01L8GzGtGQGhjN2lV0Xp/b8b82197cc1d9c1c2a44279508c4ec2e/image3-25.png" />
            
            </figure><p>We chose <a href="https://github.com/stoplightio/elements">Stoplight Elements</a>, an open-source React framework, for our site design because it has a clean layout and is easily customizable. While there are a number of both dynamic and static tools for parsing OpenAPI schemas and rendering documentation sites, we chose React because of its ubiquity, performance, and because it plays well with Cloudflare Pages, our deployment tool of choice. Within Stoplight you can generate code samples for a variety of  programming languages, like JavaScript, Java, and Python, as well as for tools like cURL, HTTPie, and wget.</p><p>We build and deploy the React application with <a href="https://pages.cloudflare.com/">Cloudflare Pages</a>, and using <a href="https://developers.cloudflare.com/pages/platform/functions/">Pages functions</a>, we optimize the OpenAPI schema file for Stoplight’s UI and cache it on Cloudflare’s network, reducing the latency needed to request the schema. Whenever teams add new API endpoints or definitions to the schema, we just update the schema file in GitHub. Because our API documentation loads the schema dynamically, this means we don’t have to wait for Cloudflare Pages to deploy a new version of the documentation site. The automation helps us ensure that everything we expose in the API is documented without manual interaction. Deploying with Pages gives us yet another opportunity to test our own products out on ourselves, helping us find areas for improvement that we turn around and pass along to you.</p>
    <div>
      <h3>Looking ahead</h3>
      <a href="#looking-ahead">
        
      </a>
    </div>
    <p>Moving our schemas to the OpenAPI specification allows us to use ready-to-go tools like Stoplight, but we’re just getting started. Soon we’ll be adding search functionality, letting you access all relevant information across developer, API, and support docs. The mobile experience will evolve, providing an even cleaner way to read API content when you’re on your phone. We’ll also add a “try it out” functionality to test out your requests right in the browser before writing your own code.</p><p>Over time, we want an even tighter integration between the API reference documentation, our how-to content in developer docs, and the Cloudflare dashboard. The standardized structure we get with the OpenAPI spec sets us up to reuse the schema files across our client libraries, Terraform, <a href="https://www.cloudflare.com/learning/security/api/what-is-an-api-gateway/">API gateway</a>, and Trakal. The consistency across API descriptions makes it easier for us to do things like localize API content, customize out-of-the-box documentation generation tools, and continue innovating like we always do.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/qgE1KAtlYwqWlrTXoVToz/8af187efed650ce369aff7fbda1a08fb/image1-41.png" />
            
            </figure>
    <div>
      <h3>We want to hear from you!</h3>
      <a href="#we-want-to-hear-from-you">
        
      </a>
    </div>
    <p>As you’re using the new <a href="https://developers.cloudflare.com/api">API doc site</a>, send us your <a href="https://docs.google.com/forms/d/e/1FAIpQLSfu46XUqWbabzDOhkIn5XCu7Wqufng_ouC4QB3qxScPge1ttA/viewform">feedback</a> and let us know if there are any feature improvements you’d like to see in the future. We want the site to be as useful as possible for your day-to-day interactions with Cloudflare’s API. We hope the improvements to our API doc experience will help you seamlessly use our API and efficiently deploy and maintain your Cloudflare products.</p><p>Thanks for your patience and perspective as we iterate on the API docs!</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <category><![CDATA[Technical Writing]]></category>
            <guid isPermaLink="false">2nISxLF3OKcbkhUcgOS2Kq</guid>
            <dc:creator>Claire Waters</dc:creator>
            <dc:creator>Kristian Freeman</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing new Cloudflare for SaaS documentation]]></title>
            <link>https://blog.cloudflare.com/introducing-new-cloudflare-for-saas-documentation/</link>
            <pubDate>Tue, 09 Aug 2022 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare for SaaS offers a suite of Cloudflare products and add-ons to improve the security, performance, and reliability of SaaS providers. Now, the Cloudflare for SaaS documentation outlines how to optimize it in order to meet your goals ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2i5rqkqFn7HJrwk36od0pM/df3914b54964a9d678cda9ab0fe97968/image3-4.png" />
            
            </figure><p>As a SaaS provider, you’re juggling many challenges while building your application, whether it’s custom domain support, protection from attacks, or maintaining an origin server. In 2021, we were proud to announce <a href="/cloudflare-for-saas/">Cloudflare for SaaS for Everyone</a>, which allows anyone to use Cloudflare to cover those challenges, so they can focus on other aspects of their business. This product has a variety of potential implementations; now, we are excited to announce a new section in our <a href="https://developers.cloudflare.com/">Developer Docs</a> specifically devoted to <a href="https://developers.cloudflare.com/cloudflare-for-saas/">Cloudflare for SaaS documentation</a> to allow you take full advantage of its product suite.</p>
    <div>
      <h3>Cloudflare for SaaS solution</h3>
      <a href="#cloudflare-for-saas-solution">
        
      </a>
    </div>
    <p>You may remember, from our <a href="/cloudflare-for-saas-for-all-now-generally-available/">October 2021 blog post</a>, all the ways that Cloudflare provides solutions for SaaS providers:</p><ul><li><p>Set up an origin server</p></li><li><p>Encrypt your customers’ traffic</p></li><li><p>Keep your customers online</p></li><li><p>Boost the performance of global customers</p></li><li><p>Support custom domains</p></li><li><p>Protect against attacks and bots</p></li><li><p>Scale for growth</p></li><li><p>Provide insights and analytics</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7LdxDeVHaUHAy19wdbLfVe/aaec3c62c1616d393a8af6c6daf270d0/image2-5.png" />
            
            </figure><p>However, we received feedback from customers indicating confusion around actually <i>using</i> the capabilities of Cloudflare for SaaS because there are so many features! With the existing documentation, it wasn’t 100% clear how to enhance security and performance, or how to support custom domains. Now, we want to show customers how to use Cloudflare for SaaS to its full potential by including more product integrations in the docs, as opposed to only focusing on the SSL/TLS piece.</p>
    <div>
      <h3>Bridging the gap</h3>
      <a href="#bridging-the-gap">
        
      </a>
    </div>
    <p>Cloudflare for SaaS can be overwhelming with so many possible add-ons and configurations. That’s why the new docs are organized into six main categories, housing a number of new, detailed guides (for example, WAF for SaaS and Regional Services for SaaS):</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5oI4ffuIoR47X455bljT6c/15422c36a5f9313c1113282577d913f2/image1-12.png" />
            
            </figure><p>Once you get your SaaS application up and running with the <a href="https://developers.cloudflare.com/cloudflare-for-saas/getting-started/">Get Started</a> page, you can find which configurations are best suited to your needs based on your priorities as a provider. Even if you aren’t sure what your goals are, this setup outlines the possibilities much more clearly through a number of new documents and product guides such as:</p><ul><li><p><a href="https://developers.cloudflare.com/cloudflare-for-saas/start/advanced-settings/regional-services-for-saas/">Regional Services for SaaS</a></p></li><li><p><a href="https://developers.cloudflare.com/analytics/graphql-api/tutorials/end-customer-analytics/">Querying HTTP events by hostname with GraphQL</a></p></li><li><p><a href="https://developers.cloudflare.com/cloudflare-for-saas/domain-support/migrating-custom-hostnames/">Migrating custom hostnames</a></p></li></ul><p>Instead of pondering over vague subsection titles, you can peruse with purpose in mind. The advantages and possibilities of Cloudflare for SaaS are highlighted instead of hidden.</p>
    <div>
      <h3>Possible configurations</h3>
      <a href="#possible-configurations">
        
      </a>
    </div>
    <p>This setup facilitates configurations much more easily to meet your goals as a SaaS provider.</p><p>For example, consider performance. Previously, there was no documentation surrounding reduced latency for SaaS providers. Now, the Performance section explains the automatic benefits to your performance by onboarding with Cloudflare for SaaS. Additionally, it offers three options of how to reduce latency even further through brand-new docs:</p><ul><li><p><a href="https://developers.cloudflare.com/cloudflare-for-saas/performance/early-hints-for-saas/">Early Hints for SaaS</a></p></li><li><p><a href="https://developers.cloudflare.com/cloudflare-for-saas/performance/cache-for-saas/">Cache for SaaS</a></p></li><li><p><a href="https://developers.cloudflare.com/cloudflare-for-saas/performance/argo-for-saas/">Argo Smart Routing for SaaS</a></p></li></ul><p>Similarly, the new organization offers <a href="https://developers.cloudflare.com/cloudflare-for-saas/security/waf-for-saas/">WAF for SaaS</a> as a previously hidden security solution, extending providers the ability to enable automatic protection from vulnerabilities and the flexibility to create custom rules. This is conveniently accompanied by a <a href="https://developers.cloudflare.com/cloudflare-for-saas/security/waf-for-saas/managed-rulesets/">step-by-step tutorial using Cloudflare Managed Rulesets</a>.</p>
    <div>
      <h3>What’s next</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>While this transition represents an improvement in the Cloudflare for SaaS docs, we’re going to expand its accessibility even more. Some tutorials, such as our <a href="https://developers.cloudflare.com/cloudflare-for-saas/security/waf-for-saas/managed-rulesets/">Managed Ruleset Tutorial</a>, are already live within the tile. However, more step-by-step guides for Cloudflare for SaaS products and add-ons will further enable our customers to take full advantage of the available product suite. In particular, keep an eye out for expanding documentation around using Workers for Platforms.</p>
    <div>
      <h3>Check it out</h3>
      <a href="#check-it-out">
        
      </a>
    </div>
    <p>Visit the new <a href="http://www.developers.cloudflare.com/cloudflare-for-saas">Cloudflare for SaaS tile</a> to see the updates. If you are a SaaS provider interested in extending Cloudflare benefits to your customers through Cloudflare for SaaS, visit our <a href="https://www.cloudflare.com/saas/">Cloudflare for SaaS overview</a> and our <a href="https://developers.cloudflare.com/cloudflare-for-saas/plans/">Plans page</a>.</p> ]]></content:encoded>
            <category><![CDATA[Technical Writing]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <category><![CDATA[Cloudflare for SaaS]]></category>
            <category><![CDATA[SSL]]></category>
            <category><![CDATA[SaaS]]></category>
            <category><![CDATA[Internship Experience]]></category>
            <guid isPermaLink="false">7cA2oDJgFIx7vyQyTY5Bk8</guid>
            <dc:creator>Mia Malden</dc:creator>
        </item>
        <item>
            <title><![CDATA[Working in public — our docs-as-code approach]]></title>
            <link>https://blog.cloudflare.com/our-docs-as-code-approach/</link>
            <pubDate>Fri, 15 Jul 2022 13:02:00 GMT</pubDate>
            <description><![CDATA[ Besides following a docs-as-code approach, at Cloudflare we handle our documentation changes in a public repository. The contributions we get from the entire Cloudflare community help us make our documentation better every day ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/TwjJUXzkKHfmcF3s6w9Jz/d4023afd682b833e7f075e352d857e11/image2-11.png" />
            
            </figure><p><a href="https://www.writethedocs.org/guide/docs-as-code/">Docs-as-code</a> is an approach to writing and publishing documentation with the same tools and processes developers use to create code. This philosophy has become more popular in recent years, especially in tech companies. Automatic link checking is part of this process, which ensures that writer's changes are sound and safe to deploy. By setting the stage with a docs-as-code approach, technical writers can focus on what they do best: ensure that our readers get useful and accurate information that is easy to find, and our documentation speaks a single language.</p><p>Besides following a docs-as-code approach, at Cloudflare we handle our documentation changes in public, in our <a href="https://github.com/cloudflare/cloudflare-docs"><code>cloudflare-docs</code> GitHub repository</a>. Having our documentation open to external contributions has helped us improve our documentation over time — our community is great at finding issues! While we need to review these contributions and ensure that they fit our style guide and content strategy, the contributions provided by the Cloudflare community have been instrumental in making our documentation better every day. While Cloudflare helps build a better Internet, our community helps build better documentation.</p>
    <div>
      <h2>Docs-as-code at Cloudflare</h2>
      <a href="#docs-as-code-at-cloudflare">
        
      </a>
    </div>
    <p>At Cloudflare, we follow a docs-as-code approach to create and publish product documentation in <a href="https://developers.cloudflare.com/">Developer Docs</a>.</p><p>Such an approach involves different components. We use Git with a <a href="https://github.com/cloudflare/cloudflare-docs">public GitHub repository</a> to keep track of changes and to handle branching and merging. We rely on GitHub Actions and Cloudflare Pages for <a href="https://www.cloudflare.com/learning/serverless/glossary/what-is-ci-cd/">continuous integration and delivery (CI/CD)</a>. Our continuous integration pipeline checks if the documentation builds successfully and if there are any broken links. Users, both internal and external, can preview the changes in each pull request, which means that collaborators don't have to set up local environments to preview the changes they're proposing. However, if they wish to do so, users can set up a local environment using open-source tools and create local builds of the documentation.</p><p>Following this docs-as-code strategy has a few advantages. We use well-known workflows that technical folks use on a daily basis. This makes it easier to get feedback from engineers, while still being simple enough to get contributions from less tech-inclined people in the company and from the general Cloudflare community. After reviewing and approving a contribution to the documentation, we can deploy those changes to the live documentation site with the click of a button. Thanks to <a href="/new-dev-docs/">recent changes in our documentation engine</a>, both deployments and local builds are fast, which helps increase our team's velocity. Additionally, it's safe to restructure parts of the documentation without being afraid of breaking stuff — our CI/CD pipeline ensures we don't have broken links.</p>
    <div>
      <h2>Our open source approach</h2>
      <a href="#our-open-source-approach">
        
      </a>
    </div>
    <p>It's possible to use a docs-as-code approach internally, using private repositories. However, we would not be extending some benefits of this approach to contributions provided by the larger Cloudflare community.</p><p>As a technical writer at Cloudflare, the great part about documentation-related work is that it’s done in our public GitHub repository. I can push changes to the <code>cloudflare-docs</code> GitHub repository with new or updated documentation that is then reviewed by my Cloudflare stakeholders, such as product managers and engineers.</p><p>Besides this work done together with other Cloudflare employees, I can also address issues and review pull requests from external stakeholders, since our documentation is open source. For example, pull request #4601 from an external contributor fixed an expression that was incorrect in the documentation:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/45JKRTKTgim1bHwWpStP4Z/41492383bf9acd90bb47632764fc31e7/image1-6.png" />
            
            </figure><p>Thanks to these contributions, we have been able to identify many issues, not just in the documentation but also in our products!</p><p>We handle these contributions as part of maintaining our own <a href="/content-as-a-product/">documentation product</a>, with its own bugs and feature requests. Issues and pull requests get assigned, prioritized, handled, and reviewed just like internal tickets – even though they're not all in the same backlog.</p><p>Our work is similar both for internal and external contributions. We review the proposed changes, making sure that the new or updated content follows our style guide and our content strategy. When required, we ask for technical validation of the content. Finally, we merge the changes when they're approved.</p><p>For issues that are not related to the documentation, we have a feedback mechanism in every documentation page that allows readers to provide feedback about the product itself. This information is then reviewed internally and addressed by the correct team.</p><p>For more information on how you can contribute to the documentation by creating an issue or a pull request, refer to the <a href="https://github.com/cloudflare/cloudflare-docs/blob/production/CONTRIBUTING.md">Contributing to Cloudflare's Documentation</a> page in our public GitHub repository.</p>
    <div>
      <h3>Keeping some secrets</h3>
      <a href="#keeping-some-secrets">
        
      </a>
    </div>
    <p>For content that we cannot disclose just yet, we currently have several approaches, depending on the exact technical writer and on the involved stakeholders.</p><p>In some situations, we work on a shared document where we receive and address direct feedback. Close to the feature release date, we create the corresponding Markdown version that we push to the public GitHub repository at the right time.</p><p>In other cases, we work in a private Git repository, getting early feedback using the same processes we have in place for our public repository. This method of handling non-public content is easy to implement because we're already following a docs-as-code approach. In this case, pushing the content to GitHub is a straightforward operation when the time comes — it's just a matter of pushing the branch to a different remote and creating a public pull request.</p>
    <div>
      <h2>What's next</h2>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>Much of our work is already done in public, but we can still improve. While we do provide <a href="https://github.com/cloudflare/cloudflare-docs/issues/new/choose">issue creation templates</a> and pull request guidelines, we'll eventually make our style guide and content strategy public. This will allow users to know in advance what we will check for (and enforce) for every contribution to the public documentation, making our review process more transparent.</p> ]]></content:encoded>
            <category><![CDATA[Technical Writing]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <guid isPermaLink="false">a2XwjA6PjyMyJVreRBXPu</guid>
            <dc:creator>Pedro Sousa</dc:creator>
        </item>
        <item>
            <title><![CDATA[We rebuilt Cloudflare's developer documentation - here's what we learned]]></title>
            <link>https://blog.cloudflare.com/new-dev-docs/</link>
            <pubDate>Fri, 27 May 2022 12:55:54 GMT</pubDate>
            <description><![CDATA[ In this blog post, we’ll cover the history of Cloudflare’s developer docs, why we made this recent transition, and why we continue to dogfood Cloudflare’s products as we develop applications internally ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We recently updated <code>developers.cloudflare.com</code>, the Cloudflare Developers documentation website, to a new version of our custom documentation engine. This change consisted of a significant migration from Gatsby to Hugo and converged a collection of Workers Sites into a single Cloudflare Pages instance. Together, these updates brought developer experience, performance, and quality of life improvements for our engineers, technical writers, and product managers.</p><p>In this blog post, we’ll cover the history of Cloudflare’s developer docs, why we made this recent transition, and why we continue to <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food">dogfood</a> Cloudflare’s products as we develop applications internally.</p>
    <div>
      <h3>What are Cloudflare’s Developer Docs?</h3>
      <a href="#what-are-cloudflares-developer-docs">
        
      </a>
    </div>
    <p>Cloudflare’s Developer Docs, which are <a href="https://github.com/cloudflare/cloudflare-docs/">open source on GitHub</a>, comprise documentation for all of Cloudflare’s products. The documentation is written by technical writers, product managers, and engineers at Cloudflare. Like many open source projects, contributions to the docs happen via Pull Requests (PRs). At time of writing, we have 1,600 documentation pages and have accepted almost 4,000 PRs, both from Cloudflare employees and external contributors in our community.</p><p>The underlying documentation engine we’ve used to build these docs has changed multiple times over the years. Documentation sites are often built with static site generators and, at Cloudflare, we’ve used tools like Hugo and Gatsby to <a href="https://blog.cloudflare.com/markdown-for-agents/">convert thousands of Markdown pages</a> into HTML, CSS, and JavaScript.</p><p>When we released the first version of our Docs Engine in mid-2020, we were excited about the facelift to our Developer Documentation site and the inclusion of dev-friendly features like dark mode and proper code syntax highlighting.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5UuLEAsx9i6dC7g3ai0LA9/b564d7bf89af2483abcf0f521f0a353f/image1-60.png" />
            
            </figure><p>Most importantly, we also used this engine to transition <i>all</i> of Cloudflare’s products with documentation onto a single engine. This allowed all Cloudflare product documentation to be developed, built, and deployed using the same core foundation. But over the next eighteen months and thousands of PRs, we realized that many of the architecture decisions we had made were not scaling.</p><p>While the user interface that we had made for navigating the documentation continued to receive great feedback from our users and product teams, decisions like using client-side rendering for docs had performance implications, especially on resource-constrained devices.</p><p>At the time, our decision to dogfood Workers Sites — which served as a precursor to Cloudflare Pages — meant that we could rapidly deploy our documentation across all of Cloudflare’s network in a matter of minutes. We implemented this by creating a separate Cloudflare Workers deployment for each product’s staging and production instances. Effectively, this meant that more than a hundred Workers were regularly updated, which caused significant headaches when trying to understand the causes and downstream effects of any failed deployments.</p><p>Finally, we struggled with our choice of underlying static site generator, Gatsby. We still think Gatsby is a great tool of choice for certain websites and applications, but we quickly found it to be the wrong match for our content-heavy documentation experience. Gatsby inherits many dependency chains to provide its featureset, but running the dependency-heavy toolchain locally on contributors’ machines proved to be an incredibly difficult and slow task for many of our documentation contributors.</p><p>When we did get to the point of deploying new docs changes, we began to be at the mercy of Gatsby’s long build times – in the worst case, almost an entire hour – just to compile Markdown and images into HTML. This negatively impacted our team’s ability to work quickly and efficiently as they improved our documentation. Ultimately, we were unable to find solutions to many of these issues, as they were core assumptions and characteristics of the underlying tools that we had chosen to build on — it was time for something new.</p><p>Built using Go, <a href="https://gohugo.io">Hugo</a> is incredibly fast at building large sites, has an active community, and is easily installable on a variety of operating systems. In our early discovery work, we found that Hugo would build our docs content in mere seconds. Since performance was a core motive for pursuing a rewrite, this was a significant factor in our decision.</p>
    <div>
      <h3>How we migrated</h3>
      <a href="#how-we-migrated">
        
      </a>
    </div>
    <p>When comparing frameworks, the most significant difference between Hugo and Gatsby – <i>from a user’s standpoint</i> – is the allowable contents of the Markdown files themselves. For example, Gatsby makes heavy use of <a href="https://mdxjs.com/">MDX</a>, allowing developers to author and import React components within their content pages. While this can be effective, MDX unfortunately is not CommonMark-compliant and, in turn, this means that its flavor of Markdown is <i>required</i> to be very flexible and permissive. This posed a problem when migrating to any other non-MDX-based solution, including Hugo, as these frameworks don’t grant the same flexibilities with Markdown syntax. Because of this, the largest technical challenge was converting the existing 1,600 markdown pages from MDX to a stricter, more standard Markdown variant that Hugo (or almost any framework) can interpret.</p><p>Not only did we have to convert 1,600 Markdown pages so that they’re rendered correctly by the new framework, we had to make these changes in a way that minimized the number of merge conflicts for when the migration itself was ready for deployment. There was a lot of work to be done as part of this migration – and work takes time! We could not stall or block the update cycles of the Developer Documentation repository, so we had to find a way to rename or modify <i>every single file</i> in the repository without gridlocking deployments for weeks.</p><p>The only way to solve this was through automation. We created <a href="https://github.com/cloudflare/cloudflare-docs/pull/3609/commits/2b16cd220f79c7cfd64d80f4a4592b73abcf0753">a migration script</a> that would apply all the necessary changes on the morning of the migration release day. Of course, this meant that we had to identify and apply the changes manually and then record that in JavaScript or Bash commands to make sweeping changes for the entire project.</p><p>For example, when migrating Markdown content, the migrator needs to take the file contents and parse them into an abstract syntax tree (AST) so that other functions can access, traverse, and modify a collection of standardized objects <i>representing</i> the content instead of resorting to a sequence string manipulations… which is scary and error-prone.</p><p>Since the project started with MDX, we needed a MDX-compatible parser which, in turn, produces its own AST with its own object standardizations. From there, one can “walk” – aka traverse – through the AST and add, remove, and/or edit objects and object properties. With the updated AST and a final traversal, a “stringifier” function can convert each object representation back to its string representation, producing updated file contents that differ from the original.</p><p>Below is an example snippet that utilizes <a href="https://www.npmjs.com/package/mdast-util-from-markdown"><code>mdast-util-from-markdown</code></a> and <a href="https://www.npmjs.com/package/mdast-util-to-markdown"><code>mdast-util-to-markdown</code></a> to create and stringify, respectively, the MDX AST and <a href="https://github.com/lukeed/astray"><code>astray</code></a> to traverse the AST with our custom modifications. For this example, we’re looking for <code>heading</code> and <code>anchor</code> nodes – both names are provided by the <code>mdast-*</code> utilities – so that we can read the primary header () text and ensure that all internal Developer Documentation links are consistent:</p>
            <pre><code>import * as fs from 'fs';
import * as astray from 'astray';
import { toMarkdown } from 'mdast-util-to-markdown';
import { fromMarkdown } from 'mdast-util-from-markdown';

/**
 * @param {string} file The "*.md" file path.
 */
export async function modify(file) {
  let content = await fs.promises.read(file, 'utf8');
  let AST = fromMarkdown(content);
  let title = '';

  astray.walk(AST, {
    /**
     * Read the page's &lt;h1&gt; to determine page's title.
     */
    heading(node) {
      // ignore if not &lt;h1&gt; header
      if (node.depth !== 1) return;

      astray.walk(node, {
        text(t: MDAST.Text) {
          // Grab the text value of the H1
          title += t.value;
        },
      });

      return astray.SKIP;
    },
    
    /**
     * Update all anchor links (&lt;a&gt;) for consistent internal linking.
     */
    link(node) {
      let value = node.url;
      
      // Ignore section header links (same page)
      if (value.startsWith('#')) return;

      if (/^(https?:)?\/\//.test(value)) {
        let tmp = new URL(value);
        // Rewrite our own "https://developers.cloudflare.com" links
        // so that they are absolute, path-based links instead.
        if (tmp.origin === 'https://developers.cloudflare.com') {
          value = tmp.pathname + tmp.search + tmp.hash;
        }
      }
      
      // ... other normalization logic ...
      
      // Update the link's `href` value
      node.url = value;
    }
  });
  
  // Now the AST has been modified in place.
  // AKA, the same `AST` variable is (or may be) different than before.
  
  // Convert the AST back to a final string.
  let updated = toMarkdown(AST);
  
  // Write the updated markdown file
  await fs.promises.writeFile(file, updated);
}</code></pre>
            <p><a href="https://gist.github.com/lukeed/d63a4561ce9859765d8f0e518b941642#file-cfblog-devdocs-0-js">https://gist.github.com/lukeed/d63a4561ce9859765d8f0e518b941642#file-cfblog-devdocs-0-js</a></p><p>The above is an abbreviated snippet of the modifications we needed to make during our migration. You may find all the AST traversals and manipulations we created as part of our migration <a href="https://github.com/cloudflare/cloudflare-docs/blob/2b16cd220f79c7cfd64d80f4a4592b73abcf0753/migrate/normalize.ts">on GitHub</a>.</p><p>We also took this opportunity to analyze the thousands and thousands of code snippets we have throughout the codebase. These serve an important role as they are crucial aides in reference documentation or are presented alongside tutorials as recipes or examples. So we added a <a href="https://github.com/cloudflare/cloudflare-docs/blob/ce64f4d28a6bff7de914d54623046384545e0048/bin/format.ts">code formatter script</a> that utilizes <a href="https://prettier.io/">Prettier</a> to apply a consistent code style across all code snippets. As a bonus side effect, Prettier would throw errors if any snippets had invalid syntax for their given language. Any of these were fixed manually and the `format` script has been added as part of our own CI process to ensure that all JavaScript, TypeScript, Rust, JSON, and/or C++ code we publish is syntactically valid!</p><p>Finally, we <a href="https://github.com/cloudflare/cloudflare-docs/blob/2b16cd220f79c7cfd64d80f4a4592b73abcf0753/migrate/Makefile#L7">created a Makefile</a> that coordinated the series of Node scripts and <code>git</code> commands we needed to make. This orchestrated the entire migration, boiling down all our work into a single <code>make run</code> command.</p><p>In effect, the majority of the <a href="https://github.com/cloudflare/cloudflare-docs/pull/3609">migration Pull Request</a> was the result of automated commits – over one million changes were applied across nearly 5,000 files in less than two minutes. With the help of product owners, we reviewed the newly generated documentation site and applied any fine-tuning adjustments where necessary.</p><p>Previously, with the Gatsby-based Workers Sites architecture, each Cloudflare product needed to be built and deployed as its own individual documentation site. These sites would then be managed and proxied by an umbrella Worker, listening on <code>developers.cloudflare.com</code>, which ensured that all requests were handled by the appropriate product-specific Worker Site. This worked well for our production needs, but made it complicated for contributors to replicate a similar setup during local development. With the move to Hugo, we were able to merge everything into a single project – in other words, 48 moving pieces became 1 single piece! This made it extremely easy to build and develop the entire Developer Docs locally, which is a big confidence booster when working.</p><p>A unified Hugo project also means that there’s only one build command and one deployable unit… This allowed us to move the Developer Docs to Cloudflare Pages! With Pages attached and configured for the GitHub repository, we immediately began making use of <a href="https://developers.cloudflare.com/pages/platform/preview-deployments/">preview deployments</a> as part of our PR review process and our <code>production</code> branch commits automatically queued new production deployments to the live site.</p>
    <div>
      <h3>Why we’re excited</h3>
      <a href="#why-were-excited">
        
      </a>
    </div>
    <p>After all the changes were in place, we ended up with a near-identical replica of the Developer Documentation site. However, upon closer inspection, a number of major improvements had been made:</p><ol><li><p>Our application now has fewer moving pieces for development <i>and</i> deployment, which makes it significantly easier to understand and onboard other contributors and team members.</p></li><li><p>Our development flow is a lot snappier and fully replicated the production behavior. This hugely increased our iteration speed and confidence.</p></li><li><p>Our application was now built as an HTML-first static site. Even though it was always a content site, we are now shipping 90% less JavaScript bytes, which means that our visitors’ browsers are doing less work to view the same content.</p></li></ol><p>The last point speaks to our web pages’ performance, which has real-world implications. These days, websites with faster page-load times are preferred over competitor sites with slower response times. This is true for human and bot users alike! In fact, this is so true that Google now <a href="https://developer.chrome.com/blog/search-ads-speed/">takes page speed into consideration</a> when ranking search results and offers tools like WebMasters and Lighthouse to help site owners track and improve their scores. Below, you can see the before-after comparison of our previous JS-first site to our HTML-first replacement:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FaGWaH2XlN9riYuoufZAQ/5978df6bf6a6299b62e75f1606058e9d/image2-55.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/60vizdQG71GVdLRHE12TyQ/f832833af15e2bd6200f07a9033a94dd/image3-40.png" />
            
            </figure><p>Here you can see that our <code>Performance</code> grade has significantly improved! It’s this figure, which is a weighted score of the Metrics like First Contentful Paint, that is tied to Page Speed. While this <i>does</i> have SEO impact, the <code>SEO</code> score in a Lighthouse report has to do with Google Crawler’s ability to parse and understand the page’s metadata. This remains unchanged because the content (and its metadata) were not changed as part of the migration.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Developer documentation is incredibly important to the success of any product. At Cloudflare, we believe that technical docs are a product – one that we can continue to iterate on, improve, and make more useful for our customers.</p><p>One of the most effective ways to improve documentation is to make it easier for our writers to contribute to them. With our new Documentation Engine, we’re giving our product content team the ability to validate content faster with instantaneous local builds. Preview links via Cloudflare Pages allows stakeholders like product managers and engineering teams the ability to quickly review what the docs will <i>actually</i> look like in production.</p><p>As we invest more into our build and deployment pipeline, we expect to further develop our ability to validate both the content and technical implementation of docs as part of review – tools like automatic spell checking, link validation, and visual diffs are all things we’d like to explore in the future.</p><p>Importantly, our documentation continues to be 100% open source. If you read Cloudflare’s developer documentation, and have feedback, feel free to <a href="https://github.com/cloudflare/cloudflare-docs/">check out the project on GitHub</a> and submit suggestions!</p> ]]></content:encoded>
            <category><![CDATA[Technical Writing]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <guid isPermaLink="false">4o47pQSmXUYk7med7nhGAM</guid>
            <dc:creator>Kristian Freeman</dc:creator>
            <dc:creator>Luke Edwards</dc:creator>
        </item>
        <item>
            <title><![CDATA[How we treat content as a product]]></title>
            <link>https://blog.cloudflare.com/content-as-a-product/</link>
            <pubDate>Thu, 26 May 2022 12:54:31 GMT</pubDate>
            <description><![CDATA[ Learn how the Product Content Experience team treats developer documentation and in-product content like a product ]]></description>
            <content:encoded><![CDATA[ <p></p><p>At Cloudflare, we talk a lot about how to help build a better Internet. On the Product Content Experience (PCX) team, we treat content like a product that represents and fulfills this mission. Our vision is to create world-class content that anticipates user needs and helps build accessible Cloudflare products. We believe we can impact the Cloudflare product experience and make it as wonderful as possible by intentionally designing, packaging, and testing the content.</p>
    <div>
      <h3>What is “content like a product”?</h3>
      <a href="#what-is-content-like-a-product">
        
      </a>
    </div>
    <p>I like taking on projects. A singular goal is met, and I clearly know I’m successful because the meaning of “done” is normally very clear. For example, I volunteer some of my time editing academic papers about technology. My role as an editor is temporary and there is a defined beginning and end to the work. I send my feedback and my task is largely complete.</p><p>“Content like a product” is when you shift your mindset from completing projects to maintaining a product, taking into consideration the user and their feedback. Product content at Cloudflare is an iterative, living, breathing thing. Inspired by the success of teams that adopt an agile mindset, along with some strategic functions you might find in a product management organization, treating content like a product means we treat content much like how a software project is created and maintained. This strategy allows for content development behaviors that closely align with the release of actual products, while also allowing technical writers and content designers to be laser-focused on doing what’s best for the user.</p>
    <div>
      <h3>Adopting a product development mindset</h3>
      <a href="#adopting-a-product-development-mindset">
        
      </a>
    </div>
    <p>When the content team was new, we initially adopted many traditional agile methodologies. Why agile? Before I joined Cloudflare I was a product owner and was a huge advocate for sprint planning, retrospectives, and daily stand-ups. I liked Agile — I could easily keep up with a technical team, focus on priorities, and get things done quickly and efficiently. However, the rigidity of agile was just a bit too much for a content team. Over time, we modified and chose our favorite parts of the methodology while letting the rest go.</p><p>Shifting to a product development process created a lot of flexibility, but we didn’t want to abandon all process. Situationally, we take a process-focused mindset. For writing tasks that need to be predictable and consistent, like choosing inclusive terminology throughout our documentation, we have automated and manual processes to ensure we’re following our best practices.</p><p>Aligning content to the product development process means that when a new product is shipping, we have <a href="https://developers.cloudflare.com/">developer documentation</a> ready to publish. Whenever the UI of the product changes, screenshots in the docs are updated accordingly. When new features are launched, we provide how-to guides and configuration content. Better alignment with the product team not only means the content team maintains accuracy of staying on top of all changes, it allows us to be user-focused. Above all, writers are aligned to the most important priority — shipping fast and often.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/68JgIRG9dlTa6XZEw3ctnn/aa215d5fe06083f533d77d2a3ec686ae/image1-59.png" />
            
            </figure>
    <div>
      <h3>Shipping content — fast!</h3>
      <a href="#shipping-content-fast">
        
      </a>
    </div>
    <p>As you know, Cloudflare ships fast. You can see just a small sample of what I mean by fast <a href="/2021-innovations-weeks/">here</a>, <a href="/welcome-security-week-2022/">here</a>, and <a href="/tag/cio-week/">here</a>. That speed was driven home within my first few weeks. I started just before Birthday Week 2020, and was super excited because I just wanted to jump in and create a lot of great content. But wow. What an intense start time. After Birthday Week, my main concerns were how to balance quality while meeting demand. I also wanted to create a quality environment for a team.</p><p>In retrospect, Birthday Week was a great time to start because it highlighted that keeping pace with products was going to be a big priority. Here’s how the content team met the demand.</p><p>First, the writers and I established that our focus was creating the most important content for the user, which allowed us to establish a product development mindset. We were now aligned with the product team.</p><p>Second, we moved content to an open source platform. This helped writers ship content fast because our authoring tools were consolidated to fewer platforms, and we were now in the same environment as our users.</p><p>We actually started publishing content as fast as products shipped within a few months! The content team began chipping away at the backlog once we understood the product team’s release cadence, and within less than six months we were ahead of the backlog and focusing on bigger initiatives including how to make content accessible, more consistent, and approachable to a wider group of users. It happened fast and was thrilling as a content creator.</p><p>The open source authoring tools on developers.cloudflare.com have evolved since 2020, continuing to help writers and contributors publish content faster by improving the review and build processes. We moved the docs platform to Cloudflare Pages earlier this year, allowing the writers to help build a more robust open source docs community while also providing valuable feedback to the Cloudflare Pages team.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Adopting a “content as a product” strategy requires buy-in from product managers and engineers, but it scales really well once established because everyone is focused on supporting the user versus the specifics of a content strategy itself. We go through the same planning, research, and analytics tasks you might find for a product to identify if we are creating the right content for folks who read the docs or use Cloudflare products. While everything we do with content is done so that we can create better content for our users, we also intentionally communicate that the content strategy is just a tool that enables a great user experience.</p><p>Over the next few weeks expect to see more about how Cloudflare writers have embraced the “content as a product” methodology as part of their own specific roles. In addition to learning more about how the <a href="https://developers.cloudflare.com/">developers.cloudflare.com</a> site was moved to Cloudflare Pages, writers will share how they leaned into content creation for an open source community, their journey from technical writer to UX writing and content design, and share more specifics about our content strategy including the customer journey and success metrics.</p><p>I’ll admit. I’m fortunate to work for a company with overwhelming support regarding content. Great documentation is important to so many folks, and we’ve created the type of writing environment I always wanted to be a part of. It’s an exciting time to be helping build a better Internet through excellent product content.</p> ]]></content:encoded>
            <category><![CDATA[Technical Writing]]></category>
            <category><![CDATA[Developer Documentation]]></category>
            <guid isPermaLink="false">4ADahoZnaUUeCqjMuySDFk</guid>
            <dc:creator>Kim Jeske</dc:creator>
        </item>
    </channel>
</rss>