One Markdown File, Two Worlds: How to Build Docs for Both Humans and AI Assistants A developer building LinkShift.app, a programmable redirect platform, created a single Markdown file that serves as a single source of truth for both human-readable documentation and AI assistant context. The rendering pipeline processes the file differently depending on the audience, using custom block directives like `:::ai-only` to include extra context for AI agents that remains hidden from human readers. This approach prevents the knowledge drift that typically occurs when maintaining separate knowledge bases for humans and AI assistants. When building a modern SaaS product with an AI assistant "Ask our docs" , you quickly hit a brutal realization about documentation design: The classic approach? Maintain two separate knowledge bases. One for humans a beautiful public CMS and one for AI prompts, vector databases, or markdown files tailored for the bot . The result? Both sources drift apart within exactly one week. In our project, we took a different route. We write exactly one Markdown file , but our rendering pipeline processes it differently depending on whether it’s being read by a human in a browser or ingested by an AI agent into our RAG Retrieval-Augmented Generation context. Here is how we built the simplest possible Single Source of Truth SSoT for both humans and AI. We are building LinkShift.app https://linkshift.app/ — a programmable redirect platform. Think of it as a smart layer on the edge where you define traffic routing using rules, dynamic link maps, and regex, instead of hard-coding messy redirects in your app or CDN. For a developer tool like this, documentation isn't just an afterthought; it's a core feature. Our users build complex routing logic, so the UI needs to be crystal clear. At the same time, our AI assistant must understand the deep mechanics behind our rules engine, batch simulations, and fallback scenarios. We simply couldn't afford a knowledge gap between what the developer reads and what our AI knows. Our MarkdownRendererComponent built with Angular and the marked parser is not just a dumb Markdown-to-HTML translator. Before the text ever hits the screen, it goes through a lightweight pre-processing pass. The entire process is controlled using simple, custom block directives :::block-name . Here is how the roles are split depending on who the audience is: | Document Element | Human Reader Docs UI | AI Assistant RAG Context | |---|---|---| Standard Markdown | ✅ Yes Rendered to HTML | ✅ Yes Raw text | Infoboxes :::info | ✅ Yes Styled callouts | ✅ Yes Textual context | Mermaid Diagrams | ✅ Yes Graphical render | ✅ Yes Raw text flow syntax | Hidden from Humans :::ai-only | ❌ Hidden CSS display: none | ✅ Yes Full text for LLM | Author Scratchpad :::hidden-on-purpose | ❌ Stripped entirely | ❌ Stripped entirely | For the technical writer or developer, it’s still just a standard .md file in the Git repository. However, they get to use a few "superpowers." :::ai-only This is the secret sauce. This is where we drop extra context that would feel repetitive or bloated to a human engineer, but is absolute gold for an LLM. python API Integration To import domains, you need to hit the POST /domains endpoint. :::ai-only ⚠️ Context for the bot: Remember to instruct the user that before calling POST /domains , they MUST first generate an organization token via /auth/org-token , otherwise they will receive a 403. Humans have this covered in the "Quickstart" section, but remind them in the chat if they ask about 403 errors. ::: How it works: