{
  "name": "Denote",
  "pages": [
    {
      "slug": "ai-native",
      "title": "AI Native",
      "description": "How Denote makes your documentation a first-class data source for AI agents",
      "aiSummary": "Denote serves docs to both humans and AI agents. Three layers of AI access - llms.txt for discovery, JSON API for structured data and RAG pipelines, and MCP server for live tool integration with Cursor, Claude, and ChatGPT. All auto-generated from markdown, zero config.",
      "aiKeywords": [
        "ai",
        "llms.txt",
        "mcp",
        "json-api",
        "rag",
        "embeddings",
        "cursor",
        "claude",
        "chatgpt"
      ],
      "content": "\n# AI Native\n\n> **See also:** The [API Reference](/docs/api) documents the specific endpoints\n> (JSON API, llms.txt) mentioned on this page.\n\nEvery Denote site is designed to serve two audiences: humans browsing your docs,\nand AI agents consuming your knowledge programmatically.\n\n## Why It Matters\n\nAI coding assistants like Cursor, Claude, and ChatGPT are now the primary way\nmany developers interact with documentation. When someone asks \"how do I\nconfigure X?\", the AI needs to find and read your docs — fast, accurately, and\nin a format it understands.\n\nMost documentation frameworks treat AI access as an afterthought. Denote builds\nit in from day one.\n\n## Three Layers of AI Access\n\n### 1. llms.txt — AI Discovery\n\nEvery Denote site auto-generates `/llms.txt` following the\n[llms.txt standard](https://llmstxt.org/). This is a curated index of your\ndocumentation that tells AI agents what's available and where to find it.\n\n```text\n# My Project\n\n> Project documentation\n\n## Docs\n\n- [Introduction](https://docs.example.com/docs/introduction): Getting started guide\n- [API Reference](https://docs.example.com/docs/api): Complete API documentation\n```\n\nThere's also `/llms-full.txt` — your entire documentation concatenated into a\nsingle file, optimized for context windows.\n\n### 2. JSON API — Structured Data\n\nThe `/api/docs` endpoint serves your documentation as structured JSON, ready for\nRAG pipelines, embedding generation, or direct context injection:\n\n```json\n{\n  \"name\": \"My Project\",\n  \"pages\": [\n    {\n      \"slug\": \"introduction\",\n      \"title\": \"Introduction\",\n      \"description\": \"Getting started guide\",\n      \"content\": \"# Introduction\\n\\nWelcome to...\",\n      \"headings\": [\n        { \"level\": 1, \"title\": \"Introduction\", \"id\": \"introduction\" }\n      ]\n    }\n  ]\n}\n```\n\n### 3. MCP Server — Live Tool Access\n\nThe built-in [MCP](https://modelcontextprotocol.io/) server turns your docs into\ntools that AI agents can search and read on demand.\n\nEnable it in your config:\n\n```typescript\n// denote.config.ts\nexport const config = {\n  // ... other config\n  ai: {\n    mcp: true,\n  },\n};\n```\n\n## MCP on Your Deployed Site\n\nWhen `mcp: true` is set, your **deployed docs site itself becomes an MCP\nendpoint** at `/mcp`. No local setup needed — AI agents connect directly to your\nlive docs URL.\n\nThis is the key differentiator: your documentation site isn't just web pages,\nit's a live API that any MCP-compatible tool can query.\n\nPoint any MCP client to your site's `/mcp` endpoint:\n\n```json\n{\n  \"mcpServers\": {\n    \"my-docs\": {\n      \"url\": \"https://docs.example.com/mcp\"\n    }\n  }\n}\n```\n\nThe endpoint supports Streamable HTTP with full CORS, so it works from any\norigin.\n\n## Local MCP\n\nDuring local development, point your MCP client at your dev server's `/mcp`\nendpoint:\n\n```json\n{\n  \"mcpServers\": {\n    \"my-docs\": {\n      \"url\": \"http://localhost:8000/mcp\"\n    }\n  }\n}\n```\n\n## Available Tools and Resources\n\nThe MCP server exposes tools for searching, reading, and dumping your docs, plus\nresources for listing and accessing individual pages. See the\n[API Reference — MCP Server](/docs/api#mcp-server) for the full list of tools\nand resources.\n\n## Content Tags\n\nUse frontmatter fields to improve AI understanding of your pages:\n\n```yaml\n---\ntitle: Authentication\nai-summary: OAuth2 and API key auth with JWT tokens, refresh flows, and scoped permissions.\nai-keywords:\n  - authentication\n  - oauth2\n  - jwt\n---\n```\n\nSee [Writing Content](/docs/content) for full details on AI content tags.\n\n## Zero Configuration\n\nAll AI endpoints are generated automatically from your Markdown files. No\nplugins, no API keys, no indexing pipeline. Write your docs, and the AI layer\njust works.\n\n## Next Steps\n\n- [API Reference](/docs/api) — Full endpoint documentation for JSON API, MCP,\n  and llms.txt\n- [Writing Content](/docs/content) — Frontmatter fields including AI content\n  tags\n- [Configuration](/docs/configuration) — Enable MCP and other AI options\n",
      "headings": [
        {
          "level": 1,
          "title": "AI Native",
          "id": "ai-native"
        },
        {
          "level": 2,
          "title": "Why It Matters",
          "id": "why-it-matters"
        },
        {
          "level": 2,
          "title": "Three Layers of AI Access",
          "id": "three-layers-of-ai-access"
        },
        {
          "level": 3,
          "title": "1. llms.txt — AI Discovery",
          "id": "1-llmstxt--ai-discovery"
        },
        {
          "level": 3,
          "title": "2. JSON API — Structured Data",
          "id": "2-json-api--structured-data"
        },
        {
          "level": 3,
          "title": "3. MCP Server — Live Tool Access",
          "id": "3-mcp-server--live-tool-access"
        },
        {
          "level": 2,
          "title": "MCP on Your Deployed Site",
          "id": "mcp-on-your-deployed-site"
        },
        {
          "level": 2,
          "title": "Local MCP",
          "id": "local-mcp"
        },
        {
          "level": 2,
          "title": "Available Tools and Resources",
          "id": "available-tools-and-resources"
        },
        {
          "level": 2,
          "title": "Content Tags",
          "id": "content-tags"
        },
        {
          "level": 2,
          "title": "Zero Configuration",
          "id": "zero-configuration"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "api",
      "title": "API Reference",
      "description": "REST API endpoints for programmatic access to your documentation",
      "aiSummary": "REST API endpoints for programmatic access. GET /api/docs returns structured JSON, GET /api/search returns the search index, GET /llms.txt and /llms-full.txt provide AI-optimized markdown, serves MCP protocol over Streamable HTTP.",
      "aiKeywords": [
        "API",
        "REST",
        "JSON",
        "search index",
        "llms.txt",
        "MCP",
        "endpoints",
        "programmatic access",
        "structured data"
      ],
      "content": "\n# API Reference\n\n> **See also:** [AI Native](/docs/ai-native) explains the design philosophy\n> behind these endpoints and how AI agents use them.\n\nEvery Denote site exposes several API endpoints for programmatic access. These\nare available automatically — no configuration required.\n\n## Endpoints\n\n### GET /api/docs\n\nReturns all documentation pages as structured JSON.\n\n```bash\ncurl https://your-docs.com/api/docs\n```\n\n**Response:**\n\n```json\n{\n  \"name\": \"My Project\",\n  \"pages\": [\n    {\n      \"slug\": \"introduction\",\n      \"title\": \"Introduction\",\n      \"description\": \"Welcome to the project\",\n      \"aiSummary\": \"One-line summary from ai-summary frontmatter\",\n      \"aiKeywords\": [\"keyword1\", \"keyword2\"],\n      \"content\": \"# Introduction\\n\\nFull markdown content...\",\n      \"headings\": [\n        { \"level\": 1, \"title\": \"Introduction\", \"id\": \"introduction\" },\n        { \"level\": 2, \"title\": \"Quick Start\", \"id\": \"quick-start\" }\n      ]\n    }\n  ],\n  \"llmsFullTxt\": \"https://your-docs.com/llms-full.txt\",\n  \"mcp\": {\n    \"endpoint\": \"https://your-docs.com/mcp\",\n    \"transport\": \"Streamable HTTP\",\n    \"tools\": [\"search_docs\", \"get_doc\", \"get_all_docs\"]\n  }\n}\n```\n\n### GET /api/search\n\nReturns a serialized [MiniSearch](https://lucaong.github.io/minisearch/) index\nfor client-side full-text search. The index includes all pages with titles,\ndescriptions, content, and AI metadata. It supports fuzzy matching, prefix\nsearch, and field boosting (titles are weighted 4x, descriptions 2x).\n\n```bash\ncurl https://your-docs.com/api/search\n```\n\nThe response is a MiniSearch JSON object (not a flat array of documents). The\nSearch island fetches this on first `Cmd+K` open and deserializes it with\n`MiniSearch.loadJSON()` for instant client-side search.\n\n### GET /llms.txt\n\nReturns an AI-readable index of your documentation following the\n[llms.txt standard](https://llmstxt.org/).\n\n```bash\ncurl https://your-docs.com/llms.txt\n```\n\n**Response:**\n\n```text\n# My Project\n\n> Project documentation\n\n## Docs\n\n- [Introduction](https://your-docs.com/docs/introduction): Welcome to the project\n- [Installation](https://your-docs.com/docs/installation): How to install\n\n## API\n\n- [Full docs as markdown](https://your-docs.com/llms-full.txt): Complete documentation\n- [Structured JSON](https://your-docs.com/api/docs): All pages as JSON\n```\n\n### GET /llms-full.txt\n\nReturns your entire documentation concatenated into a single markdown file.\nDesigned for loading into AI context windows.\n\n```bash\ncurl https://your-docs.com/llms-full.txt\n```\n\nThis is useful for:\n\n- Feeding full project context to an LLM\n- Building RAG pipelines\n- Generating embeddings across all your docs\n\n## MCP Server\n\nFor richer AI integration, Denote includes a built-in\n[Model Context Protocol](https://modelcontextprotocol.io/) server. See the\n[AI Native](/docs/ai-native) page for setup instructions.\n\n### MCP Tools\n\n| Tool           | Description                                          |\n| -------------- | ---------------------------------------------------- |\n| `search_docs`  | Fuzzy search with prefix matching and field boosting |\n| `get_doc`      | Get full content of a page by slug                   |\n| `get_all_docs` | Get entire documentation as one text block           |\n\n### MCP Resources\n\n| Resource        | Description                               |\n| --------------- | ----------------------------------------- |\n| `docs://index`  | List of all available documentation pages |\n| `docs://{slug}` | Content of a specific documentation page  |\n\n## Custom Endpoints\n\nRegister custom API routes on the Fresh app instance in your `main.ts`. The\n`app` returned by `denote()` is a standard Fresh app, so you can add routes with\n`app.get()`, `app.post()`, etc.:\n\n```typescript\n// main.ts\nimport { denote } from \"@denote/core\";\nimport { config } from \"./denote.config.ts\";\n\nexport const app = denote({ config });\n\napp.get(\"/api/custom\", (ctx) => {\n  return new Response(JSON.stringify({ hello: \"world\" }), {\n    headers: { \"Content-Type\": \"application/json\" },\n  });\n});\n```\n\n## Fresh\n\nDenote is built on [Fresh](https://fresh.deno.dev/docs/). For details on\nrouting, middleware, and app configuration, see the\n[Fresh documentation](https://fresh.deno.dev/docs/).\n\n## Next Steps\n\n- [AI Native](/docs/ai-native) — Design philosophy behind these endpoints\n- [Custom Pages](/docs/custom-pages) — Add standalone routes to your app\n- [Deployment](/docs/deployment) — Deploy to Deno Deploy or Docker\n",
      "headings": [
        {
          "level": 1,
          "title": "API Reference",
          "id": "api-reference"
        },
        {
          "level": 2,
          "title": "Endpoints",
          "id": "endpoints"
        },
        {
          "level": 3,
          "title": "GET /api/docs",
          "id": "get-apidocs"
        },
        {
          "level": 3,
          "title": "GET /api/search",
          "id": "get-apisearch"
        },
        {
          "level": 3,
          "title": "GET /llms.txt",
          "id": "get-llmstxt"
        },
        {
          "level": 3,
          "title": "GET /llms-full.txt",
          "id": "get-llms-fulltxt"
        },
        {
          "level": 2,
          "title": "MCP Server",
          "id": "mcp-server"
        },
        {
          "level": 3,
          "title": "MCP Tools",
          "id": "mcp-tools"
        },
        {
          "level": 3,
          "title": "MCP Resources",
          "id": "mcp-resources"
        },
        {
          "level": 2,
          "title": "Custom Endpoints",
          "id": "custom-endpoints"
        },
        {
          "level": 2,
          "title": "Fresh",
          "id": "fresh"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "components",
      "title": "Components",
      "description": "Built-in UI components and interactive islands in Denote",
      "aiSummary": "Built-in server components (Header, Sidebar, DocsLayout, PageLayout, EditLink) and Preact islands (Search, CollapsibleNav, ActiveToc, ThemeToggle, CopyButton, MobileMenu) with their props and behavior.",
      "aiKeywords": [
        "components",
        "islands",
        "Header",
        "Sidebar",
        "Search",
        "ThemeToggle",
        "CollapsibleNav",
        "ActiveToc",
        "CopyButton",
        "Preact"
      ],
      "content": "\n# Components\n\nDenote includes several built-in components that enhance the documentation\nexperience. These are a mix of server-rendered components and interactive\nislands (client-side JavaScript).\n\n## Navigation Components\n\n### Breadcrumbs\n\nBreadcrumbs appear automatically above each page title, showing the navigation\npath (e.g., **Getting Started > Installation**). They're generated from your\n`denote.config.ts` navigation structure.\n\n### Collapsible Sidebar\n\nThe sidebar navigation supports collapsible sections. Click the chevron arrow\nnext to any section title to expand or collapse it. Your preferences are saved\nin `localStorage` and persist across page loads.\n\n### Previous / Next Navigation\n\nLinks to the previous and next pages appear at the bottom of each doc page. The\norder is determined by your navigation configuration in `denote.config.ts`.\n\n## Interactive Islands\n\nDenote uses Fresh's island architecture to ship JavaScript only where needed:\n\n### Search (⌘K)\n\nPress `⌘K` (or `Ctrl+K`) to open the search modal. Powered by\n[MiniSearch](https://lucaong.github.io/minisearch/), it provides ranked\nfull-text search across titles, descriptions, content, and AI metadata with\nfuzzy and prefix matching. The search index is lazily fetched from `/api/search`\non first open and cached for instant subsequent use. Navigate results with arrow\nkeys and press Enter to select.\n\n### Active Table of Contents\n\nThe right sidebar shows the current page's headings and highlights the active\nsection as you scroll. This uses client-side scroll tracking to update in real\ntime.\n\n### Copy Button on Code Blocks\n\nEvery code block has a copy button that appears on hover. Click the clipboard\nicon to copy the code to your clipboard. A checkmark confirms the copy was\nsuccessful.\n\n### Theme Toggle\n\nToggle between light and dark mode using the sun/moon icon in the header. Your\npreference is saved in `localStorage`.\n\n### Mobile Menu\n\nOn smaller screens, the sidebar collapses into a hamburger menu accessible from\nthe header.\n\n## Next Steps\n\n- [Theming & Styling](/docs/theming) — Customize colors, dark mode, and CSS\n  variables\n- [Custom Pages](/docs/custom-pages) — Add standalone pages outside the docs\n  layout\n",
      "headings": [
        {
          "level": 1,
          "title": "Components",
          "id": "components"
        },
        {
          "level": 2,
          "title": "Navigation Components",
          "id": "navigation-components"
        },
        {
          "level": 3,
          "title": "Breadcrumbs",
          "id": "breadcrumbs"
        },
        {
          "level": 3,
          "title": "Collapsible Sidebar",
          "id": "collapsible-sidebar"
        },
        {
          "level": 3,
          "title": "Previous / Next Navigation",
          "id": "previous--next-navigation"
        },
        {
          "level": 2,
          "title": "Interactive Islands",
          "id": "interactive-islands"
        },
        {
          "level": 3,
          "title": "Search (⌘K)",
          "id": "search-k"
        },
        {
          "level": 3,
          "title": "Active Table of Contents",
          "id": "active-table-of-contents"
        },
        {
          "level": 3,
          "title": "Copy Button on Code Blocks",
          "id": "copy-button-on-code-blocks"
        },
        {
          "level": 3,
          "title": "Theme Toggle",
          "id": "theme-toggle"
        },
        {
          "level": 3,
          "title": "Mobile Menu",
          "id": "mobile-menu"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "configuration",
      "title": "Configuration",
      "description": "Configure your Denote documentation site",
      "aiSummary": "Configure Denote via denote.config.ts. Covers site name, navigation tree, colors, fonts, layout, SEO metadata, analytics, social links, landing page, and AI features (MCP, llms.txt).",
      "aiKeywords": [
        "config",
        "denote.config.ts",
        "navigation",
        "colors",
        "fonts",
        "SEO",
        "analytics",
        "landing page",
        "MCP",
        "DenoteConfig"
      ],
      "content": "\n# Configuration\n\nDenote is configured through the `denote.config.ts` file in your project root.\n\n## Basic Configuration\n\n```typescript\nimport type { DenoteConfig } from \"@denote/core\";\n\nexport const config: DenoteConfig = {\n  name: \"My Documentation\",\n  logo: {\n    light: \"/logo.svg\", // Image logo\n    dark: \"/logo-dark.svg\", // Dark mode variant\n    text: \"mysite\", // Text logo (overrides name in header)\n    suffix: \".dev\", // Styled suffix in primary color\n  },\n  favicon: \"/favicon.ico\",\n};\n```\n\n## Navigation\n\nThe navigation structure defines your sidebar and breadcrumbs:\n\n```typescript\nexport const config: DenoteConfig = {\n  navigation: [\n    {\n      title: \"Getting Started\",\n      children: [\n        { title: \"Introduction\", href: \"/docs/introduction\" },\n        { title: \"Installation\", href: \"/docs/installation\" },\n      ],\n    },\n    {\n      title: \"Guides\",\n      children: [\n        { title: \"Writing Content\", href: \"/docs/content\" },\n        { title: \"Components\", href: \"/docs/components\" },\n      ],\n    },\n  ],\n};\n```\n\nNavigation sections are collapsible in the sidebar — users can click the chevron\nto expand or collapse them. Their preferences persist across page loads.\n\nThe navigation order also determines the **previous/next** page links at the\nbottom of each doc page and the **breadcrumb trail** shown above the title.\n\n## Colors\n\nCustomize your brand colors:\n\n```typescript\nexport const config: DenoteConfig = {\n  colors: {\n    primary: \"#6366f1\", // Links, buttons, accents\n    accent: \"#22c55e\", // Secondary accent\n  },\n};\n```\n\nFor full control over surfaces, text, and borders:\n\n```typescript\nexport const config: DenoteConfig = {\n  colors: {\n    primary: \"#6366f1\",\n    accent: \"#22c55e\",\n    background: \"#ffffff\", // Page background\n    surface: \"#f9fafb\", // Cards, sidebar\n    text: \"#111827\", // Body text\n    border: \"#e5e7eb\", // Borders\n    dark: {\n      primary: \"#818cf8\",\n      background: \"#030712\",\n      surface: \"#0a0a0a\",\n      text: \"#f9fafb\",\n      border: \"#1f2937\",\n    },\n  },\n};\n```\n\nSee the [Theming guide](/docs/theming) for the full list of design tokens and\nhow auto-derivation works.\n\n## Layout\n\nControl dimensions and visibility of layout elements:\n\n```typescript\nexport const config: DenoteConfig = {\n  layout: {\n    sidebarWidth: 280, // Sidebar width in px\n    maxContentWidth: 900, // Content area max width in px\n    headerHeight: 56, // Header height in px\n    tocWidth: 240, // Table of contents width in px\n    toc: false, // Hide table of contents\n    breadcrumbs: false, // Hide breadcrumbs\n    footer: false, // Hide prev/next footer\n  },\n};\n```\n\n## Landing Page\n\nSkip the landing page and redirect to docs:\n\n```typescript\nexport const config: DenoteConfig = {\n  landing: {\n    enabled: false, // Redirect \"/\" to first doc page\n    redirectTo: \"/docs/quickstart\", // Optional custom target\n  },\n};\n```\n\n## Style\n\nControl border radius, dark mode behavior, and custom CSS:\n\n```typescript\nexport const config: DenoteConfig = {\n  style: {\n    roundedness: \"lg\", // \"none\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n    darkMode: \"auto\", // \"auto\" | \"light\" | \"dark\" | \"toggle\"\n    customCss: \"/custom.css\", // Custom CSS file loaded after theme tokens\n  },\n};\n```\n\nSee the [Theming guide](/docs/theming) for details on each option.\n\n## Top Navigation\n\nAdd links to your header:\n\n```typescript\nexport const config: DenoteConfig = {\n  topNav: [\n    { title: \"Documentation\", href: \"/docs\" },\n    { title: \"Blog\", href: \"/blog\" },\n    { title: \"GitHub\", href: \"https://github.com/<your-org>/<your-repo>\" },\n  ],\n};\n```\n\n## Social Links\n\nAdd social media links:\n\n```typescript\nexport const config: DenoteConfig = {\n  social: {\n    github: \"https://github.com/<your-org>/<your-repo>\",\n    twitter: \"https://twitter.com/<your-handle>\",\n    discord: \"https://discord.gg/<your-invite-code>\",\n  },\n};\n```\n\n## Footer\n\nConfigure your footer:\n\n```typescript\nexport const config: DenoteConfig = {\n  footer: {\n    copyright: \"© 2026 Your Organization\",\n    links: [\n      { title: \"Terms\", href: \"/terms\" },\n      { title: \"Privacy\", href: \"/privacy\" },\n    ],\n    poweredBy: false, // Hide \"Documentation by Denote\" attribution (default: true)\n  },\n};\n```\n\nA subtle \"Documentation by Denote\" attribution link is shown by default in the\ndocs layout footer and the landing page footer. Set `poweredBy: false` to remove\nit.\n\n## Edit Link\n\nShow an \"Edit this page\" link at the bottom of each doc page:\n\n```typescript\nexport const config: DenoteConfig = {\n  editUrl: \"https://github.com/your-org/your-repo/edit/main/docs/content/docs\",\n};\n```\n\nDenote appends `/<slug>.md` automatically. If `editUrl` is not set, no link\nappears.\n\n## SEO\n\nDenote includes several built-in SEO features that work automatically, plus an\noptional `seo` config block for production sites that need full control.\n\n### SEO Configuration\n\nFor production sites with a custom domain, add the `seo` block:\n\n```typescript\nexport const config: DenoteConfig = {\n  seo: {\n    url: \"https://denote.sh\",\n    ogImage: \"https://denote.sh/og.png\",\n    ogImageWidth: 1200,\n    ogImageHeight: 630,\n    locale: \"en\",\n    jsonLdType: \"WebSite\",\n    jsonLdExtra: {\n      author: { \"@type\": \"Organization\", name: \"Denote\" },\n    },\n  },\n};\n```\n\n| Property        | Description                                                                               |\n| --------------- | ----------------------------------------------------------------------------------------- |\n| `url`           | Canonical base URL — unlocks proper canonical URLs, hreflang, and sitemap URLs            |\n| `description`   | Default meta description and `og:description` for pages without frontmatter `description` |\n| `ogImage`       | Default OG image for social sharing (1200x630 recommended)                                |\n| `ogImageWidth`  | OG image width in pixels (default: 1200 when ogImage is set)                              |\n| `ogImageHeight` | OG image height in pixels (default: 630 when ogImage is set)                              |\n| `locale`        | Language code for `<html lang>`, `og:locale`, and hreflang tags (default: \"en\")           |\n| `jsonLdType`    | JSON-LD `@type` (default: \"WebSite\", or \"SoftwareApplication\", etc.)                      |\n| `jsonLdExtra`   | Additional properties merged into the JSON-LD structured data object                      |\n\n`seo.url` is technically optional but strongly recommended for any deployed site\n— without it, canonical links, sitemap URLs, and OG URLs fall back to the\nrequest origin (e.g. `localhost`). `deno task validate` warns when it is unset.\n\n### Per-Page Meta Tags\n\nEach page's `title` and `description` from frontmatter are used for the HTML\n`<title>` tag and `<meta name=\"description\">`. Always add descriptive\nfrontmatter to your pages for better search engine visibility.\n\n### OpenGraph & Twitter Cards\n\nDenote automatically generates OpenGraph (`og:title`, `og:description`,\n`og:url`, `og:image`, `og:image:width`, `og:image:height`) and Twitter Card meta\ntags for every page. When `seo.ogImage` is configured, it's used as the default\nfor all pages. Individual pages can override it with the `image` frontmatter\nfield.\n\n### Sitemap\n\nA `sitemap.xml` is automatically generated at `/sitemap.xml` and includes all\ndocumentation pages with `<changefreq>` and `<priority>` elements (home=1.0,\ndocs index=0.8, pages=0.6). When `seo.url` is set, sitemap URLs use your\ncanonical domain instead of the request origin.\n\n### Robots.txt\n\nA `robots.txt` file is served at `/robots.txt` with an `Allow: /` directive and\na reference to the sitemap. When `seo.url` is set, the sitemap URL uses your\ncanonical domain.\n\n### Canonical URLs\n\nEach page includes a `<link rel=\"canonical\">` tag and `og:url` meta tag. When\n`seo.url` is configured, these use your canonical domain, helping search engines\navoid duplicate content issues across preview deployments.\n\n### Structured Data (JSON-LD)\n\nDenote auto-generates JSON-LD structured data on every page. By default it uses\n`\"WebSite\"` as the `@type`. Customize it via the `seo` config:\n\n```typescript\nseo: {\n  jsonLdType: \"SoftwareApplication\",\n  jsonLdExtra: {\n    applicationCategory: \"DeveloperApplication\",\n    operatingSystem: \"Any\",\n    offers: { \"@type\": \"Offer\", price: \"0\", priceCurrency: \"USD\" },\n  },\n}\n```\n\nThe `jsonLdExtra` properties are merged into the generated object alongside the\nauto-populated `name`, `url`, and `description` fields.\n\n## Analytics\n\nDenote has built-in server-side analytics that works with privacy-friendly\nproviders. No client-side JavaScript, no cookies, fully GDPR-compliant.\n\n### Built-in Providers\n\n- **Umami** — Free cloud tier (100K events/mo), open source, EU-friendly\n- **Plausible** — EU-hosted, starts at $9/mo\n- **Custom** — Any endpoint that accepts JSON POST requests\n\n### Setup\n\n1. Add an `analytics` block to your config:\n\n```typescript\nexport const config: DenoteConfig = {\n  name: \"My Docs\",\n  analytics: { provider: \"umami\" },\n  // ...\n};\n```\n\n2. Set the `ANALYTICS_SITE_ID` environment variable to your website ID:\n\n```bash\nexport ANALYTICS_SITE_ID=\"your-website-id\"\n```\n\nThat's it. The endpoint defaults to the provider's cloud API (`cloud.umami.is`\nfor Umami, `plausible.io` for Plausible). Override with `endpoint` if you\nself-host.\n\nFor **Plausible**:\n\n```typescript\nanalytics: { provider: \"plausible\" },\n// ANALYTICS_SITE_ID=\"your-domain.com\"\n```\n\nFor a **custom** provider, both `endpoint` and `siteId` (or the env var) are\nrequired:\n\n```typescript\nanalytics: {\n  provider: \"custom\",\n  endpoint: \"https://my-analytics.example.com/collect\",\n},\n// ANALYTICS_SITE_ID=\"my-site\"\n```\n\n> **Why an env var?** Your site ID is the key that authorizes writes to your\n> analytics account. If it's in your source code, anyone can read it and send\n> bogus pageviews. Keeping it in an environment variable means it never leaks\n> into your repo or client-side bundle.\n\n### How It Works\n\n- **Server-side only** — no tracking scripts are injected into your pages\n- **No cookies** — visitor privacy is preserved by default\n- **Non-blocking** — analytics are sent asynchronously after the response\n- **Selective** — only GET requests returning HTML documents are tracked; static\n  assets, API routes, and internal paths are automatically skipped\n\n### Deployment\n\nSet `ANALYTICS_SITE_ID` in your hosting platform's environment variables (Deno\nDeploy, Docker, etc.). If the env var is missing, analytics are silently\ndisabled — your site still works fine.\n\n## Advanced Options\n\nThe `denote()` factory function accepts a `DenoteOptions` object that goes\nbeyond `DenoteConfig`. Use these to customize paths or disable built-in\nfeatures:\n\n```typescript\nimport { denote } from \"@denote/core\";\nimport { config } from \"./denote.config.ts\";\n\nconst app = denote({\n  config,\n  contentDir: \"./my-docs\", // Default: \"./content/docs\"\n  docsBasePath: \"/guide\", // Default: \"/docs\"\n  includeLandingPage: false, // Default: true\n  includeStaticFiles: false, // Default: true\n  includeSeo: false, // Default: true\n  includeErrorHandlers: false, // Default: true\n});\n```\n\n| Option                 | Default            | Description                                  |\n| ---------------------- | ------------------ | -------------------------------------------- |\n| `contentDir`           | `\"./content/docs\"` | Path to your markdown content directory      |\n| `docsBasePath`         | `\"/docs\"`          | URL prefix where doc pages are served        |\n| `includeLandingPage`   | `true`             | Include the default landing page at `/`      |\n| `includeStaticFiles`   | `true`             | Include static file serving middleware       |\n| `includeSeo`           | `true`             | Include SEO routes (sitemap.xml, robots.txt) |\n| `includeErrorHandlers` | `true`             | Include built-in 404/error pages             |\n\nDisabling features is useful when embedding Denote into a larger Fresh app where\nyou provide your own error pages, static file handling, or landing page.\n\n## Config Hot Reload\n\nDuring development, config changes hot-reload without restarting the server. The\n`denoteHmr()` Vite plugin watches `denote.config.ts` for changes, re-imports the\nmodule, and triggers a browser refresh:\n\n```typescript\n// vite.config.ts (already included in scaffolded projects)\nimport { denoteHmr } from \"@denote/core/vite\";\n\nexport default {\n  plugins: [denoteHmr()],\n};\n```\n\nWhen you save `denote.config.ts`, you'll see `[denote] Config reloaded` in the\nterminal. If there's a syntax error, the previous config stays active and an\nerror message is shown — no crash, no restart needed.\n\n## Content Validation\n\nRun `deno task validate` to check your config, content, and navigation for\ncommon issues:\n\n```bash\ndeno task validate\n```\n\nThe validator checks:\n\n- **Content directory** — exists and contains markdown files\n- **Frontmatter** — each page has a valid `title`\n- **Navigation links** — every internal nav href matches an existing doc page\n- **SEO URLs** — `seo.url` and `seo.ogImage` are valid URLs when set; warns if\n  `seo.url` is absent\n- **Hex colors** — all color values in `colors` and `colors.dark` are valid hex\n\nNote: Config field types, enums (`style.darkMode`, `style.roundedness`,\n`analytics.provider`), and unrecognized keys are validated by Zod at startup\nwhen `setConfig()` is called, not by `deno task validate`.\n\nIf your project uses custom content or base paths, pass them as CLI args:\n\n```bash\ndeno run -A jsr:@denote/core/validate --content-dir=./my-content --docs-base-path=/reference\n```\n\nErrors block deployment; warnings are informational. Add this to your CI\npipeline to catch broken links and missing metadata before they go live.\n\n## Full Example\n\nHere's a complete configuration example:\n\n```typescript\nimport type { DenoteConfig } from \"@denote/core\";\n\nexport const config: DenoteConfig = {\n  name: \"Acme Docs\",\n  logo: {\n    light: \"/logo.svg\",\n    dark: \"/logo-dark.svg\",\n  },\n  favicon: \"/favicon.ico\",\n  colors: {\n    primary: \"#0066cc\",\n    accent: \"#00cc66\",\n    // background, surface, text, border, dark are also available\n    // See \"Theming\" docs for full options\n  },\n  navigation: [\n    {\n      title: \"Getting Started\",\n      children: [\n        { title: \"Introduction\", href: \"/docs/introduction\" },\n        { title: \"Installation\", href: \"/docs/installation\" },\n      ],\n    },\n  ],\n  topNav: [\n    { title: \"Docs\", href: \"/docs\" },\n    { title: \"API\", href: \"/api\" },\n  ],\n  social: {\n    github: \"https://github.com/acme/docs\",\n  },\n  footer: {\n    copyright: \"© 2026 Acme Inc.\",\n  },\n  search: {\n    enabled: true,\n  },\n  layout: {\n    toc: true,\n    breadcrumbs: true,\n    footer: true,\n  },\n  style: {\n    roundedness: \"md\",\n    darkMode: \"auto\",\n  },\n  analytics: {\n    provider: \"umami\",\n  },\n  // Set ANALYTICS_SITE_ID env var in your hosting platform\n  editUrl: \"https://github.com/acme/docs/edit/main/docs/content/docs\",\n};\n```\n\n## Next Steps\n\n- [Theming & Styling](/docs/theming) — Colors, fonts, dark mode, and CSS\n  variables\n- [Writing Content](/docs/content) — Markdown syntax and frontmatter options\n- [Deployment](/docs/deployment) — Deploy to Deno Deploy or Docker\n",
      "headings": [
        {
          "level": 1,
          "title": "Configuration",
          "id": "configuration"
        },
        {
          "level": 2,
          "title": "Basic Configuration",
          "id": "basic-configuration"
        },
        {
          "level": 2,
          "title": "Navigation",
          "id": "navigation"
        },
        {
          "level": 2,
          "title": "Colors",
          "id": "colors"
        },
        {
          "level": 2,
          "title": "Layout",
          "id": "layout"
        },
        {
          "level": 2,
          "title": "Landing Page",
          "id": "landing-page"
        },
        {
          "level": 2,
          "title": "Style",
          "id": "style"
        },
        {
          "level": 2,
          "title": "Top Navigation",
          "id": "top-navigation"
        },
        {
          "level": 2,
          "title": "Social Links",
          "id": "social-links"
        },
        {
          "level": 2,
          "title": "Footer",
          "id": "footer"
        },
        {
          "level": 2,
          "title": "Edit Link",
          "id": "edit-link"
        },
        {
          "level": 2,
          "title": "SEO",
          "id": "seo"
        },
        {
          "level": 3,
          "title": "SEO Configuration",
          "id": "seo-configuration"
        },
        {
          "level": 3,
          "title": "Per-Page Meta Tags",
          "id": "per-page-meta-tags"
        },
        {
          "level": 3,
          "title": "OpenGraph & Twitter Cards",
          "id": "opengraph--twitter-cards"
        },
        {
          "level": 3,
          "title": "Sitemap",
          "id": "sitemap"
        },
        {
          "level": 3,
          "title": "Robots.txt",
          "id": "robotstxt"
        },
        {
          "level": 3,
          "title": "Canonical URLs",
          "id": "canonical-urls"
        },
        {
          "level": 3,
          "title": "Structured Data (JSON-LD)",
          "id": "structured-data-json-ld"
        },
        {
          "level": 2,
          "title": "Analytics",
          "id": "analytics"
        },
        {
          "level": 3,
          "title": "Built-in Providers",
          "id": "built-in-providers"
        },
        {
          "level": 3,
          "title": "Setup",
          "id": "setup"
        },
        {
          "level": 3,
          "title": "How It Works",
          "id": "how-it-works"
        },
        {
          "level": 3,
          "title": "Deployment",
          "id": "deployment"
        },
        {
          "level": 2,
          "title": "Advanced Options",
          "id": "advanced-options"
        },
        {
          "level": 2,
          "title": "Config Hot Reload",
          "id": "config-hot-reload"
        },
        {
          "level": 2,
          "title": "Content Validation",
          "id": "content-validation"
        },
        {
          "level": 2,
          "title": "Full Example",
          "id": "full-example"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "content",
      "title": "Writing Content",
      "description": "Learn how to write documentation with Denote's markdown syntax",
      "aiSummary": "Write documentation in Markdown with YAML frontmatter (title, description, ai-summary, ai-keywords). Supports GFM syntax, code highlighting, tables, task lists, and single-line paragraph convention.",
      "aiKeywords": [
        "markdown",
        "frontmatter",
        "GFM",
        "content",
        "syntax highlighting",
        "tables",
        "ai-summary",
        "ai-keywords",
        "writing"
      ],
      "content": "\n# Writing Content\n\nDenote uses Markdown for documentation with frontmatter support for metadata.\n\n## Frontmatter\n\nEvery documentation page starts with frontmatter:\n\n```yaml\n---\ntitle: Page Title\ndescription: A brief description of this page\n---\n```\n\n### Frontmatter Options\n\n| Property      | Description                                              |\n| ------------- | -------------------------------------------------------- |\n| `title`       | The page title (required)                                |\n| `description` | A brief description for SEO and previews                 |\n| `image`       | OG image URL for social sharing (overrides site default) |\n| `ai-summary`  | AI-optimized summary for LLM context/embeddings          |\n| `ai-keywords` | Keywords for AI retrieval and classification             |\n\n### AI Content Tags\n\nDenote's AI features use optional frontmatter fields to improve how AI agents\nunderstand and retrieve your documentation:\n\n```yaml\n---\ntitle: Authentication\ndescription: How to authenticate with the API\nai-summary: OAuth2 and API key authentication. Supports JWT tokens, refresh flows, and scoped permissions. Rate limits apply per-key.\nai-keywords:\n  - authentication\n  - oauth2\n  - api-keys\n  - jwt\n  - security\n---\n```\n\n**`ai-summary`** — A concise, LLM-optimized summary of the page. Unlike\n`description` (which targets humans and SEO), `ai-summary` should be dense with\ntechnical details that help AI agents understand the page's content without\nreading it. Used in llms.txt, the JSON API, and MCP tool responses.\n\n**`ai-keywords`** — A list of keywords for AI retrieval. These are indexed in\nthe search API and MCP search tool, making pages discoverable by semantic\nconcepts that might not appear literally in the content.\n\nBoth fields are optional. When `ai-summary` is absent, Denote falls back to\n`description`. When `ai-keywords` is absent, search relies on content matching.\n\n## Markdown Syntax\n\n### Headings\n\n```markdown\n# Heading 1\n\n## Heading 2\n\n### Heading 3\n\n#### Heading 4\n```\n\nHeadings automatically generate anchor links and appear in the table of\ncontents.\n\n### Text Formatting\n\n```markdown\n**Bold text** _Italic text_ `inline code` ~~Strikethrough~~\n```\n\n**Bold text** renders as strong, _italic text_ as emphasis, `inline code` with a\nhighlighted background, and ~~strikethrough~~ with a line through it.\n\n### Links\n\n```markdown\n[External Link](https://example.com) [Internal Link](/docs/other-page)\n```\n\n### Images\n\n```markdown\n![Alt text](/images/screenshot.png)\n```\n\nImages are rendered with lazy loading enabled. Place image files in the\n`static/` directory and reference them with absolute paths.\n\n### Lists\n\nDenote supports both flat and nested lists:\n\n```markdown\n- Unordered item 1\n- Unordered item 2\n  - Nested child item\n  - Another nested item\n    - Deeply nested\n- Back to top level\n\n1. Ordered item 1\n2. Ordered item 2\n   1. Nested ordered\n   2. Another nested\n3. Back to top level\n```\n\nNesting is controlled by indentation — use 2 or more spaces to create sub-lists.\nYou can mix ordered and unordered lists at different levels.\n\n### Code Blocks\n\nUse triple backticks with a language hint:\n\n```typescript\nfunction greet(name: string): string {\n  return `Hello, ${name}!`;\n}\n```\n\nSupported languages include: typescript, javascript, python, bash, json, yaml,\nmarkdown, css, html, rust, go, sql, diff, toml, xml, and more.\n\nCode blocks include a **copy button** that appears on hover — click the\nclipboard icon to copy the code content.\n\n### Tables\n\n```markdown\n| Feature | Status |\n| ------- | ------ |\n| Tables  | ✅     |\n| Lists   | ✅     |\n```\n\nTables support left, center, and right alignment using colons in the separator\nrow (`:---`, `:---:`, `---:`).\n\n### Blockquotes\n\n```markdown\n> This is a blockquote. Use it for important notes or quotes.\n```\n\n> This is a blockquote. Use it for important notes or quotes.\n\n### Horizontal Rules\n\nUse three or more dashes to create a horizontal rule:\n\n```markdown\n---\n```\n\n---\n\n## File Organization\n\nOrganize your docs in the `content/docs/` directory:\n\n```\ncontent/docs/\n├── introduction.md       # /docs/introduction\n├── installation.md       # /docs/installation\n├── guides/\n│   ├── index.md         # /docs/guides\n│   ├── basics.md        # /docs/guides/basics\n│   └── advanced.md      # /docs/guides/advanced\n└── api/\n    └── reference.md     # /docs/api/reference\n```\n\n> [!NOTE]\n> Pages must be added to `navigation` in `denote.config.ts` to appear in the\n> sidebar. Files in `content/docs/` are accessible by URL but won't show in\n> navigation until configured.\n\n## Extended Markdown Features\n\nDenote uses `@deer/gfm` which supports GitHub Flavored Markdown extensions.\n\n### Task Lists\n\n```markdown\n- [x] Completed task\n- [ ] Incomplete task\n- [ ] Another todo\n```\n\n- [x] Completed task\n- [ ] Incomplete task\n- [ ] Another todo\n\n### GitHub Alerts\n\nGitHub-style alerts using blockquote syntax:\n\n```markdown\n> [!NOTE]\n> Useful information that users should know.\n\n> [!TIP]\n> Helpful advice for doing things better.\n\n> [!IMPORTANT]\n> Key information users need to know.\n\n> [!WARNING]\n> Urgent info that needs immediate attention.\n\n> [!CAUTION]\n> Advises about risks or negative outcomes.\n```\n\n> [!NOTE]\n> Useful information that users should know.\n\n> [!TIP]\n> Helpful advice for doing things better.\n\n> [!IMPORTANT]\n> Key information users need to know.\n\n> [!WARNING]\n> Urgent info that needs immediate attention.\n\n> [!CAUTION]\n> Advises about risks or negative outcomes.\n\n### Footnotes\n\n```markdown\nHere is a sentence with a footnote[^1].\n\n[^1]: This is the footnote content.\n```\n\nHere is a sentence with a footnote[^1].\n\n[^1]: This is the footnote content.\n\n### Autolinks\n\nURLs and email addresses are automatically linked:\n\n- https://example.com\n- contact@example.com\n\n---\n\n## Best Practices\n\n1. **Use descriptive titles** — help users understand what the page covers\n2. **Add descriptions** — improve SEO and search results\n3. **Link related pages** — help users discover more content\n4. **Use code examples** — show, don't just tell\n5. **Keep pages focused** — one topic per page\n6. **Use nested lists** — organize complex information hierarchically\n\n## Next Steps\n\n- [Components](/docs/components) — Built-in UI components and islands\n- [Configuration](/docs/configuration) — Customize your site settings\n- [Theming & Styling](/docs/theming) — Colors, dark mode, and CSS variables\n",
      "headings": [
        {
          "level": 1,
          "title": "Writing Content",
          "id": "writing-content"
        },
        {
          "level": 2,
          "title": "Frontmatter",
          "id": "frontmatter"
        },
        {
          "level": 3,
          "title": "Frontmatter Options",
          "id": "frontmatter-options"
        },
        {
          "level": 3,
          "title": "AI Content Tags",
          "id": "ai-content-tags"
        },
        {
          "level": 2,
          "title": "Markdown Syntax",
          "id": "markdown-syntax"
        },
        {
          "level": 3,
          "title": "Headings",
          "id": "headings"
        },
        {
          "level": 3,
          "title": "Text Formatting",
          "id": "text-formatting"
        },
        {
          "level": 3,
          "title": "Links",
          "id": "links"
        },
        {
          "level": 3,
          "title": "Images",
          "id": "images"
        },
        {
          "level": 3,
          "title": "Lists",
          "id": "lists"
        },
        {
          "level": 3,
          "title": "Code Blocks",
          "id": "code-blocks"
        },
        {
          "level": 3,
          "title": "Tables",
          "id": "tables"
        },
        {
          "level": 3,
          "title": "Blockquotes",
          "id": "blockquotes"
        },
        {
          "level": 3,
          "title": "Horizontal Rules",
          "id": "horizontal-rules"
        },
        {
          "level": 2,
          "title": "File Organization",
          "id": "file-organization"
        },
        {
          "level": 2,
          "title": "Extended Markdown Features",
          "id": "extended-markdown-features"
        },
        {
          "level": 3,
          "title": "Task Lists",
          "id": "task-lists"
        },
        {
          "level": 3,
          "title": "GitHub Alerts",
          "id": "github-alerts"
        },
        {
          "level": 3,
          "title": "Footnotes",
          "id": "footnotes"
        },
        {
          "level": 3,
          "title": "Autolinks",
          "id": "autolinks"
        },
        {
          "level": 2,
          "title": "Best Practices",
          "id": "best-practices"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "custom-pages",
      "title": "Custom Pages",
      "description": "Add standalone pages like legal notices, about pages, or anything outside the docs layout",
      "aiSummary": "Add standalone routes (legal, about, landing pages) outside the docs layout. Fresh file-system routing with automatic PageLayout wrapping and access to DenoteContext.",
      "aiKeywords": [
        "custom pages",
        "routes",
        "Fresh",
        "file-system routing",
        "PageLayout",
        "standalone",
        "legal pages"
      ],
      "content": "\n# Custom Pages\n\nDenote sites aren't limited to documentation pages. You can add standalone\nroutes — legal pages, landing pages, about pages — that get the site header and\nfooter automatically without the docs sidebar and table of contents.\n\n## Creating a Page\n\nAdd a `.tsx` file to your project's `routes/` directory. Denote wraps it in a\n`PageLayout` that provides the site header and a footer with your configured\nlinks. Your component only needs to render its own content.\n\n```tsx\n// routes/about.tsx\nexport default function AboutPage() {\n  return (\n    <>\n      <h1 class=\"text-3xl font-bold text-[var(--denote-text)] mb-8\">\n        About\n      </h1>\n      <p class=\"text-[var(--denote-text-secondary)]\">\n        This is a standalone page with the site header and footer.\n      </p>\n    </>\n  );\n}\n```\n\nThis page is now available at `/about`.\n\n## What You Get\n\nThe `PageLayout` wrapper provides:\n\n- **Site header** — logo, top navigation, theme toggle, search, mobile menu\n- **Footer** — copyright notice and any links from your `footer` config\n- **Consistent styling** — centered content area with site background color\n\nYou don't need to import or render any of these — they're automatic.\n\n## Footer Configuration\n\nFooter links appear on all pages wrapped by `PageLayout`. Configure them in your\n`denote.config.ts`:\n\n```typescript\nexport const config: DenoteConfig = {\n  // ...\n  footer: {\n    copyright: \"© 2026 My Project\",\n    links: [\n      { title: \"GitHub\", href: \"https://github.com/my/project\" },\n      { title: \"Privacy\", href: \"/privacy\" },\n    ],\n  },\n};\n```\n\n## How It Works\n\nDenote uses Fresh's file-system routing. When you call `denote()` in your\n`main.ts`, it registers the documentation routes first (with their own\n`DocsLayout`), then applies `PageLayout` to any routes in your `routes/`\ndirectory. This means:\n\n- **Docs pages** (`/docs/*`) use the docs layout with sidebar and TOC\n- **Your pages** (`routes/*.tsx`) use the simpler `PageLayout` with header and\n  footer\n- **No double-wrapping** — each route type gets exactly one layout\n\n## Styling\n\nCustom pages have access to all Denote CSS variables. Use them to stay\nconsistent with the site theme:\n\n```tsx\n<div class=\"text-[var(--denote-text)]\">          {/* Primary text */}\n<p class=\"text-[var(--denote-text-secondary)]\">   {/* Secondary text */}\n<a class=\"text-[var(--denote-primary-text)]\">      {/* Link color */}\n<hr class=\"border-[var(--denote-border)]\" />        {/* Border color */}\n```\n\nSee the [Theming & Styling](/docs/theming) page for all available tokens.\n\n## Next Steps\n\n- [Theming & Styling](/docs/theming) — All available CSS variables and dark mode\n- [Deployment](/docs/deployment) — Deploy to Deno Deploy or Docker\n",
      "headings": [
        {
          "level": 1,
          "title": "Custom Pages",
          "id": "custom-pages"
        },
        {
          "level": 2,
          "title": "Creating a Page",
          "id": "creating-a-page"
        },
        {
          "level": 2,
          "title": "What You Get",
          "id": "what-you-get"
        },
        {
          "level": 2,
          "title": "Footer Configuration",
          "id": "footer-configuration"
        },
        {
          "level": 2,
          "title": "How It Works",
          "id": "how-it-works"
        },
        {
          "level": 2,
          "title": "Styling",
          "id": "styling"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "deployment",
      "title": "Deployment",
      "description": "Deploy your Denote documentation site to production",
      "aiSummary": "Deploy Denote to Deno Deploy (recommended one-click), Docker, or any Deno-capable host. Covers production builds, environment variables, GitHub Actions CI/CD, and custom domain setup.",
      "aiKeywords": [
        "deployment",
        "Deno Deploy",
        "Docker",
        "production build",
        "CI/CD",
        "GitHub Actions",
        "environment variables",
        "hosting"
      ],
      "content": "\n# Deployment\n\nDenote is a standard [Fresh](https://fresh.deno.dev) app. It can be deployed\nanywhere that runs Deno or Docker.\n\n## Build for Production\n\nCreate a production build:\n\n```bash\ndeno task build\n```\n\nThis generates an optimized build in the `_fresh/` directory. To preview it\nlocally:\n\n```bash\ndeno task start\n```\n\nYour site will be available at [http://localhost:8000](http://localhost:8000).\n\n## Deno Deploy\n\n[Deno Deploy](https://deno.com/deploy) is the fastest way to deploy. Since\nDenote is a Fresh app, follow the standard\n[Fresh deployment guide](https://fresh.deno.dev/docs/deployment).\n\nThe quickest option is connecting your GitHub repository for automatic deploys\non every push — no CLI needed.\n\n### Manual Deploy\n\nIf you prefer the CLI:\n\n```bash\ndeno install -gArf jsr:@deno/deployctl\n\ndeno task build\ndeployctl deploy --project=<your-project> _fresh/server.js\n```\n\n## Docker\n\nEvery Denote project includes a production-ready `Dockerfile`.\n\n### Build and Run\n\n```bash\ndocker build -t my-docs .\ndocker run -p 8000:8000 my-docs\n```\n\nYour site will be available at [http://localhost:8000](http://localhost:8000).\n\n### Container Platforms\n\nThe Docker image works on any container platform — Railway, Fly.io, Render,\nCoolify, Kubernetes, or any VPS with Docker installed.\n\n## Security Headers\n\nDenote automatically sets security headers on every response — no reverse proxy\nconfiguration needed:\n\n| Header                      | Value                                          |\n| --------------------------- | ---------------------------------------------- |\n| `Strict-Transport-Security` | `max-age=63072000; includeSubDomains; preload` |\n| `X-Content-Type-Options`    | `nosniff`                                      |\n| `X-Frame-Options`           | `DENY`                                         |\n| `Referrer-Policy`           | `strict-origin-when-cross-origin`              |\n| `Content-Security-Policy`   | Auto-configured policy                         |\n| `Permissions-Policy`        | Restricts browser features (camera, mic, etc.) |\n\nThese headers are always active in both development and production. Hashed\nstatic assets (files matching `/_fresh/` or `.[hash].(js|css|...)`) also receive\n`Cache-Control: public, max-age=31536000, immutable` for aggressive caching.\n\nIf you run Denote behind a reverse proxy, the proxy's headers will merge with\nthese. No extra proxy configuration is needed for basic security compliance.\n\n## Next Steps\n\n- [Configuration](/docs/configuration) — Customize your site before deploying\n- [Writing Content](/docs/content) — Add more documentation pages\n",
      "headings": [
        {
          "level": 1,
          "title": "Deployment",
          "id": "deployment"
        },
        {
          "level": 2,
          "title": "Build for Production",
          "id": "build-for-production"
        },
        {
          "level": 2,
          "title": "Deno Deploy",
          "id": "deno-deploy"
        },
        {
          "level": 3,
          "title": "Manual Deploy",
          "id": "manual-deploy"
        },
        {
          "level": 2,
          "title": "Docker",
          "id": "docker"
        },
        {
          "level": 3,
          "title": "Build and Run",
          "id": "build-and-run"
        },
        {
          "level": 3,
          "title": "Container Platforms",
          "id": "container-platforms"
        },
        {
          "level": 2,
          "title": "Security Headers",
          "id": "security-headers"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "installation",
      "title": "Installation",
      "description": "How to install and set up Denote for your project",
      "aiSummary": "Install Denote via deno init with the @denote/init scaffolder. Requires Deno 2.x. Creates a ready-to-run project with config, content directory, routes, and dev server.",
      "aiKeywords": [
        "install",
        "deno",
        "scaffold",
        "init",
        "setup",
        "prerequisites",
        "project structure",
        "dev server"
      ],
      "content": "\n# Installation\n\nGet up and running with Denote in minutes.\n\n## Prerequisites\n\nBefore you begin, make sure you have [Deno](https://deno.com) installed on your\nsystem:\n\n```bash\n# Install Deno (macOS/Linux)\ncurl -fsSL https://deno.com/install.sh | sh\n\n# Or with Homebrew\nbrew install deno\n```\n\n## Create a New Project\n\nThe easiest way to get started is using our init command:\n\n```bash\ndeno run -Ar jsr:@denote/init my-docs\ncd my-docs\n```\n\nThis will create a new Denote project with the following structure:\n\n```\nmy-docs/\n├── content/\n│   └── docs/\n│       ├── introduction.md\n│       └── installation.md\n├── static/\n├── client.ts\n├── denote.config.ts\n├── deno.json\n├── Dockerfile\n├── main.ts\n├── README.md\n├── styles.css\n├── vite.config.ts\n└── .gitignore\n```\n\n## Start the Development Server\n\nRun the development server to see your docs:\n\n```bash\ndeno task dev\n```\n\nOpen [http://localhost:8000](http://localhost:8000) to view your documentation\nsite.\n\n## Project Structure\n\n- `content/docs/` - Your documentation markdown files\n- `denote.config.ts` - Site configuration (navigation, branding, etc.)\n- `main.ts` - Fresh app entry point\n- `vite.config.ts` - Vite build configuration\n- `client.ts` - Client-side entry for CSS\n- `styles.css` - Tailwind CSS imports\n- `static/` - Static assets (images, fonts, etc.)\n- `Dockerfile` - Production Docker image\n\n## Validate Your Project\n\nRun the built-in validation to catch common issues:\n\n```bash\ndeno task validate\n```\n\nThis checks your project for:\n\n- **Config errors** — missing `name`, invalid hex colors, malformed URLs,\n  unrecognized keys\n- **Content issues** — missing `content/docs/` directory, files without a\n  `title` in frontmatter\n- **Broken navigation links** — any `href` in your `navigation` config that\n  doesn't match an existing markdown file\n\nIf your project uses custom paths, pass `--content-dir` and `--docs-base-path`:\n\n```bash\ndeno run -A jsr:@denote/core/validate --content-dir=./my-content --docs-base-path=/reference\n```\n\nFix any errors before deploying to avoid broken links or missing pages.\n\n## Next Steps\n\n- [Quick Start](/docs/quickstart) — Build your first doc page\n- [Configuration](/docs/configuration) — Customize your site\n- [Writing Content](/docs/content) — Learn the markdown syntax\n",
      "headings": [
        {
          "level": 1,
          "title": "Installation",
          "id": "installation"
        },
        {
          "level": 2,
          "title": "Prerequisites",
          "id": "prerequisites"
        },
        {
          "level": 2,
          "title": "Create a New Project",
          "id": "create-a-new-project"
        },
        {
          "level": 2,
          "title": "Start the Development Server",
          "id": "start-the-development-server"
        },
        {
          "level": 2,
          "title": "Project Structure",
          "id": "project-structure"
        },
        {
          "level": 2,
          "title": "Validate Your Project",
          "id": "validate-your-project"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "introduction",
      "title": "Welcome to Denote",
      "description": "Denote — the open-source, AI-native documentation framework",
      "aiSummary": "Denote is an open-source, AI-native documentation framework. It auto-generates llms.txt, JSON API, and MCP server endpoints so AI agents can consume your docs as structured data. Zero config, server-rendered, markdown-first.",
      "aiKeywords": [
        "documentation",
        "ai-native",
        "open-source",
        "llms.txt",
        "mcp",
        "any-language"
      ],
      "content": "\n# Welcome to Denote\n\nDenote is an open-source, AI-native documentation framework — designed for a\nworld where AI agents read your docs too.\n\nWrite Markdown. Get a site that humans love and AI agents can query. Every AI\nfeature is built in and free.\n\n## Why Denote?\n\nTraditional documentation tools weren't built for the era of AI agents. They\nrequire complex build steps, heavy dependencies, and bolted-on AI integrations.\nDenote takes a different approach:\n\n- **AI-Native**: Built-in MCP server, llms.txt, and structured JSON API — every\n  site is a first-class data source for AI agents, out of the box.\n- **Zero Config**: Works immediately with sensible defaults. No plugins, no\n  setup.\n- **Any Project**: Document any codebase — Java, Go, Rust, Python, TypeScript.\n  Denote is the docs layer, independent of your stack.\n- **Markdown First**: Write your docs in Markdown with frontmatter. No MDX\n  compilation step. Just files.\n- **Lightning Fast**: Minimal client JavaScript. Fast page loads, no bloat.\n\n## AI Features\n\nEvery Denote site ships with these endpoints automatically:\n\n- **`/llms.txt`** and **`/llms-full.txt`** — AI discovery files following the\n  [llms.txt standard](https://llmstxt.org) for AI-readable documentation.\n- **`/api/docs`** — Structured JSON API serving your entire knowledge base,\n  ready for RAG pipelines, embeddings, or direct context injection.\n- **MCP server** — Expose your docs as tools and resources for Cursor, Claude\n  Desktop, ChatGPT, and any MCP-compatible client. Requires `ai: { mcp: true }`\n  in your config.\n\nThe llms.txt and JSON API endpoints are zero-config. Just write Markdown.\n\n## Quick Example\n\nHere's a simple documentation file:\n\n```markdown\n---\ntitle: My Page\ndescription: A simple documentation page\n---\n\n# Hello World\n\nWelcome to my documentation!\n```\n\n## Features at a Glance\n\n- 🤖 AI-native: MCP server, llms.txt, JSON API\n- 📝 Markdown with frontmatter support\n- 🎨 Beautiful, responsive design with dark mode\n- 🔍 Full-text search (⌘K)\n- 📱 Mobile-friendly navigation\n- ⚡ Lightning fast, minimal client JavaScript\n- 🚀 Deploy anywhere — Docker, Deno Deploy, or self-host\n\n## Getting Started\n\nReady to build your docs? Install in one command:\n\n```bash\ndeno run -Ar jsr:@denote/init\n```\n\nOr head to the [Installation guide](/docs/installation) for more options.\n\n## Next Steps\n\n- [Quick Start](/docs/quickstart) — Create your first page in 5 minutes\n- [Installation](/docs/installation) — Full setup guide and project structure\n- [AI Native](/docs/ai-native) — How AI agents consume your docs\n",
      "headings": [
        {
          "level": 1,
          "title": "Welcome to Denote",
          "id": "welcome-to-denote"
        },
        {
          "level": 2,
          "title": "Why Denote?",
          "id": "why-denote"
        },
        {
          "level": 2,
          "title": "AI Features",
          "id": "ai-features"
        },
        {
          "level": 2,
          "title": "Quick Example",
          "id": "quick-example"
        },
        {
          "level": 2,
          "title": "Features at a Glance",
          "id": "features-at-a-glance"
        },
        {
          "level": 2,
          "title": "Getting Started",
          "id": "getting-started"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "quickstart",
      "title": "Quick Start",
      "description": "Get your first documentation page up in 5 minutes",
      "aiSummary": "Step-by-step guide to create your first Denote documentation page. Covers creating markdown files with frontmatter, adding navigation entries, and running the dev server.",
      "aiKeywords": [
        "quickstart",
        "tutorial",
        "markdown",
        "frontmatter",
        "navigation",
        "dev server",
        "first page"
      ],
      "content": "\n# Quick Start\n\nLet's create your first documentation page!\n\n## Step 1: Create a Markdown File\n\nCreate a new file in `content/docs/` called `hello.md`:\n\n```markdown\n---\ntitle: Hello World\ndescription: My first documentation page\n---\n\n# Hello World\n\nWelcome to my documentation!\n\n## Getting Started\n\nThis is a simple example of a documentation page.\n\n- Item one\n- Item two\n- Item three\n```\n\nPretty simple, right?\n\n## Step 2: Add to Navigation\n\nUpdate your `denote.config.ts` to include the new page:\n\n```typescript\nimport type { DenoteConfig } from \"@denote/core\";\n\nexport const config: DenoteConfig = {\n  name: \"My Docs\",\n  navigation: [\n    {\n      title: \"Getting Started\",\n      children: [\n        { title: \"Introduction\", href: \"/docs/introduction\" },\n        { title: \"Hello World\", href: \"/docs/hello\" }, // Add this\n      ],\n    },\n  ],\n};\n```\n\n> [!NOTE]\n> Pages must be added to `navigation` in `denote.config.ts` to appear in the\n> sidebar. Files in `content/docs/` are accessible by URL but won't show in\n> navigation until configured.\n\n## Step 3: View Your Page\n\nStart the dev server and navigate to `/docs/hello`:\n\n```bash\ndeno task dev\n```\n\nYour new page is now live! 🎉\n\n## Next Steps\n\n- [Writing Content](/docs/content) — Frontmatter options and markdown syntax\n- [Configuration](/docs/configuration) — Customize navigation, branding, and\n  more\n- [Components](/docs/components) — Built-in UI components and islands\n",
      "headings": [
        {
          "level": 1,
          "title": "Quick Start",
          "id": "quick-start"
        },
        {
          "level": 2,
          "title": "Step 1: Create a Markdown File",
          "id": "step-1-create-a-markdown-file"
        },
        {
          "level": 2,
          "title": "Step 2: Add to Navigation",
          "id": "step-2-add-to-navigation"
        },
        {
          "level": 2,
          "title": "Step 3: View Your Page",
          "id": "step-3-view-your-page"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    },
    {
      "slug": "theming",
      "title": "Theming & Styling",
      "description": "Customize colors, fonts, layout, and CSS through config alone",
      "aiSummary": "Theme Denote via CSS custom properties (--denote-* tokens) driven by config. Covers color palette with auto-derived dark mode, font imports, layout dimensions, roundedness presets, and custom CSS injection.",
      "aiKeywords": [
        "theming",
        "CSS custom properties",
        "colors",
        "dark mode",
        "fonts",
        "layout",
        "roundedness",
        "design tokens",
        "customization"
      ],
      "content": "\n# Theming & Styling\n\nDenote's theming system lets you fully customize the look and feel of your\ndocumentation site through `denote.config.ts` — no component edits, no CSS\noverrides, no `!important` hacks.\n\n## How It Works\n\nDenote uses **CSS custom properties** (design tokens) for all visual\ncustomization. Every surface, text color, border, and shadow references a\n`--denote-*` variable. When you set colors in your config, Denote generates\noverrides that cascade correctly over the defaults.\n\nComponents use Tailwind CSS v4 with these CSS variables, so they automatically\nadapt to light mode, dark mode, and any custom theme:\n\n```tsx\n<div class=\"p-6 rounded-xl bg-[var(--denote-bg-secondary)] border border-[var(--denote-border)]\">\n  <h3 class=\"text-lg font-semibold text-[var(--denote-text)]\">{title}</h3>\n  <p class=\"text-[var(--denote-text-secondary)]\">{children}</p>\n</div>;\n```\n\n## How Styles Are Loaded\n\nThe scaffolded project wires the style pipeline through three pieces:\n\n**`styles.css`** — your project's main stylesheet:\n\n```css\n@import \"tailwindcss\";\n@import \"@denote/core/styles.css\";\n@source \"./\";\n@variant dark (&:where(.dark, .dark *));\n```\n\n- `@import \"tailwindcss\"` brings in Tailwind's reset, theme tokens, and empty\n  utilities layer — utilities get generated on demand for the classes Tailwind\n  finds in _your_ source.\n- `@import \"@denote/core/styles.css\"` brings in Denote's design tokens, markdown\n  rules, and a **pre-compiled block of Tailwind utilities** for every class used\n  inside the framework's own components. Denote ships these pre-compiled because\n  JSR packages aren't installed into `node_modules`, so your Tailwind build\n  can't scan the framework source itself.\n- `@source \"./\"` tells Tailwind to scan your project root for class names in\n  your own markup.\n\n**`vite.config.ts`** — the `denoteStyles()` plugin inlines the framework CSS at\nbuild time. It's required because `@tailwindcss/vite` has its own CSS `@import`\nresolver that bypasses Vite's plugin chain and can't find JSR packages. The\nplugin runs before `tailwindcss()` in the plugins array.\n\n**What this means for you:**\n\n- Write any Tailwind utility class in your own components, routes, or markdown —\n  Tailwind scans your source and generates it automatically.\n- You don't need to duplicate or re-declare framework utilities. They're already\n  in the shipped CSS.\n- To override a framework color, change the `--denote-*` tokens via config (see\n  [Colors](#colors)) — don't try to override `.bg-[var(--denote-bg)]` directly.\n  The tokens drive every framework class.\n- For custom CSS rules beyond tokens, use the [`style.customCss`](#custom-css)\n  config option.\n\n## Colors\n\nSet your brand colors in `denote.config.ts`:\n\n```typescript\nexport const config: DenoteConfig = {\n  colors: {\n    primary: \"#6366f1\", // Links, buttons, accents\n    accent: \"#22c55e\", // Secondary accent color\n  },\n};\n```\n\nFor full control, you can customize every surface:\n\n```typescript\nexport const config: DenoteConfig = {\n  colors: {\n    primary: \"#b45309\", // Brand color\n    accent: \"#059669\", // Secondary accent\n    background: \"#fef3c7\", // Page background\n    surface: \"#fde68a\", // Cards, sidebar, code blocks\n    text: \"#451a03\", // Body text\n    border: \"#d97706\", // Borders and dividers\n  },\n};\n```\n\nWhen you set `primary`, Denote automatically derives hover, subtle, and shadow\nvariants using `color-mix()`. You only need to set the base color.\n\n## Dark Mode\n\nDark mode works out of the box with sensible defaults. To customize dark mode\ncolors independently, add a `dark` object:\n\n```typescript\nexport const config: DenoteConfig = {\n  colors: {\n    primary: \"#b45309\",\n    accent: \"#059669\",\n    background: \"#fef3c7\",\n    surface: \"#fde68a\",\n    text: \"#451a03\",\n    border: \"#d97706\",\n    dark: {\n      primary: \"#f59e0b\",\n      accent: \"#34d399\",\n      background: \"#042f2e\",\n      surface: \"#0f766e\",\n      text: \"#ccfbf1\",\n      border: \"#115e59\",\n    },\n  },\n};\n```\n\nIf you set `colors.primary` but no `dark.primary`, Denote auto-derives a lighter\nvariant for dark mode. If you don't set any dark overrides, the built-in dark\npalette (indigo on near-black) is used.\n\n### Dark Mode Toggle\n\nUsers can toggle between light and dark mode using the moon/sun icon in the\nheader. The preference is saved to `localStorage` and respected on subsequent\nvisits. If no preference is saved, Denote follows the system preference\n(`prefers-color-scheme`).\n\n### Dark Mode Behavior\n\nControl how dark mode works via the `style` config:\n\n```typescript\nexport const config: DenoteConfig = {\n  style: {\n    darkMode: \"auto\", // \"auto\" | \"light\" | \"dark\" | \"toggle\"\n  },\n};\n```\n\n| Mode     | Behavior                                                  |\n| -------- | --------------------------------------------------------- |\n| `auto`   | Follow system preference, no toggle (default)             |\n| `light`  | Force light mode, no toggle                               |\n| `dark`   | Force dark mode, no toggle                                |\n| `toggle` | Follow system preference, show toggle for users to switch |\n\n### When to Use `dark:` Prefixes\n\nFor **semantic colors** that don't map to theme tokens (e.g., status badges,\nalerts), Tailwind's `dark:` prefix is still appropriate:\n\n```tsx\n// Semantic: always green for success, not theme-dependent\n<span class=\"bg-emerald-100 dark:bg-emerald-900/50 text-emerald-700 dark:text-emerald-300\">\n  Active\n</span>;\n```\n\nFor **everything else** (backgrounds, text, borders, surfaces), use CSS\nvariables. They adapt to any theme automatically — no `dark:` needed.\n\n## Fonts\n\nCustomize the font families used across your site:\n\n```typescript\nexport const config: DenoteConfig = {\n  fonts: {\n    body: '\"Source Sans 3\", system-ui, sans-serif',\n    heading: '\"Newsreader\", Georgia, serif',\n    mono: '\"JetBrains Mono\", ui-monospace, monospace',\n    imports: [\"/fonts.css\"],\n  },\n};\n```\n\nThe `imports` array adds `<link rel=\"stylesheet\">` tags for font loading.\n**Self-host your fonts** — place `.woff2` files in your `static/fonts/`\ndirectory and create a `static/fonts.css` with `@font-face` declarations\npointing to them. This avoids third-party requests that leak visitor IPs (a GDPR\nconcern with services like Google Fonts). Font families are applied via CSS\ncustom properties, so they affect the entire site including markdown content.\n\n## Layout\n\nControl the dimensions of major layout sections:\n\n```typescript\nexport const config: DenoteConfig = {\n  layout: {\n    sidebarWidth: 280, // px (default: 256)\n    maxContentWidth: 900, // px (default: 768)\n    headerHeight: 56, // px (default: 64)\n    tocWidth: 240, // px (default: 256)\n  },\n};\n```\n\nThese become CSS custom properties (`--denote-sidebar-width`, etc.) consumed by\nall layout components. You can also toggle visibility of layout elements:\n\n```typescript\nexport const config: DenoteConfig = {\n  layout: {\n    toc: false, // Hide table of contents sidebar\n    breadcrumbs: false, // Hide breadcrumb navigation\n    footer: false, // Hide prev/next footer navigation\n  },\n};\n```\n\n### Responsive Breakpoints\n\nDenote is fully responsive:\n\n| Breakpoint         | Layout                                |\n| ------------------ | ------------------------------------- |\n| **xl+** (1280px)   | Sidebar + content + table of contents |\n| **lg–xl** (1024px) | Sidebar + content                     |\n| **< lg**           | Collapsible mobile menu               |\n\n## Landing Page\n\nBy default, Denote shows a landing page at `/`. To skip it and redirect straight\nto your first documentation page:\n\n```typescript\nexport const config: DenoteConfig = {\n  landing: {\n    enabled: false, // Redirect \"/\" to first doc page\n  },\n};\n```\n\nYou can also specify a custom redirect path:\n\n```typescript\nexport const config: DenoteConfig = {\n  landing: {\n    enabled: false,\n    redirectTo: \"/docs/quickstart\", // Custom target\n  },\n};\n```\n\n## Roundedness\n\nControl the border radius scale across the entire site:\n\n```typescript\nexport const config: DenoteConfig = {\n  style: {\n    roundedness: \"lg\", // \"none\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n  },\n};\n```\n\n| Scale  | `--denote-radius` | `--denote-radius-lg` | `--denote-radius-xl` |\n| ------ | ----------------- | -------------------- | -------------------- |\n| `none` | 0                 | 0                    | 0                    |\n| `sm`   | 0.25rem           | 0.375rem             | 0.5rem               |\n| `md`   | 0.5rem            | 0.75rem              | 1rem                 |\n| `lg`   | 0.75rem           | 1rem                 | 1.25rem              |\n| `xl`   | 1rem              | 1.25rem              | 1.5rem               |\n\n## Custom CSS\n\nFor an escape hatch beyond what the config supports, point to a custom CSS file:\n\n```typescript\nexport const config: DenoteConfig = {\n  style: {\n    customCss: \"/custom.css\", // Loaded after all theme tokens\n  },\n};\n```\n\nThe file is loaded via a `<link>` tag after all theme styles, so it can override\nany token. Use `html:root` for specificity parity with config-driven overrides.\n\n### Markdown Content\n\nDocumentation content is rendered by `@deer/gfm` and styled via the\n`.markdown-body` class. Denote bridges its theme tokens to GFM variables\nautomatically (see [GFM Bridge](#gfm-bridge)), so markdown content follows your\ntheme. Custom overrides go in your CSS file:\n\n```css\n/* Heading sizes */\n.markdown-body h1 {\n  font-size: 2.25rem;\n  font-weight: 700;\n}\n\n/* Styled blockquotes */\n.markdown-body blockquote {\n  border-left-color: var(--gfm-accent-color);\n  background: var(--gfm-inline-code-bg);\n  border-radius: 0 0.5rem 0.5rem 0;\n}\n```\n\n### Code Blocks\n\nCode blocks use the `.highlight` wrapper and `.code-header` from `@deer/gfm`:\n\n```css\n/* Code block container */\n.markdown-body .highlight {\n  border-radius: 0.75rem;\n  border: 1px solid var(--gfm-border-color);\n  overflow: hidden;\n}\n\n/* Language label + copy button header */\n.markdown-body .code-header {\n  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n  font-size: 0.75rem;\n  text-transform: uppercase;\n}\n```\n\n## Design Tokens Reference\n\nThese are the CSS custom properties that control the theme. All components\nreference these tokens — you never need to edit component files.\n\n| Token                        | Purpose                                  |\n| ---------------------------- | ---------------------------------------- |\n| `--denote-primary`           | Brand color for links, buttons, accents  |\n| `--denote-primary-hover`     | Hover state of primary color             |\n| `--denote-primary-subtle`    | Light tint for backgrounds               |\n| `--denote-primary-text`      | Primary color used for text              |\n| `--denote-accent`            | Secondary accent color                   |\n| `--denote-bg`                | Page background                          |\n| `--denote-bg-secondary`      | Sidebar, card backgrounds                |\n| `--denote-bg-tertiary`       | Code block backgrounds, subtle surfaces  |\n| `--denote-surface-overlay`   | Modal/overlay backdrop                   |\n| `--denote-text`              | Primary body text                        |\n| `--denote-text-secondary`    | Secondary/subdued text                   |\n| `--denote-text-muted`        | Muted text (timestamps, hints)           |\n| `--denote-text-inverse`      | Text on dark backgrounds                 |\n| `--denote-border`            | Default border color                     |\n| `--denote-border-strong`     | Emphasized borders                       |\n| `--denote-shadow-primary`    | Primary-tinted shadow                    |\n| `--denote-font-body`         | Body text font family                    |\n| `--denote-font-heading`      | Heading font family                      |\n| `--denote-font-mono`         | Monospace font family                    |\n| `--denote-sidebar-width`     | Sidebar width (default: 256px)           |\n| `--denote-content-max-width` | Max content area width (default: 768px)  |\n| `--denote-header-height`     | Header height (default: 64px)            |\n| `--denote-toc-width`         | Table of contents width (default: 256px) |\n| `--denote-radius`            | Base border radius                       |\n| `--denote-radius-lg`         | Large border radius                      |\n| `--denote-radius-xl`         | Extra-large border radius                |\n\n## GFM Bridge\n\nDenote automatically bridges its tokens to `@deer/gfm` variables, so markdown\ncontent follows your theme without extra configuration:\n\n| Denote Token              | GFM Variable         |\n| ------------------------- | -------------------- |\n| `--denote-text-secondary` | `--gfm-fg-default`   |\n| `--denote-text`           | `--gfm-fg-heading`   |\n| `--denote-primary`        | `--gfm-accent-color` |\n| `--denote-border`         | `--gfm-border-color` |\n| `--denote-bg-secondary`   | `--gfm-bg-subtle`    |\n| `--denote-bg-tertiary`    | `--gfm-bg-surface`   |\n\n## Real-World Example: denote.sh\n\nThe [denote.sh](https://denote.sh) documentation site uses the theming system to\nachieve a warm, editorial look — parchment backgrounds, serif headings, and a\nmatching dark mode — all through config alone:\n\n```typescript\nexport const config: DenoteConfig = {\n  name: \"Denote\",\n  logo: {\n    text: \"denote\", // Lowercase in header\n    suffix: \".sh\", // Rendered in primary color\n  },\n  colors: {\n    primary: \"#2d5016\", // forest green\n    accent: \"#b8860b\", // dark goldenrod\n    background: \"#faf6f1\", // parchment\n    surface: \"#f0ebe4\", // warm linen\n    text: \"#2c2c2c\", // charcoal\n    border: \"#d4cec6\", // warm gray\n    dark: {\n      primary: \"#4a9e6a\", // forest green, readable on dark\n      accent: \"#e9b84e\", // warm gold\n      background: \"#0d1117\", // deep dark\n      surface: \"#1c2333\", // visible separation from bg\n      text: \"#e6edf3\", // soft white\n      border: \"#30363d\", // clear borders\n    },\n  },\n  fonts: {\n    heading: '\"Newsreader\", Georgia, serif',\n    body: '\"Source Sans 3\", system-ui, sans-serif',\n    imports: [\"/fonts.css\"],\n  },\n  style: {\n    roundedness: \"lg\",\n  },\n};\n```\n\nThis demonstrates how the theming system can create a dramatically different\naesthetic from the defaults — no custom CSS, no component overrides, just\nconfig.\n\n## Best Practices\n\n1. **Use CSS vars for theme colors** — `bg-[var(--denote-bg)]` adapts to any\n   theme automatically\n2. **Reserve `dark:` for semantics** — status colors, badges, alerts that have\n   fixed meaning regardless of theme\n3. **Use the config first** — most customizations belong in `denote.config.ts`,\n   not custom CSS\n4. **Test both modes** — toggle dark mode to verify contrast and readability\n\n## Next Steps\n\n- [Components](/docs/components) — Built-in UI components and islands\n- [Custom Pages](/docs/custom-pages) — Add standalone pages outside the docs\n  layout\n- [Configuration](/docs/configuration) — Full config reference\n",
      "headings": [
        {
          "level": 1,
          "title": "Theming & Styling",
          "id": "theming--styling"
        },
        {
          "level": 2,
          "title": "How It Works",
          "id": "how-it-works"
        },
        {
          "level": 2,
          "title": "How Styles Are Loaded",
          "id": "how-styles-are-loaded"
        },
        {
          "level": 2,
          "title": "Colors",
          "id": "colors"
        },
        {
          "level": 2,
          "title": "Dark Mode",
          "id": "dark-mode"
        },
        {
          "level": 3,
          "title": "Dark Mode Toggle",
          "id": "dark-mode-toggle"
        },
        {
          "level": 3,
          "title": "Dark Mode Behavior",
          "id": "dark-mode-behavior"
        },
        {
          "level": 3,
          "title": "When to Use dark: Prefixes",
          "id": "when-to-use-dark-prefixes"
        },
        {
          "level": 2,
          "title": "Fonts",
          "id": "fonts"
        },
        {
          "level": 2,
          "title": "Layout",
          "id": "layout"
        },
        {
          "level": 3,
          "title": "Responsive Breakpoints",
          "id": "responsive-breakpoints"
        },
        {
          "level": 2,
          "title": "Landing Page",
          "id": "landing-page"
        },
        {
          "level": 2,
          "title": "Roundedness",
          "id": "roundedness"
        },
        {
          "level": 2,
          "title": "Custom CSS",
          "id": "custom-css"
        },
        {
          "level": 3,
          "title": "Markdown Content",
          "id": "markdown-content"
        },
        {
          "level": 3,
          "title": "Code Blocks",
          "id": "code-blocks"
        },
        {
          "level": 2,
          "title": "Design Tokens Reference",
          "id": "design-tokens-reference"
        },
        {
          "level": 2,
          "title": "GFM Bridge",
          "id": "gfm-bridge"
        },
        {
          "level": 2,
          "title": "Real-World Example: denote.sh",
          "id": "real-world-example-denotesh"
        },
        {
          "level": 2,
          "title": "Best Practices",
          "id": "best-practices"
        },
        {
          "level": 2,
          "title": "Next Steps",
          "id": "next-steps"
        }
      ]
    }
  ],
  "llmsFullTxt": "https://denote.sh/llms-full.txt",
  "mcp": {
    "endpoint": "https://denote.sh/mcp",
    "transport": "Streamable HTTP",
    "tools": [
      "search_docs",
      "get_doc",
      "get_all_docs"
    ]
  }
}