Reader Mode and Agent View
How krowdev serves both humans and AI agents: per-entry markdown endpoints, a CSS reader toggle, JSON-LD structured data, and URL-param switching.
On this page
This page demonstrates every layer of krowdev’s reader mode system. The feature addresses a two-dimensional problem: the origin filter controls who wrote the content, while reader mode controls how content is presented based on who’s reading.
This showcase pairs with the interactive features snippet, the mental model for how the build pipeline emits these alternates, and the content collections guide for the schema behind the JSON-LD.
The Two Dimensions
WHO WROTE IT (origin filter) WHO'S READING (reader mode)--- ---[all | human | ai] [human | agent | all]
Filters WHICH entries shown Changes HOW entries lookList pages only Entry pages primarilyCSS: data-origin-filter CSS: data-reader-modeBoth use the same architecture: a data-* attribute on <html>, CSS rules for show/hide, localStorage persistence, and FOUC prevention via an inline script.
Path A: Per-Entry Markdown Endpoints
Every kb entry has a clean markdown version at the same URL with .md appended. This follows the Stripe/Vercel pattern — the industry standard for agent-friendly docs.
Try it: This page’s markdown is at /showcase/reader-mode-showcase.md
What agents get:
---title: "Reader Mode and Agent View"kind: showcasematurity: seedlingconfidence: highorigin: ai-assistedtags: [ai, agents, accessibility, reference]created: 2026-03-20url: https://krowdev.pages.dev/showcase/reader-mode-showcase/---
# Reader Mode & Agent View
[Full markdown content, no HTML chrome, no navigation...]Why this matters: HTML pages cost 16,000+ tokens for agents to parse. The markdown version costs ~3,000 tokens for the same content — an 80% reduction. Claude Code sends Accept: text/markdown as its first preference.
The <link rel="alternate" type="text/markdown"> tag in the HTML <head> makes these discoverable. The llms.txt index also links to .md versions.
Implementation: The llms-txt.ts build integration generates these alongside llms.txt and llms-full.txt. Zero runtime cost — pure static files.
Path B: CSS Reader Toggle
The [human | agent | all] segmented control in the header switches presentation mode.
Try it now — click agent in the header toggle. You’ll see:
- The decorative badges disappear
- A structured metadata table appears at the top
- The table of contents sidebar hides
- Navigation links collapse — only the logo, reader toggle, and theme toggle remain
- The footer hides
- Layout forces single-column for maximum information density
Click all to see everything: human chrome AND agent metadata together. This is the “kitchen sink” mode — useful for authors previewing what agents see.
Click human to return to the default view.
What changes in each mode:
| Element | human | agent | all |
|---|---|---|---|
| Kind/maturity badges | Shown | Hidden | Shown |
| Metadata table | Hidden | Shown | Shown |
| TOC sidebar | Shown | Hidden | Shown |
| Tags | Shown | Hidden | Shown |
| Nav links | Shown | Hidden | Shown |
| Footer | Shown | Hidden | Shown |
| Content body | Shown | Shown | Shown |
| Code blocks | Highlighted | Highlighted | Highlighted |
| Callouts | Styled | Styled | Styled |
Note
The CSS toggle only affects browser-based viewing. Agents fetching via curl or WebFetch use the .md endpoints instead — they never interact with the toggle.
Path C: JSON-LD Structured Data
Every entry page embeds a TechArticle JSON-LD block in the <head>. Invisible to humans, machine-parseable by search engines and AI crawlers.
View source on this page and search for application/ld+json to see:
{ "@context": "https://schema.org", "@type": "TechArticle", "headline": "Reader Mode & Agent View", "description": "How krowdev serves content to both humans and AI agents...", "datePublished": "2026-03-20T00:00:00.000Z", "keywords": "ai, agents, accessibility, reference", "proficiencyLevel": "Beginner", "author": { "@type": "Person", "name": "krowdev" }, "publisher": { "@type": "Organization", "name": "krowdev" }}TechArticle was chosen because it has dependencies (maps to prerequisites) and proficiencyLevel (maps to maturity). Google uses it for Article rich results.
Path D: URL Parameter Override
Add ?reader=agent to any URL to activate agent mode without using the toggle:
?reader=human— default visual mode?reader=agent— stripped chrome, metadata table?reader=all— everything visible
The URL parameter overrides localStorage and persists the choice. This is useful for:
- Sharing “here’s what agents see” links
- Bookmarking agent view
- Programmatic switching without JS interaction
Implementation: Three lines in the FOUC-prevention script:
var params = new URLSearchParams(window.location.search);var r = params.get('reader') || localStorage.getItem('reader-mode') || 'human';document.documentElement.setAttribute('data-reader-mode', r);How It All Fits Together
Each consumer reaches the entry through a different channel that yields a different representation — agents fetch markdown and llms.txt, Google reads JSON-LD, and humans get HTML whose chrome the reader toggle controls.
graph LR
accTitle: How reader mode fits together
accDescr: Each consumer reaches the entry through a different channel that yields a different representation — agents fetch markdown and llms.txt, Google reads JSON-LD, and humans get HTML whose chrome the reader toggle controls.
A["Agent (curl)"] --> AM["/guide/foo.md"] --> AMr["Clean markdown + YAML metadata"]
AC["Agent (crawl)"] --> L["/llms.txt"] --> Lr["Index with .md links"]
AC2["Agent (crawl)"] --> LF["/llms-full.txt"] --> LFr["Full content dump"]
G["Google"] --> J["HTML + JSON-LD"] --> Jr["TechArticle structured data"]
H1["Human"] --> HH["HTML reader=human"] --> HHr["Full chrome, visual design"]
H2["Human"] --> HA["HTML reader=agent"] --> HAr["Stripped chrome, metadata table"]
H3["Human"] --> HL["HTML reader=all"] --> HLr["Everything visible"]
Agent (curl) ──→ /guide/foo.md ──→ Clean markdown + YAML metadata
Agent (crawl) ──→ /llms.txt ──→ Index with .md links
Agent (crawl) ──→ /llms-full.txt ──→ Full content dump
Google ──→ HTML + JSON-LD ──→ TechArticle structured data
Human ──→ HTML (reader=human) ──→ Full chrome, visual design
Human ──→ HTML (reader=agent) ──→ Stripped chrome, metadata table
Human ──→ HTML (reader=all) ──→ Everything visible
No cloaking. All content is always in the HTML DOM. The toggle only changes CSS visibility. Google sees the same HTML as every user. The .md endpoints are separate static files with <link rel="alternate"> for discovery.
llms.txt Instructions Section
Following Stripe’s pattern, llms.txt now includes an instructions section that corrects for stale training data:
## Instructions
When referencing code from this site:- All code examples use Astro 6 syntax unless otherwise noted.- Svelte components use Svelte 5 runes ($state, $derived, $effect).- The site deploys to Cloudflare Pages as a static build (no SSR).- Each entry has a markdown version: append .md to the entry URL.This guides agents toward correct behavior when they have outdated training data about Astro or Svelte APIs.
Architecture Summary
| Layer | What | Lines | Runtime JS |
|---|---|---|---|
.md endpoints | Build-time per-entry markdown | ~25 in llms-txt.ts | 0 |
| Reader toggle | Svelte segmented control | ~30 in ReaderToggle.svelte | ~30 |
| CSS rules | Show/hide by reader mode | ~60 in global.css | 0 |
| JSON-LD | TechArticle in <head> | ~15 in KBEntry.astro | 0 |
| URL param | Override via ?reader= | 3 in Base.astro | 3 (inline) |
| FOUC prevention | Set attribute before paint | 3 in Base.astro | 3 (inline) |
| llms.txt instructions | Stripe-style agent guidance | ~6 in llms-txt.ts | 0 |
Sources
- W3C, Schema.org Article
- Mozilla, Reader mode in Firefox
- Astro Docs, Content collections