# Markdown Documentation Server A lightweight, fast, and beautiful documentation server that renders Markdown files as styled HTML with zero configuration. ## Project Overview This is a modern documentation server built with Python, FastAPI, and powerful Markdown extensions. It's designed to be: - **Zero-config**: Drop markdown files and go - **Beautiful**: Nuxt UI-inspired design - **AI-friendly**: Built-in llms.txt support - **Production-ready**: Docker, caching, testing ## Quick Links Essential starting points: - [Homepage](http://static.109.5.225.46.clients.your-server.de/index.md) - Project overview and introduction - [Quick Setup Guide](http://static.109.5.225.46.clients.your-server.de/quick-setup.md) - Get running in 5 minutes - [Configuration](http://static.109.5.225.46.clients.your-server.de/configuration.md) - Environment variables and settings ## Core Documentation ### Getting Started - [Quick Setup Guide](http://static.109.5.225.46.clients.your-server.de/quick-setup.md) - Installation and first steps - [Configuration](http://static.109.5.225.46.clients.your-server.de/configuration.md) - Environment variables, file structure, and settings ### Features - [Markdown Features](http://static.109.5.225.46.clients.your-server.de/features/markdown.md) - Complete markdown capabilities showcase - [Navigation Guide](http://static.109.5.225.46.clients.your-server.de/features/navigation.md) - Sidebar and topbar configuration - [LLMs.txt Support](http://static.109.5.225.46.clients.your-server.de/features/llms-txt.md) - AI assistant integration (remarkable!) - [Caching System](http://static.109.5.225.46.clients.your-server.de/features/caching.md) - How the intelligent cache works ### Deployment - [Docker Deployment](http://static.109.5.225.46.clients.your-server.de/deployment/docker.md) - Container-based deployment - [Environment Variables](http://static.109.5.225.46.clients.your-server.de/deployment/environment.md) - Production configuration - [Production Tips](http://static.109.5.225.46.clients.your-server.de/deployment/production.md) - Best practices and optimization ### API Reference - [HTTP Endpoints](http://static.109.5.225.46.clients.your-server.de/api/endpoints.md) - All available API endpoints - [Response Formats](http://static.109.5.225.46.clients.your-server.de/api/responses.md) - Response structures and status codes ### Architecture - [Architecture Overview](http://static.109.5.225.46.clients.your-server.de/architecture/overview.md) - System design and components - [Code Structure](http://static.109.5.225.46.clients.your-server.de/architecture/structure.md) - Module organization and patterns - [Testing Strategy](http://static.109.5.225.46.clients.your-server.de/architecture/testing.md) - Test coverage and approach ### Examples - [Basic Setup](http://static.109.5.225.46.clients.your-server.de/examples/basic.md) - Simple configuration examples - [Advanced Features](http://static.109.5.225.46.clients.your-server.de/examples/advanced.md) - Complex use cases - [Custom Styling](http://static.109.5.225.46.clients.your-server.de/examples/styling.md) - Theming and customization ## Key Features This server provides remarkable capabilities: 1. **Rich Markdown**: Tables, code highlighting, task lists, footnotes, and more 2. **Beautiful UI**: Three-column responsive layout with sidebar, content, and TOC 3. **AI Integration**: Native llms.txt and llms-full.txt endpoints 4. **Smart Caching**: Automatic HTML caching for fast performance 5. **Security**: Path traversal protection built-in 6. **Docker Ready**: Production-optimized container 7. **Well Tested**: 71 tests with 100% pass rate 8. **Modern Python**: FastAPI, async/await, type hints ## Technical Details - **Language**: Python 3.13+ - **Framework**: FastAPI - **Markdown**: Python-Markdown with extensions - **Styling**: CSS3 with modern design - **Testing**: pytest with 71 tests - **Linting**: Ruff for code quality - **Package Manager**: uv for fast installs ## Project Structure ``` docs_server/ ├── config.py # Settings and environment ├── helpers.py # Utilities and navigation ├── caching.py # Cache operations ├── markdown_service.py # Markdown rendering ├── llms_service.py # LLMs.txt generation ├── templates.py # HTML templates └── main.py # FastAPI routes ``` ## Use Cases Perfect for: - **Open Source Projects**: Self-hosted documentation - **Internal Teams**: Company documentation portals - **API Documentation**: REST/GraphQL API docs - **Technical Writing**: Blog posts and tutorials - **Knowledge Bases**: Internal wikis ## Community - **GitHub**: github.com/yourusername/markdown-docs-server - **License**: MIT - **Python Version**: 3.13+ recommended - **Dependencies**: FastAPI, Python-Markdown, Pygments, Uvicorn ## Getting Help If you need assistance: 1. Check the [Configuration Guide](http://static.109.5.225.46.clients.your-server.de/configuration.md) 2. Review [Examples](http://static.109.5.225.46.clients.your-server.de/examples/basic.md) 3. Open a GitHub issue 4. Read the [Troubleshooting](http://static.109.5.225.46.clients.your-server.de/configuration.md#troubleshooting) section ## What Makes This Special? Unlike static site generators (Hugo, Jekyll, MkDocs), this is a **live server** that: - Renders markdown on-demand - No build step required - Hot reload in development - Dynamic caching - API endpoints for integrations - Native AI assistant support ## Quick Command Reference ```bash # Development DOCS_ROOT=./docs DEBUG=true uv run python -m docs_server # Production DOCS_ROOT=/app/docs BASE_URL=https://docs.site.com uv run python -m docs_server # Docker docker run -p 8080:8080 -v $(pwd)/docs:/app/docs markdown-docs-server # Testing uv run pytest tests/ -v # Linting uv run ruff check src/ ``` ## Status ✅ Production Ready ✅ Well Tested (71 tests, 100% passing) ✅ Fully Documented ✅ Docker Optimized ✅ Type Hinted ✅ Linted and Formatted --- For the complete documentation, visit any page listed above or explore the sidebar navigation. http://static.109.5.225.46.clients.your-server.de/index.md # Markdown Documentation Server A **lightweight, fast, and beautiful** documentation server that renders Markdown files as styled HTML with zero configuration. ## 🚀 What Makes This Special? This isn't just another static site generator. It's a **live documentation server** with remarkable features: ### ✨ Zero Configuration - Drop your `.md` files in a folder - Start the server - Beautiful docs instantly available ### 🎨 Beautiful Design - Inspired by [Nuxt UI](https://ui.nuxt.com/) documentation - Three-column layout (sidebar, content, table of contents) - Responsive design for mobile/tablet/desktop - Dark mode ready with customizable colors ### 🤖 AI-Friendly - **llms.txt** support for AI assistants - **llms-full.txt** for complete context - **MCP endpoint** for interactive queries (250x less context) - Automatic link transformation - Optimized for Claude, ChatGPT, and other LLMs ### ⚡ Performance - Intelligent caching system - Fast markdown rendering - Minimal dependencies - Production-ready Docker image ### 🎯 Developer Experience - Hot reload in development - Clear error messages - Type hints everywhere - Comprehensive test suite (71 tests, 100% passing) --- ## 📚 Quick Start ### Installation ```bash # Clone the repository git clone https://github.com/yourusername/markdown-docs-server cd markdown-docs-server # Install dependencies with uv (recommended) pip install uv uv sync # Or with pip pip install -e . ``` ### Run Locally ```bash # Development mode (auto-reload) uv run python -m docs_server # Or with environment variables DOCS_ROOT=./my-docs PORT=8080 uv run python -m docs_server ``` Visit `http://localhost:8080` and see your documentation come to life! 🎉 --- ## 🐳 Docker Deployment ### Quick Start ```bash # Build the image docker build -t markdown-docs-server . # Run with your docs docker run -p 8080:8080 \ -v $(pwd)/my-docs:/app/docs \ markdown-docs-server ``` ### Production Deployment ```bash # With environment variables docker run -d \ -p 8080:8080 \ -e BASE_URL=https://docs.example.com \ -e DEBUG=false \ -v $(pwd)/docs:/app/docs \ --restart unless-stopped \ --name docs-server \ markdown-docs-server ``` --- ## 📖 Documentation Structure Your documentation needs just **3 required files** and 1 optional: ``` docs/ ├── index.md # Homepage (required) ├── sidebar.md # Navigation structure (required) ├── topbar.md # Top bar navigation (required) └── llms.txt # AI assistant index (optional) ``` All other `.md` files are your content pages! --- ## 🎯 Key Features | Feature | Description | |---------|-------------| | **Markdown Extensions** | Tables, code highlighting, TOC, task lists, and more | | **Navigation** | Sidebar with groups, topbar with sections | | **Caching** | Smart caching for fast performance | | **Security** | Path traversal protection | | **Dual Mode** | Serve HTML or raw markdown | | **Assets** | Images, PDFs, videos supported | | **LLMs.txt** | Built-in AI assistant support | | **MCP Support** | Interactive queries via JSON-RPC (250x less context) | | **Responsive** | Mobile-first design | --- ## 🌟 What You're Seeing Now This documentation is **powered by the server itself**! Every feature you see here is built-in: - ✅ The beautiful three-column layout - ✅ Syntax-highlighted code blocks - ✅ Responsive navigation - ✅ Automatic table of contents - ✅ Markdown tables - ✅ Task lists - ✅ And much more! --- ## 🔍 Learn More Explore the documentation to see all features in action: - [**Quick Setup Guide**](quick-setup.md) - Get started in 5 minutes - [**Markdown Features**](features/markdown.md) - See what's possible - [**Navigation Guide**](features/navigation.md) - Create beautiful menus - [**LLMs.txt Guide**](features/llms-txt.md) - AI assistant integration - [**MCP Integration**](features/mcp.md) - Interactive queries for LLMs - [**Docker Deployment**](deployment/docker.md) - Production deployment - [**API Reference**](api/endpoints.md) - HTTP endpoints - [**Configuration**](configuration.md) - Environment variables --- ## 💡 Why This Server? ### For Documentation Teams - **Zero learning curve** - just write Markdown - **Beautiful by default** - no CSS needed - **Fast deployment** - Docker ready ### For Open Source Projects - **GitHub-friendly** - works with GitHub Pages - **Self-hosted** - own your docs - **Modern design** - professional appearance ### For AI/LLM Integration - **llms.txt native** - built-in AI support - **Context optimization** - smart link transformation - **Full content export** - llms-full.txt endpoint --- ## 🎨 Customization While the default theme is beautiful, you can customize: - Colors (CSS variables) - Logo (place in `assets/`) - Navigation structure (sidebar.md, topbar.md) - Content organization (any folder structure) --- ## 🧪 Quality This is a **production-ready** server with: - ✅ **71 unit tests** (100% passing) - ✅ **Type hints** everywhere - ✅ **Linting** with Ruff - ✅ **CI/CD** ready - ✅ **Docker** optimized - ✅ **Security** focused --- ## 🤝 Contributing Contributions welcome! This server is: - 🐍 **Python 3.13+** with modern features - ⚡ **FastAPI** for performance - 📦 **uv** for fast dependency management - 🧪 **pytest** for comprehensive testing --- ## 📜 License MIT License - use it freely for any project! --- ## 🚀 Next Steps 1. **[Quick Setup](quick-setup.md)** - Get running in 5 minutes 2. **[Features Guide](features/markdown.md)** - Explore all capabilities 3. **[Deployment](deployment/docker.md)** - Go to production ---

Ready to Create Beautiful Docs?

Get started now and see your documentation transform!

uv run python -m docs_server
http://static.109.5.225.46.clients.your-server.de/quick-setup.md # Quick Setup Guide Get your documentation server running in **5 minutes** or less! ## Prerequisites - Python 3.13+ (or Python 3.11+ with minor adjustments) - `uv` package manager (recommended) or `pip` ## Step 1: Install ### Option A: With uv (Recommended) ```bash # Install uv if you haven't already pip install uv # Clone and setup git clone https://github.com/yourusername/markdown-docs-server cd markdown-docs-server uv sync ``` ### Option B: With pip ```bash # Clone and setup git clone https://github.com/yourusername/markdown-docs-server cd markdown-docs-server pip install -e . ``` ## Step 2: Prepare Your Docs Create a `docs` folder with required files: ```bash mkdir -p docs cd docs ``` ### Required Files **1. Create `index.md`** (your homepage): ```markdown # Welcome to My Documentation This is the homepage of my documentation. ## Quick Links - [Getting Started](getting-started.md) - [API Reference](api.md) ``` **2. Create `sidebar.md`** (navigation structure): ```markdown # Navigation * [Home](index.md) * [Getting Started](getting-started.md) * [API Reference](api.md) * [Authentication](api/auth.md) * [Endpoints](api/endpoints.md) ``` **3. Create `topbar.md`** (top navigation): ```markdown # Top Bar ## left * [Docs](index.md) ## right * [GitHub](https://github.com/yourproject) ``` ## Step 3: Run the Server ```bash # From the project root DOCS_ROOT=./docs uv run python -m docs_server ``` Or for development with auto-reload: ```bash DOCS_ROOT=./docs DEBUG=true uv run python -m docs_server ``` ## Step 4: View Your Docs Open your browser to: - **Homepage**: http://localhost:8080 - **Any page**: http://localhost:8080/getting-started.html - **Raw markdown**: http://localhost:8080/getting-started.md - **Health check**: http://localhost:8080/health - **LLMs.txt**: http://localhost:8080/llms.txt 🎉 **That's it!** Your documentation is live! --- ## Quick Docker Setup Prefer Docker? Even faster: ```bash # Build docker build -t my-docs . # Run docker run -p 8080:8080 -v $(pwd)/docs:/app/docs my-docs ``` Visit http://localhost:8080 --- ## Environment Variables Customize behavior with environment variables: ```bash # Documentation root (default: ./test_docs or /app/docs in Docker) DOCS_ROOT=./my-docs # Cache directory (default: ./__cache__ or /app/cache in Docker) CACHE_ROOT=./my-cache # Base URL for llms.txt absolute links (auto-detected if not set) BASE_URL=https://docs.mysite.com # Enable debug mode with auto-reload (default: false) DEBUG=true # Server port (default: 8080) PORT=3000 ``` --- ## File Structure Your docs directory should look like this: ``` docs/ ├── index.md # Required: Homepage ├── sidebar.md # Required: Sidebar navigation ├── topbar.md # Required: Top bar ├── llms.txt # Optional: AI assistant index ├── getting-started.md # Your content pages ├── api.md ├── api/ │ ├── auth.md │ └── endpoints.md └── assets/ # Optional: Images, etc. └── logo.svg ``` --- ## Next Steps Now that your server is running: 1. **[Explore Features](features/markdown.md)** - See what's possible with Markdown 2. **[Configure Navigation](features/navigation.md)** - Customize your sidebar and topbar 3. **[Deploy to Production](deployment/docker.md)** - Take it live! --- ## Troubleshooting ### Server won't start? Check that Python 3.13+ is installed: ```bash python --version # Should show 3.13.0 or higher ``` ### Can't find docs? Make sure `DOCS_ROOT` points to the correct directory: ```bash ls $DOCS_ROOT # Should show: index.md sidebar.md topbar.md ``` ### Port already in use? Change the port: ```bash PORT=3000 uv run python -m docs_server ``` ### Need help? - Check the [Configuration Guide](configuration.md) - Review [Examples](examples/basic.md) - Open an issue on GitHub --- ## What's Next? Your documentation is now live! Here's what you can do: ✅ Add more markdown pages ✅ Customize navigation ✅ Add images and assets ✅ Enable llms.txt for AI ✅ Deploy to production **Happy documenting!** 📚 http://static.109.5.225.46.clients.your-server.de/configuration.md # Configuration Configure the documentation server with environment variables and file structure. ## Environment Variables ### Core Settings | Variable | Default | Description | |----------|---------|-------------| | `DOCS_ROOT` | `./test_docs` or `/app/docs` | Root directory for markdown files | | `CACHE_ROOT` | `./__cache__` or `/app/cache` | Cache directory for rendered HTML | | `PORT` | `8080` | HTTP server port | | `DEBUG` | `false` | Enable debug mode with auto-reload | | `BASE_URL` | Auto-detected | Base URL for absolute links in llms.txt and Copy page AI links (ChatGPT, Claude) | | `SERVEMD_BRANDING_ENABLED` | `true` | Show "Powered by servemd" footer. Set to `false` to disable for white-label or self-hosted deployments | | `CUSTOM_CSS` | `custom.css` | Filename of custom CSS in DOCS_ROOT. Loaded on every page after default styles. See [Customization](features/customization.html) | ### MCP Settings | Variable | Default | Description | |----------|---------|-------------| | `MCP_ENABLED` | `true` | Enable/disable MCP endpoint | | `MCP_RATE_LIMIT_REQUESTS` | `120` | Max requests per window per IP | | `MCP_RATE_LIMIT_WINDOW` | `60` | Rate limit window in seconds | | `MCP_MAX_SEARCH_RESULTS` | `10` | Default max search results | | `MCP_SNIPPET_LENGTH` | `200` | Max characters for search snippets | ### Example Configurations **Development:** ```bash DOCS_ROOT=./docs \ DEBUG=true \ PORT=3000 \ uv run python -m docs_server ``` **Production:** ```bash DOCS_ROOT=/var/www/docs \ CACHE_ROOT=/var/cache/docs \ BASE_URL=https://docs.example.com \ PORT=8080 \ uv run python -m docs_server ``` **Clear cache on startup:** ```bash uv run python -m docs_server --clear-cache ``` **Docker:** ```bash docker run \ -e DOCS_ROOT=/app/docs \ -e BASE_URL=https://docs.mysite.com \ -e DEBUG=false \ -p 8080:8080 \ -v $(pwd)/docs:/app/docs \ markdown-docs-server ``` **White-label (disable branding):** ```bash SERVEMD_BRANDING_ENABLED=false uv run python -m docs_server ``` The "Powered by servemd" footer is shown by default. Disable it with `SERVEMD_BRANDING_ENABLED=false` for white-label or self-hosted deployments where you prefer no attribution. ### Custom CSS Place a CSS file (e.g. `custom.css`) in `DOCS_ROOT`. It is served at `/custom.css` and loaded on every page **after** the default styles, so your rules override defaults. Use `CUSTOM_CSS=theme.css` to serve a different filename. See [Customization](features/customization.html) for CSS variables and examples. --- ## Required File Structure Your `DOCS_ROOT` must contain three required files: ``` docs/ ├── index.md # Homepage (REQUIRED) ├── sidebar.md # Sidebar navigation (REQUIRED) └── topbar.md # Top bar navigation (REQUIRED) ``` ### index.md Your documentation homepage: ```markdown # Welcome to My Project Quick introduction and getting started guide. ## Features - Feature 1 - Feature 2 ## Quick Start [Get started here](quick-start.md) ``` ### sidebar.md Hierarchical navigation structure: ```markdown # Navigation * [Home](index.md) * [Getting Started](getting-started.md) * [User Guide](user-guide.md) * [Installation](user-guide/install.md) * [Configuration](user-guide/config.md) * [API Reference](api.md) * [REST API](api/rest.md) * [GraphQL](api/graphql.md) ``` **Rules:** - Top-level items: `* [Title](link.md)` - Child items: ` * [Title](link.md)` (2 spaces indent) - Sections automatically detected - `.md` extensions converted to `.html` in rendered output ### topbar.md Top bar with left/middle/right sections: ```markdown # Top Bar Navigation ## left * [📚 Docs](index.md) * [🚀 Quick Start](quick-start.md) ## middle * [v2.0.0](https://github.com/project/releases) ## right * [GitHub](https://github.com/project) * [Discord](https://discord.gg/project) ``` **Sections:** - `## left` - Left side (logo, main links) - `## middle` - Center (optional, breadcrumbs) - `## right` - Right side (external links, social) **Placeholders** (double braces so `{logo}` displays literally elsewhere): | Tag | Syntax | Purpose | |-----|--------|---------| | `{{logo}}` | `* {{logo}} \| [Home](index.md)` | Logo + link in left section | | `{{search}}` | `* {{search}}` or `* {{search:icon=...,mode=...,placeholder=...}}` | Search bar (MCP search when enabled) | See [Navigation Features](features/navigation.md) for all `{{search}}` options: `icon` (lucide-search, lucide-x, custom SVG), `mode` (full, button, input), `placeholder`. --- ## Optional Files ### llms.txt AI assistant index (see [LLMs.txt Guide](features/llms-txt.md)): ```markdown # Project Documentation [Homepage](index.md) [Quick Start](quick-start.md) [API Reference](api.md) ``` If not provided, auto-generated from `sidebar.md` + `index.md`. ### assets/ Place static assets in an `assets/` folder: ``` docs/ └── assets/ ├── logo.svg ├── screenshot.png └── diagram.pdf ``` Reference in markdown: ```markdown ![Logo](assets/logo.svg) [Download PDF](assets/diagram.pdf) ``` --- ## Directory Structure Organize content in subdirectories: ``` docs/ ├── index.md ├── sidebar.md ├── topbar.md ├── getting-started.md ├── user-guide/ │ ├── installation.md │ ├── configuration.md │ └── troubleshooting.md ├── api/ │ ├── rest.md │ ├── graphql.md │ └── webhooks.md ├── deployment/ │ ├── docker.md │ ├── kubernetes.md │ └── cloud.md └── assets/ ├── logo.svg └── images/ └── screenshot.png ``` **Best practices:** - Group related content in folders - Use clear, URL-friendly names - Keep hierarchy shallow (2-3 levels max) - Use descriptive filenames --- ## Markdown Configuration The server uses these Markdown extensions: ### Enabled Extensions | Extension | Purpose | |-----------|---------| | `codehilite` | Syntax highlighting for code blocks | | `toc` | Automatic table of contents | | `tables` | GitHub-style tables | | `fenced_code` | ``` code blocks | | `footnotes` | Footnote support[^1] | | `attr_list` | HTML attributes in markdown | | `def_list` | Definition lists | | `abbr` | Abbreviations | | `pymdownx.superfences` | Advanced code blocks | | `pymdownx.tasklist` | - [ ] Task lists | | `pymdownx.highlight` | Enhanced highlighting | | `pymdownx.inlinehilite` | Inline code highlight | [^1]: Like this footnote! ### Extension Configuration Customize in `config.py`: ```python markdown_extension_configs = { "codehilite": { "css_class": "highlight", "use_pygments": True, }, "toc": { "permalink": True, "toc_depth": 3, "permalink_title": "🔗", }, "pymdownx.tasklist": { "custom_checkbox": True, }, } ``` --- ## Caching Strategy ### How It Works 1. **First request**: Markdown rendered to HTML, cached 2. **Subsequent requests**: Served from cache (instant) 3. **Server restart**: Cache cleared automatically ### Cache Location ```bash # Default cache directory CACHE_ROOT=./__cache__ # Custom cache directory CACHE_ROOT=/tmp/docs-cache ``` ### Cache Files ``` __cache__/ ├── index.html # Cached homepage ├── quick-start.html # Cached page ├── user-guide/ │ └── installation.html ├── llms.txt # Cached llms.txt └── llms-full.txt # Cached full content ``` ### Manual Cache Clear ```bash # Remove cache directory rm -rf __cache__ # Server will recreate on next request ``` --- ## Security Settings ### Path Traversal Protection Built-in security prevents directory traversal: ```python # These are blocked: /../../../../etc/passwd ❌ /../secret.md ❌ /../../config.yml ❌ # These work: /user-guide/install.md ✅ /api/endpoints.md ✅ ``` ### Safe Path Validation All file paths are validated before serving: ```python def is_safe_path(path: str, base_path: Path) -> bool: """Validate path is within allowed directory.""" abs_base = base_path.resolve() abs_path = (base_path / path).resolve() return os.path.commonpath([abs_base, abs_path]) == str(abs_base) ``` --- ## URL Routing ### HTML Mode Serves rendered HTML: ``` http://localhost:8080/index.html → Rendered http://localhost:8080/api/endpoints.html → Rendered ``` ### Raw Markdown Mode Serves original markdown: ``` http://localhost:8080/index.md → Raw markdown http://localhost:8080/api/endpoints.md → Raw markdown ``` ### Static Assets Direct file serving: ``` http://localhost:8080/assets/logo.svg → Static file http://localhost:8080/assets/doc.pdf → Static file ``` ### Special Endpoints ``` http://localhost:8080/ → Redirects to /index.html http://localhost:8080/health → Health check JSON http://localhost:8080/llms.txt → AI assistant index http://localhost:8080/llms-full.txt → Full documentation ``` --- ## MCP Cache Considerations ### Kubernetes / k3s Deployments When deploying to Kubernetes or k3s with MCP enabled: **Cache Persistence:** - MCP search index is stored in `CACHE_ROOT/mcp/` - Each pod builds its own index on first startup (~200ms for typical docs) - Cache persists across container restarts if volume is mounted - Recommended: Use emptyDir volume for cache (ephemeral, fast) ```yaml # Example volume mount for cache volumes: - name: cache emptyDir: {} volumeMounts: - name: cache mountPath: /app/cache ``` **Horizontal Scaling:** - Each pod maintains its own independent search index - Index rebuilds automatically when docs change (hash-based validation) - No shared state required between pods - Rate limiting is per-pod (each pod has 120 req/min limit) **Startup Performance:** - First startup: ~200ms to build index (100 docs) - Subsequent startups: ~10ms to load from cache - Health check passes immediately (MCP initialization is async) **Environment Variables:** ```yaml env: - name: MCP_ENABLED value: "true" - name: MCP_RATE_LIMIT_REQUESTS value: "120" - name: CACHE_ROOT value: "/app/cache" ``` ## Production Checklist Before deploying to production: - [ ] Set `DEBUG=false` - [ ] Configure `BASE_URL` for llms.txt - [ ] Use proper `DOCS_ROOT` path - [ ] Set up cache directory with write permissions - [ ] Configure reverse proxy (nginx/caddy) - [ ] Enable HTTPS - [ ] Set proper PORT if needed - [ ] Add health check monitoring - [ ] Configure log aggregation - [ ] Set up backup for docs - [ ] For k8s/k3s: Configure emptyDir volume for cache - [ ] For k8s/k3s: Consider per-pod rate limit scaling --- ## Troubleshooting ### Server won't start Check port availability: ```bash lsof -i :8080 # See what's using port 8080 ``` ### Files not found Verify `DOCS_ROOT`: ```bash echo $DOCS_ROOT ls $DOCS_ROOT # Should show index.md, sidebar.md, topbar.md ``` ### Styling broken Check for required files: ```bash ls $DOCS_ROOT/sidebar.md ls $DOCS_ROOT/topbar.md ``` ### Cache issues Clear and restart: ```bash rm -rf __cache__ uv run python -m docs_server ``` --- ## Advanced Configuration ### Custom Port ```bash PORT=3000 uv run python -m docs_server ``` ### Multiple Environments ```bash # Development cp .env.development .env uv run python -m docs_server # Production cp .env.production .env uv run python -m docs_server ``` ### Environment File Create `.env`: ```bash DOCS_ROOT=./docs CACHE_ROOT=./__cache__ PORT=8080 DEBUG=false BASE_URL=https://docs.mysite.com ``` Load with: ```bash source .env && uv run python -m docs_server ``` --- ## Next Steps - **[Deployment Guide](deployment/docker.md)** - Deploy to production - **[API Reference](api/endpoints.md)** - HTTP endpoints - **[Examples](examples/basic.md)** - Configuration examples http://static.109.5.225.46.clients.your-server.de/features/markdown.md # Markdown Features This server supports **rich Markdown** with powerful extensions. See them all in action! ## Headings # H1 Heading ## H2 Heading ### H3 Heading #### H4 Heading ##### H5 Heading ###### H6 Heading All headings automatically get: - Unique IDs for linking - Permalink icons on hover (🔗) - Table of contents entries --- ## Text Formatting **Bold text** using `**bold**` *Italic text* using `*italic*` ***Bold and italic*** using `***both***` ~~Strikethrough~~ using `~~strikethrough~~` --- ## Lists ### Unordered Lists * Item 1 * Item 2 * Nested item 2.1 * Nested item 2.2 * Item 3 ### Ordered Lists 1. First item 2. Second item 1. Nested 2.1 2. Nested 2.2 3. Third item ### Task Lists - [x] Completed task - [x] Another completed task - [ ] Pending task - [ ] Another pending task --- ## Code Blocks ### Inline Code Use `backticks` for inline code like `const x = 5;` ### Syntax Highlighted Blocks Python example: ```python def fibonacci(n): """Calculate Fibonacci number.""" if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2) # Usage result = fibonacci(10) print(f"Fibonacci(10) = {result}") ``` JavaScript example: ```javascript // Async/await example async function fetchData(url) { try { const response = await fetch(url); const data = await response.json(); return data; } catch (error) { console.error('Error:', error); } } ``` Bash example: ```bash # Docker deployment docker build -t my-app . docker run -p 8080:8080 my-app # With environment variables docker run \ -e DEBUG=true \ -e PORT=3000 \ -p 3000:3000 \ my-app ``` --- ## Tables Tables are fully supported with automatic styling: | Feature | Supported | Notes | |---------|-----------|-------| | Markdown | ✅ Yes | Full CommonMark support | | Code Highlighting | ✅ Yes | Pygments-powered | | Tables | ✅ Yes | You're looking at one! | | Math | ❌ No | Not yet implemented | | Mermaid | ✅ Yes | Diagrams supported | ### Table with Alignment | Left Aligned | Center Aligned | Right Aligned | |:-------------|:--------------:|--------------:| | Left | Center | Right | | Text | Text | Text | | More | More | More | --- ## Links ### Internal Links Link to other pages: [Quick Setup Guide](../quick-setup.md) Link to sections: [Back to Code Blocks](#code-blocks) ### External Links Visit [GitHub](https://github.com) or [Python.org](https://python.org) External links open in new tabs automatically in the navigation. --- ## Blockquotes > This is a blockquote. > It can span multiple lines. > > And even multiple paragraphs! > **Pro Tip**: Blockquotes are great for callouts, tips, and warnings. --- ## Horizontal Rules Separate content with horizontal rules: --- Like that one above! --- ## Images Images are automatically handled: ![Example Image](../assets/example.png) Images support: - PNG, JPG, GIF, SVG - Automatic sizing - Responsive layout - Lazy loading --- ## Footnotes You can add footnotes[^1] to your documentation. Another footnote[^2] reference. [^1]: This is the first footnote. [^2]: This is the second footnote with more text. --- ## Definition Lists Term 1 : Definition of term 1 Term 2 : Definition of term 2 : Another definition for term 2 --- ## Abbreviations The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium --- ## Advanced Features ### Nested Lists with Code 1. First step ```python print("Step 1") ``` 2. Second step ```python print("Step 2") ``` 3. Third step ### Mixed Content You can mix **bold**, *italic*, `code`, and [links](#) in tables: | Feature | Code | Link | |---------|------|------| | **Bold** | `code` | [link](#) | | *Italic* | `more` | [another](#) | --- ## Escaping Need to show literal markdown? Escape with backslash: \*\*Not bold\*\* \`Not code\` \[Not a link\](url) --- ## Special Characters The server handles special characters correctly: - En dash: – - Em dash: — - Ellipsis: … - Quotes: "smart" 'quotes' - Symbols: © ® ™ - Arrows: → ← ↑ ↓ - Math: ± × ÷ ≠ ≈ - Emojis: 🎉 🚀 ✅ ❌ 💡 --- ## What's Not Supported? Currently not implemented: - Math equations (LaTeX) - Embedded videos - Custom HTML components - MDX-style components Everything else from [CommonMark](https://commonmark.org/) and popular extensions is supported! --- ## Next Steps - **[Navigation Features](navigation.md)** - Learn about sidebar and topbar - **[LLMs.txt Support](llms-txt.md)** - AI assistant integration - **[Examples](../examples/advanced.md)** - See real-world examples http://static.109.5.225.46.clients.your-server.de/features/navigation.md # Navigation Features Create beautiful, hierarchical navigation with sidebar and topbar support. ## Sidebar Navigation The sidebar provides the main documentation structure with collapsible groups. ### Structure Format Create `sidebar.md` with this format: ```markdown # Navigation * [Home](index.md) * [Getting Started](getting-started.md) * [User Guide](user-guide.md) * [Installation](user-guide/install.md) * [Configuration](user-guide/config.md) * [Troubleshooting](user-guide/troubleshoot.md) * [API Reference](api.md) * [REST API](api/rest.md) * [GraphQL](api/graphql.md) ``` ### Rules - **Top-level items**: `* [Title](link.md)` (no indentation) - **Child items**: ` * [Title](link.md)` (2 spaces) - **No nesting beyond 2 levels** (keep it simple) - **Links auto-convert**: `.md` → `.html` in rendered output ### Types The sidebar automatically detects two types: 1. **Standalone Links** - No children, clickable 2. **Groups** - Has children, header + children both clickable --- ## Topbar Navigation The topbar provides quick access to key pages and external links. ### Placeholders Topbar items support special placeholders. Use double braces so that single braces like `{logo}` display as literal text in documentation: | Tag | Section | Purpose | |-----|---------|---------| | `{{logo}}` | left | Logo + optional link (see [Logo Support](#logo-support)) | | `{{search}}` | left, middle, or right | Search bar when MCP is enabled (see [Search Bar Placement](#search-bar-placement)) | ### Structure Format Create `topbar.md` with sections: ```markdown # Top Bar ## left * [📚 Docs](index.md) * [🚀 Quick Start](quick-start.md) ## middle * Version 2.0 ## right * [GitHub](https://github.com/project) * [Discord](https://discord.gg/project) ``` ### Sections **Left Section** - Main navigation ```markdown ## left * [Home](index.md) * [Docs](docs.md) ``` **Middle Section** - Breadcrumbs, version info (optional) ```markdown ## middle * v2.0.0 * [Changelog](changelog.md) ``` **Right Section** - External links, social ```markdown ## right * [GitHub](https://github.com/project) * [Twitter](https://twitter.com/project) ``` --- ## Search Bar Placement When MCP search is enabled, place the search bar exactly where you want it using the `{{search}}` placeholder in any topbar section (left, middle, or right). > **Re{{search}} the `{{search}}` tag** — defaults can be set right in the tag. See all options below. ### Syntax | Syntax | Description | |--------|-------------| | `{{search}}` | Defaults: full mode, search icon, "Search..." placeholder | | `{{search:key=value}}` | Single parameter | | `{{search:key1=val1,key2=val2}}` | Multiple parameters (comma-separated) | ### All Parameters | Parameter | Values | Default | Description | |-----------|--------|---------|-------------| | `icon` | `i-lucide-star`, `lucide-search`, `lucide-x`, `lucide-star`, or path like `assets/search.svg` | `lucide-search` | Icon shown in button and input. Use `i-lucide-{name}` for any [Lucide icon](https://lucide.dev/icons) (loaded from Iconify CDN). Built-in: lucide-search, lucide-x, lucide-star. Custom paths are relative to `DOCS_ROOT`. | | `mode` | `full`, `button`, `input` | `full` | `full` = input + trailing icon, always visible; `button` = icon only, tap to expand; `input` = input only, no icon. | | `placeholder` | Any string | `Search...` | Placeholder text in the search input. | ### All Options — Examples **Default (no params):** ```markdown * {{search}} ``` **Icon options:** ```markdown * {{search:icon=lucide-search}} * {{search:icon=i-lucide-star}} * {{search:icon=i-lucide-search}} * {{search:icon=lucide-x}} * {{search:icon=lucide-star}} * {{search:icon=assets/search.svg}} ``` **Mode options:** ```markdown * {{search:mode=full}} * {{search:mode=button}} * {{search:mode=input}} ``` **Placeholder:** ```markdown * {{search:placeholder=Search...}} * {{search:placeholder=Zoeken...}} * {{search:placeholder=Find a page...}} ``` **Combined (all params):** ```markdown * {{search:icon=lucide-search,mode=button,placeholder=Zoeken...}} * {{search:mode=button,placeholder=Find...}} * {{search:icon=assets/search.svg,placeholder=Search docs...}} ``` When `{{search}}` is present, the search bar renders at that position. When absent, it defaults to the far right of the right section. ### Keyboard Shortcuts | Key | Action | |-----|--------| | `/` | Focus the search bar (ignored when focus is in an input or textarea) | | `Escape` | Blur the search input | --- ## Copy Page Dropdown On every documentation page, a **Copy page** dropdown appears to the right of the page title (Nuxt UI-style). It provides: | Option | Description | |--------|--------------| | **Copy Markdown link** | Copies `[Page Title](page_url)` to the clipboard | | **View as Markdown** | Opens the raw `.md` file in a new tab | | **Open in Mistral Le Chat** | Opens Mistral Le Chat with a pre-filled prompt to read the page | | **Open in ChatGPT** | Opens ChatGPT with a pre-filled prompt to read the page | | **Open in Claude** | Opens Claude with a pre-filled prompt to read the page | The AI links use the raw markdown URL so assistants can fetch and read the page content. For self-hosted deployments, set `BASE_URL` in your environment so these links use your public URL: ```bash BASE_URL=https://docs.example.com uv run python -m docs_server ``` Without `BASE_URL`, the server uses the request URL (e.g. `http://localhost:8080`), which works locally but may not be reachable by AI assistants when deployed. --- ## Active State Highlighting Both sidebar and topbar automatically highlight the current page. **In sidebar:** - Active page gets blue background - Orange left border accent - Bold text **In topbar:** - Active link gets blue background - Subtle color change --- ## Logo Support Add a logo to the topbar left section: ```markdown ## left * {{logo}} | [Home](index.md) * [Docs](docs.md) ``` Place your logo at `docs/assets/logo.svg` --- ## Examples ### Minimal Sidebar ```markdown # Navigation * [Home](index.md) * [About](about.md) * [Contact](contact.md) ``` ### Complex Sidebar ```markdown # Documentation * [Home](index.md) * [Quick Start](quick-start.md) * [Features](features.md) * [Markdown Support](features/markdown.md) * [Navigation](features/navigation.md) * [LLMs.txt](features/llms-txt.md) * [Caching](features/caching.md) * [Deployment](deployment.md) * [Docker](deployment/docker.md) * [Kubernetes](deployment/k8s.md) * [Cloud](deployment/cloud.md) * [API Reference](api.md) * [Endpoints](api/endpoints.md) * [Authentication](api/auth.md) * [Rate Limiting](api/rate-limit.md) * [Contributing](contributing.md) * [Code of Conduct](contributing/coc.md) * [Development Setup](contributing/setup.md) * [Pull Request Process](contributing/pr-process.md) ``` ### Simple Topbar ```markdown # Top Bar ## left * [Docs](index.md) ## right * [GitHub](https://github.com/project) ``` ### Full Topbar ```markdown # Top Navigation ## left * {{logo}} | [Docs Home](index.md) * [Quick Start](quick-start.md) * [API](api.md) ## middle * v2.1.0 * [Release Notes](changelog.md) ## right * [GitHub](https://github.com/project) * [Issues](https://github.com/project/issues) * [Discord](https://discord.gg/project) * [Twitter](https://twitter.com/project) ``` --- ## Best Practices ### Sidebar ✅ **DO:** - Keep hierarchy shallow (max 2 levels) - Use clear, descriptive titles - Group related content - Order by user journey - Limit to 10-15 top-level items ❌ **DON'T:** - Over-nest (3+ levels) - Use generic titles ("Misc", "Other") - List every single page - Alphabetize blindly - Create huge lists ### Topbar ✅ **DO:** - Keep it minimal (3-5 items per section) - Put important links in left - Use icons/emojis for visual interest - Link to external resources in right - Version info in middle ❌ **DON'T:** - Overload with links - Duplicate sidebar content - Use only text (boring!) - Hide important pages - Ignore mobile users --- ## Responsive Behavior ### Desktop (>768px) - Sidebar: Fixed left, always visible - Topbar: Full width with all sections - TOC: Fixed right (if content has headings) ### Tablet (768px-1200px) - Sidebar: Fixed left, collapsible - Topbar: Full width - TOC: Hidden ### Mobile (<768px) - Sidebar: Hidden by default, slide-in menu - Topbar: Compact, hamburger menu - TOC: Hidden --- ## Styling ### Colors Navigation uses the theme colors: ```css --accent-primary: #f26a28; /* Accent color */ --color-primary: #3b82f6; /* Active links */ --color-gray-700: #374151; /* Normal text */ --color-gray-50: #f9fafb; /* Hover background */ ``` ### Customization To customize, modify `templates.py`: ```python # Change accent color .nav-group-header.active { border-left: 3px solid #your-color; } # Change hover color .nav-group-link:hover { background-color: #your-color; } ``` --- ## Next Steps - **[Markdown Features](markdown.md)** - Content capabilities - **[LLMs.txt Support](llms-txt.md)** - AI integration - **[Examples](../examples/basic.md)** - Real-world examples http://static.109.5.225.46.clients.your-server.de/features/llms-txt.md # LLMs.txt Support One of the most **remarkable features** of this documentation server: built-in support for AI assistants! ## What is llms.txt? [llms.txt](https://llmstxt.org/) is an emerging standard for making documentation easily consumable by Large Language Models (LLMs) like Claude, ChatGPT, and others. Think of it as a **sitemap for AI assistants** - a standardized way to present your documentation structure so AI can understand and reference it accurately. --- ## Why This Matters When you ask an AI assistant about your project: ❌ **Without llms.txt**: AI might hallucinate, miss pages, or give outdated info ✅ **With llms.txt**: AI gets accurate, structured access to all your documentation --- ## Automatic Generation This server provides **two strategies** for llms.txt: ### Strategy 1: Curated (Recommended) Create a custom `llms.txt` in your docs root: ```markdown # My Project Documentation Brief description of your project. ## Getting Started [Quick Start](quick-start.md) [Installation](installation.md) ## Core Concepts [Architecture](architecture.md) [API Reference](api.md) ## Advanced [Deployment](deployment.md) [Troubleshooting](troubleshooting.md) ``` **Benefits:** - Full control over AI context - Curated order and grouping - Custom descriptions - Priority ranking ### Strategy 2: Auto-Generated (Fallback) If no `llms.txt` exists, the server automatically generates one from: 1. Your `sidebar.md` (navigation structure) 2. Your `index.md` (homepage content) **Benefits:** - Zero configuration - Always up-to-date - Follows your navigation --- ## Two Endpoints ### 1. `/llms.txt` - Index A lightweight index of your documentation: ```bash curl http://localhost:8080/llms.txt ``` Returns: ``` # Project Documentation [Page 1](https://yourdomain.com/page1.md) [Page 2](https://yourdomain.com/page2.md) ... ``` **Features:** - Relative links → Absolute URLs - Smart caching - Follows llms.txt spec ### 2. `/llms-full.txt` - Complete Content All your documentation in one file: ```bash curl http://localhost:8080/llms-full.txt ``` Returns: ``` # Index content here https://yourdomain.com/page1.md Full content of page1.md https://yourdomain.com/page2.md Full content of page2.md ``` **Use cases:** - Full context for AI - Offline documentation - Complete project dump --- ## Link Transformation The server automatically transforms relative links to absolute URLs: **Input (your markdown):** ```markdown [Getting Started](getting-started.md) [API](api/endpoints.md) ``` **Output (llms.txt):** ```markdown [Getting Started](https://yourdomain.com/getting-started.md) [API](https://yourdomain.com/api/endpoints.md) ``` This ensures AI assistants can fetch the actual content! --- ## Base URL Configuration Control the base URL for absolute links: ### Auto-Detection (Default) ```bash # Server detects from request # Request: http://localhost:8080/llms.txt # Links: http://localhost:8080/page.md ``` ### Manual Configuration ```bash # Set explicit base URL BASE_URL=https://docs.myproject.com uv run python -m docs_server # In Docker docker run -e BASE_URL=https://docs.myproject.com ... ``` --- ## Using with AI Assistants ### Claude (claude.ai) 1. Upload your `/llms-full.txt` 2. Ask questions about your docs 3. Claude has full context! ### ChatGPT 1. Share your `/llms.txt` URL 2. ChatGPT can fetch pages as needed 3. Accurate, up-to-date responses ### Cursor/Copilot 1. Reference your documentation URL 2. Code assistants can look up APIs 3. Better code completion --- ## Example: Curated llms.txt Here's a well-structured example: ```markdown # Awesome Project A revolutionary way to do X, Y, and Z. ## Quick Links - [Homepage](https://docs.awesome.com/index.md) - [Quick Start](https://docs.awesome.com/quick-start.md) ## Documentation Structure ### Getting Started Essential reading for new users: - [Installation](https://docs.awesome.com/install.md) - [Configuration](https://docs.awesome.com/config.md) - [First Steps](https://docs.awesome.com/first-steps.md) ### Core Concepts Deep dives into how it works: - [Architecture](https://docs.awesome.com/architecture.md) - [Data Model](https://docs.awesome.com/data-model.md) - [API Design](https://docs.awesome.com/api-design.md) ### API Reference Complete API documentation: - [REST API](https://docs.awesome.com/api/rest.md) - [GraphQL API](https://docs.awesome.com/api/graphql.md) - [Webhooks](https://docs.awesome.com/api/webhooks.md) ### Deployment Production deployment guides: - [Docker](https://docs.awesome.com/deploy/docker.md) - [Kubernetes](https://docs.awesome.com/deploy/k8s.md) - [Cloud Providers](https://docs.awesome.com/deploy/cloud.md) ## FAQ - [Common Issues](https://docs.awesome.com/faq.md) - [Troubleshooting](https://docs.awesome.com/troubleshooting.md) ## Additional Resources - GitHub: https://github.com/awesome/project - Discord: https://discord.gg/awesome - Blog: https://blog.awesome.com ``` --- ## Caching Both endpoints are **intelligently cached**: - ✅ First request: Generates content (slow) - ✅ Subsequent requests: Serves from cache (instant) - ✅ Server restart: Cache cleared, regenerated No manual cache management needed! --- ## Testing Your llms.txt ### Check Format ```bash # View in browser open http://localhost:8080/llms.txt # Or with curl curl http://localhost:8080/llms.txt ``` ### Validate Links ```bash # All links should be absolute curl http://localhost:8080/llms.txt | grep -E '\[.*\]\(http' ``` ### Check Full Content ```bash # See complete documentation curl http://localhost:8080/llms-full.txt | head -100 ``` --- ## Best Practices ### DO ✅ - Keep llms.txt focused on essential pages - Use clear, descriptive titles - Group related content - Include direct links (not anchors) - Update when adding major pages ### DON'T ❌ - Don't list every single page - Don't use relative links (server handles this) - Don't duplicate content - Don't forget descriptions - Don't ignore the structure --- ## Real-World Impact **Before llms.txt:** ``` User: "How do I deploy this?" AI: "I'm not sure, let me guess..." (hallucinates) ``` **After llms.txt:** ``` User: "How do I deploy this?" AI: "According to your deployment docs at /deploy/docker.md..." (accurate!) ``` --- ## Specification Compliance This server follows the [llms.txt spec](https://llmstxt.org/): ✅ Plain text format ✅ Markdown structure ✅ Absolute URLs ✅ Clear hierarchy ✅ Complete context option --- ## Advanced: Custom Generation Want custom llms.txt logic? Extend the server: ```python # In llms_service.py async def generate_llms_txt_content(base_url: str) -> str: # Your custom logic here # - Filter pages by category # - Add custom metadata # - Generate from database pass ``` --- ## What's Next? - **[Configuration](../configuration.md)** - Environment variables - **[API Reference](../api/endpoints.md)** - All HTTP endpoints - **[Examples](../examples/advanced.md)** - See it in action --- ## Resources - [llmstxt.org](https://llmstxt.org/) - Official specification - [Example llms.txt files](https://github.com/search?q=llms.txt) - [AI Documentation Best Practices](https://example.com) ---
💡 Pro Tip: Test your llms.txt by asking Claude or ChatGPT questions about your docs. You'll be amazed at how accurate the responses become!
http://static.109.5.225.46.clients.your-server.de/deployment/docker.md # Docker Deployment Deploy the documentation server with Docker for production use. ## Quick Start ```bash # Build the image docker build -t markdown-docs-server . # Run with your docs docker run -d \ -p 8080:8080 \ -v $(pwd)/docs:/app/docs \ --name docs-server \ markdown-docs-server ``` Visit http://localhost:8080 --- ## Dockerfile The included Dockerfile is production-optimized: ```dockerfile FROM python:3.13-slim # Install uv RUN pip install --no-cache-dir uv # Set working directory WORKDIR /app # Copy dependency files COPY pyproject.toml uv.lock ./ # Install dependencies RUN uv sync --no-dev # Copy source code COPY src/ ./src/ # Create directories RUN mkdir -p /app/docs /app/cache # Default environment variables ENV DOCS_ROOT=/app/docs ENV CACHE_ROOT=/app/cache ENV PORT=8080 # Expose port EXPOSE 8080 # Run server CMD ["uv", "run", "python", "-m", "docs_server"] ``` **Features:** - Python 3.13 slim base - Multi-stage build for minimal size - Non-root user (TODO: add in production) - Caching layers for fast rebuilds - Healthcheck support --- ## Building ### Basic Build ```bash docker build -t my-docs . ``` ### With Build Args ```bash docker build \ --build-arg PYTHON_VERSION=3.13 \ -t my-docs:v1.0.0 \ . ``` ### Multi-Platform ```bash docker buildx build \ --platform linux/amd64,linux/arm64 \ -t my-docs:latest \ . ``` --- ## Running ### Development ```bash docker run -it \ -p 8080:8080 \ -v $(pwd)/docs:/app/docs \ -e DEBUG=true \ markdown-docs-server ``` ### Production ```bash docker run -d \ --name docs-server \ -p 8080:8080 \ -v /var/www/docs:/app/docs:ro \ -e BASE_URL=https://docs.mysite.com \ -e DEBUG=false \ --restart unless-stopped \ --memory=512m \ --cpus=1 \ markdown-docs-server ``` ### With Environment File ```bash # Create .env file cat > .env < http://static.109.5.225.46.clients.your-server.de/api/endpoints.md # HTTP Endpoints Complete API reference for all HTTP endpoints provided by the documentation server. ## Health Check ### `GET /health` Returns server health status. **Response:** ```json { "status": "healthy", "docs_root": "/app/docs", "cache_root": "/app/cache", "debug": false } ``` **Status Codes:** - `200 OK` - Server is healthy **Example:** ```bash curl http://localhost:8080/health ``` --- ## MCP Endpoint ### `POST /mcp` Model Context Protocol endpoint for interactive documentation queries via JSON-RPC 2.0. **Features:** - Full-text search with Whoosh - Fuzzy search (typo tolerance) - Page retrieval with section filtering - Rate limited (120 req/min per IP) **Available Methods:** - `initialize` — Handshake and capability negotiation - `tools/list` — List available tools - `tools/call` — Execute a tool (search_docs, get_doc_page, list_doc_pages) **Example - Initialize:** ```bash curl -X POST http://localhost:8080/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {} } }' ``` **Example - Search:** ```bash curl -X POST http://localhost:8080/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "2", "method": "tools/call", "params": { "name": "search_docs", "arguments": {"query": "configuration", "limit": 5} } }' ``` **Status Codes:** - `200 OK` — Response returned (check JSON-RPC result/error) - `404 Not Found` — MCP disabled - `429 Too Many Requests` — Rate limit exceeded **Error Codes (JSON-RPC):** - `-32700` — Parse error (invalid JSON) - `-32600` — Invalid request (missing fields) - `-32601` — Method not found - `-32602` — Invalid params - `-32603` — Internal error (rate limit, index not ready) See [MCP Integration Guide](../features/mcp.md) for complete documentation. --- ## LLMs.txt Endpoints ### `GET /llms.txt` Returns AI assistant index with absolute URLs. **Features:** - PRIMARY: Serves curated `llms.txt` if exists - FALLBACK: Auto-generates from `sidebar.md` + `index.md` - Transforms relative links to absolute - Cached for performance **Response:** Plain text (Markdown format) **Status Codes:** - `200 OK` - Content returned - `500 Internal Server Error` - Generation failed **Example:** ```bash curl http://localhost:8080/llms.txt ``` ### `GET /llms-full.txt` Returns complete documentation in one file. **Features:** - Includes llms.txt index - Appends full content of all linked pages - XML-style `` and `` tags - Cached for performance **Response Format:** ``` # Index content https://example.com/page1.md Full content of page1.md https://example.com/page2.md Full content of page2.md ``` **Status Codes:** - `200 OK` - Content returned - `500 Internal Server Error` - Generation failed **Example:** ```bash curl http://localhost:8080/llms-full.txt > all-docs.txt ``` --- ## Search Endpoint ### `GET /search` Search documentation. Displays results in the main content area with sidebar and topbar. Requires MCP to be enabled (`MCP_ENABLED=true`). **Parameters:** - `q` — Search query (optional). Empty or whitespace-only shows the search page with no results. - `format` — Response format: omit for HTML page, `json` for JSON (used by client-side live search). **Response formats:** | Format | Use Case | |--------|----------| | HTML (default) | Full page with search bar and results | | JSON (`format=json`) | HTML fragment + metadata for AJAX/live search | **JSON response fields:** - `query` — The search query - `count` — Number of results - `results` — Array of `{title, path, url, snippet, score, category}` - `html` — Pre-rendered HTML fragment of results **Status Codes:** - `200 OK` — Search page or results returned **Example:** ```bash # HTML search page curl "http://localhost:8080/search?q=configuration" # JSON (for client-side fetch) curl "http://localhost:8080/search?q=configuration&format=json" ``` **When index unavailable:** Shows "Search will be available once the index is built." **When no results:** Shows "No results found for 'query'." --- ## Content Endpoints ### `GET /` (Root) Redirects to homepage. **Response:** `302 Found` redirect to `/index.html` **Example:** ```bash curl -L http://localhost:8080/ ``` ### `GET /{path}.html` Serves rendered HTML for markdown file. **Features:** - Renders `.md` file to styled HTML - Includes navigation (sidebar, topbar) - Adds table of contents - Syntax highlighting - Responsive design - Cached after first render **Parameters:** - `path` - Path to markdown file (without `.md` extension) **Response:** HTML document **Status Codes:** - `200 OK` - Content rendered - `404 Not Found` - File doesn't exist - `500 Internal Server Error` - Rendering failed **Examples:** ```bash # Homepage curl http://localhost:8080/index.html # Nested page curl http://localhost:8080/user-guide/installation.html # API docs curl http://localhost:8080/api/endpoints.html ``` ### `GET /{path}.md` Serves raw markdown content. **Features:** - Returns original markdown source - No rendering or processing - UTF-8 encoded - No caching (always fresh) **Parameters:** - `path` - Path to markdown file **Response:** Plain text (Markdown) **Status Codes:** - `200 OK` - Content returned - `404 Not Found` - File doesn't exist - `500 Internal Server Error` - Read failed **Examples:** ```bash # Get raw markdown curl http://localhost:8080/index.md # Download a page curl http://localhost:8080/api/endpoints.md -o endpoints.md ``` ### `GET /{path}` Serves static assets. **Supported types:** - Images: PNG, JPG, GIF, SVG - Documents: PDF - Media: MP4, MP3, WAV **Parameters:** - `path` - Path to asset file **Response:** Binary file with appropriate MIME type **Status Codes:** - `200 OK` - File served - `404 Not Found` - File doesn't exist **Examples:** ```bash # Get image curl http://localhost:8080/assets/logo.svg # Get PDF curl http://localhost:8080/assets/manual.pdf -o manual.pdf ``` --- ## Response Headers All responses include standard headers: ``` Content-Type: text/html; charset=utf-8 (HTML pages) Content-Type: text/plain; charset=utf-8 (Markdown, llms.txt) Content-Type: application/json (Health check) Content-Type: image/png (Images) Content-Type: application/pdf (PDFs) ... ``` --- ## Error Responses ### 404 Not Found File or page doesn't exist. **Response:** ```json { "detail": "File not found" } ``` ### 500 Internal Server Error Server error during processing. **Response:** ```json { "detail": "Error reading file: [error message]" } ``` --- ## Caching Behavior ### Cached Endpoints These endpoints use intelligent caching: | Endpoint | Cache Duration | Cache Key | |----------|----------------|-----------| | `GET /{path}.html` | Until server restart | File path | | `GET /llms.txt` | Until server restart | `llms.txt` | | `GET /llms-full.txt` | Until server restart | `llms-full.txt` | ### Non-Cached Endpoints These endpoints are always fresh: - `GET /health` - Real-time status - `GET /{path}.md` - Original source - `GET /{path}` (assets) - Static files ### Cache Invalidation Cache is cleared on: - Server restart - Manual cache directory deletion - File modification (in development with DEBUG=true) --- ## Rate Limiting No rate limiting by default. For production, use a reverse proxy (nginx, caddy) with rate limiting: ```nginx limit_req_zone $binary_remote_addr zone=docs:10m rate=10r/s; server { location / { limit_req zone=docs burst=20; proxy_pass http://localhost:8080; } } ``` --- ## CORS CORS is not configured by default. To enable CORS for API consumption: ```python # Add to main.py from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["GET"], allow_headers=["*"], ) ``` --- ## Authentication No authentication by default. For private documentation, use: 1. **Reverse Proxy Auth** (nginx, caddy) 2. **VPN/Firewall** (network-level) 3. **Custom Middleware** (FastAPI) Example nginx basic auth: ```nginx server { location / { auth_basic "Documentation"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://localhost:8080; } } ``` --- ## URL Structure The server follows these URL patterns: ``` / → Redirects to /index.html /index.html → Rendered homepage /index.md → Raw markdown /page.html → Rendered page /page.md → Raw markdown /folder/page.html → Nested rendered page /folder/page.md → Nested raw markdown /assets/image.png → Static asset /llms.txt → AI index /llms-full.txt → Full content /health → Health check /search?q=... → Search documentation (MCP required) ``` --- ## Content Negotiation The server doesn't use `Accept` headers. Instead, the URL extension determines the response: - `.html` → Rendered HTML - `.md` → Raw markdown - Other → File type based on extension --- ## Examples ### Get Homepage HTML ```bash curl http://localhost:8080/index.html ``` ### Get Raw Markdown ```bash curl http://localhost:8080/api/endpoints.md ``` ### Download All Docs for AI ```bash curl http://localhost:8080/llms-full.txt -o all-docs.txt ``` ### Check Server Health ```bash curl http://localhost:8080/health | jq . ``` ### Get Specific Asset ```bash curl http://localhost:8080/assets/logo.svg -o logo.svg ``` --- ## Integration Examples ### Python ```python import requests # Get rendered page response = requests.get("http://localhost:8080/index.html") html = response.text # Get raw markdown response = requests.get("http://localhost:8080/index.md") markdown = response.text # Get AI index response = requests.get("http://localhost:8080/llms.txt") llms_txt = response.text ``` ### JavaScript/Node ```javascript // Fetch rendered page const response = await fetch('http://localhost:8080/index.html'); const html = await response.text(); // Fetch markdown const mdResponse = await fetch('http://localhost:8080/index.md'); const markdown = await mdResponse.text(); ``` ### cURL ```bash # Get page and save curl http://localhost:8080/page.html -o page.html # Get all docs curl http://localhost:8080/llms-full.txt -o docs.txt # Check if page exists curl -I http://localhost:8080/page.html ``` --- ## Performance ### Response Times | Endpoint Type | First Request | Cached | |---------------|---------------|--------| | Rendered HTML | 50-100ms | <5ms | | Raw Markdown | <10ms | <10ms | | LLMs.txt | 100-200ms | <5ms | | Assets | <5ms | <5ms | ### Optimization Tips 1. Use caching (enabled by default) 2. Serve static assets via CDN 3. Use reverse proxy caching 4. Enable gzip compression 5. Minimize markdown files --- ## Security ### Built-in Protection ✅ Path traversal prevention ✅ File type validation ✅ UTF-8 encoding enforcement ✅ Safe path resolution ### Additional Security Consider adding: - HTTPS (via reverse proxy) - Rate limiting - Authentication - CSP headers - CORS configuration --- ## Next Steps - **[Configuration](../configuration.md)** - Environment variables - **[Deployment](../deployment/docker.md)** - Production deployment - **[Examples](../examples/advanced.md)** - Integration examples http://static.109.5.225.46.clients.your-server.de/configuration.md#troubleshooting # Configuration Configure the documentation server with environment variables and file structure. ## Environment Variables ### Core Settings | Variable | Default | Description | |----------|---------|-------------| | `DOCS_ROOT` | `./test_docs` or `/app/docs` | Root directory for markdown files | | `CACHE_ROOT` | `./__cache__` or `/app/cache` | Cache directory for rendered HTML | | `PORT` | `8080` | HTTP server port | | `DEBUG` | `false` | Enable debug mode with auto-reload | | `BASE_URL` | Auto-detected | Base URL for absolute links in llms.txt and Copy page AI links (ChatGPT, Claude) | | `SERVEMD_BRANDING_ENABLED` | `true` | Show "Powered by servemd" footer. Set to `false` to disable for white-label or self-hosted deployments | | `CUSTOM_CSS` | `custom.css` | Filename of custom CSS in DOCS_ROOT. Loaded on every page after default styles. See [Customization](features/customization.html) | ### MCP Settings | Variable | Default | Description | |----------|---------|-------------| | `MCP_ENABLED` | `true` | Enable/disable MCP endpoint | | `MCP_RATE_LIMIT_REQUESTS` | `120` | Max requests per window per IP | | `MCP_RATE_LIMIT_WINDOW` | `60` | Rate limit window in seconds | | `MCP_MAX_SEARCH_RESULTS` | `10` | Default max search results | | `MCP_SNIPPET_LENGTH` | `200` | Max characters for search snippets | ### Example Configurations **Development:** ```bash DOCS_ROOT=./docs \ DEBUG=true \ PORT=3000 \ uv run python -m docs_server ``` **Production:** ```bash DOCS_ROOT=/var/www/docs \ CACHE_ROOT=/var/cache/docs \ BASE_URL=https://docs.example.com \ PORT=8080 \ uv run python -m docs_server ``` **Clear cache on startup:** ```bash uv run python -m docs_server --clear-cache ``` **Docker:** ```bash docker run \ -e DOCS_ROOT=/app/docs \ -e BASE_URL=https://docs.mysite.com \ -e DEBUG=false \ -p 8080:8080 \ -v $(pwd)/docs:/app/docs \ markdown-docs-server ``` **White-label (disable branding):** ```bash SERVEMD_BRANDING_ENABLED=false uv run python -m docs_server ``` The "Powered by servemd" footer is shown by default. Disable it with `SERVEMD_BRANDING_ENABLED=false` for white-label or self-hosted deployments where you prefer no attribution. ### Custom CSS Place a CSS file (e.g. `custom.css`) in `DOCS_ROOT`. It is served at `/custom.css` and loaded on every page **after** the default styles, so your rules override defaults. Use `CUSTOM_CSS=theme.css` to serve a different filename. See [Customization](features/customization.html) for CSS variables and examples. --- ## Required File Structure Your `DOCS_ROOT` must contain three required files: ``` docs/ ├── index.md # Homepage (REQUIRED) ├── sidebar.md # Sidebar navigation (REQUIRED) └── topbar.md # Top bar navigation (REQUIRED) ``` ### index.md Your documentation homepage: ```markdown # Welcome to My Project Quick introduction and getting started guide. ## Features - Feature 1 - Feature 2 ## Quick Start [Get started here](quick-start.md) ``` ### sidebar.md Hierarchical navigation structure: ```markdown # Navigation * [Home](index.md) * [Getting Started](getting-started.md) * [User Guide](user-guide.md) * [Installation](user-guide/install.md) * [Configuration](user-guide/config.md) * [API Reference](api.md) * [REST API](api/rest.md) * [GraphQL](api/graphql.md) ``` **Rules:** - Top-level items: `* [Title](link.md)` - Child items: ` * [Title](link.md)` (2 spaces indent) - Sections automatically detected - `.md` extensions converted to `.html` in rendered output ### topbar.md Top bar with left/middle/right sections: ```markdown # Top Bar Navigation ## left * [📚 Docs](index.md) * [🚀 Quick Start](quick-start.md) ## middle * [v2.0.0](https://github.com/project/releases) ## right * [GitHub](https://github.com/project) * [Discord](https://discord.gg/project) ``` **Sections:** - `## left` - Left side (logo, main links) - `## middle` - Center (optional, breadcrumbs) - `## right` - Right side (external links, social) **Placeholders** (double braces so `{logo}` displays literally elsewhere): | Tag | Syntax | Purpose | |-----|--------|---------| | `{{logo}}` | `* {{logo}} \| [Home](index.md)` | Logo + link in left section | | `{{search}}` | `* {{search}}` or `* {{search:icon=...,mode=...,placeholder=...}}` | Search bar (MCP search when enabled) | See [Navigation Features](features/navigation.md) for all `{{search}}` options: `icon` (lucide-search, lucide-x, custom SVG), `mode` (full, button, input), `placeholder`. --- ## Optional Files ### llms.txt AI assistant index (see [LLMs.txt Guide](features/llms-txt.md)): ```markdown # Project Documentation [Homepage](index.md) [Quick Start](quick-start.md) [API Reference](api.md) ``` If not provided, auto-generated from `sidebar.md` + `index.md`. ### assets/ Place static assets in an `assets/` folder: ``` docs/ └── assets/ ├── logo.svg ├── screenshot.png └── diagram.pdf ``` Reference in markdown: ```markdown ![Logo](assets/logo.svg) [Download PDF](assets/diagram.pdf) ``` --- ## Directory Structure Organize content in subdirectories: ``` docs/ ├── index.md ├── sidebar.md ├── topbar.md ├── getting-started.md ├── user-guide/ │ ├── installation.md │ ├── configuration.md │ └── troubleshooting.md ├── api/ │ ├── rest.md │ ├── graphql.md │ └── webhooks.md ├── deployment/ │ ├── docker.md │ ├── kubernetes.md │ └── cloud.md └── assets/ ├── logo.svg └── images/ └── screenshot.png ``` **Best practices:** - Group related content in folders - Use clear, URL-friendly names - Keep hierarchy shallow (2-3 levels max) - Use descriptive filenames --- ## Markdown Configuration The server uses these Markdown extensions: ### Enabled Extensions | Extension | Purpose | |-----------|---------| | `codehilite` | Syntax highlighting for code blocks | | `toc` | Automatic table of contents | | `tables` | GitHub-style tables | | `fenced_code` | ``` code blocks | | `footnotes` | Footnote support[^1] | | `attr_list` | HTML attributes in markdown | | `def_list` | Definition lists | | `abbr` | Abbreviations | | `pymdownx.superfences` | Advanced code blocks | | `pymdownx.tasklist` | - [ ] Task lists | | `pymdownx.highlight` | Enhanced highlighting | | `pymdownx.inlinehilite` | Inline code highlight | [^1]: Like this footnote! ### Extension Configuration Customize in `config.py`: ```python markdown_extension_configs = { "codehilite": { "css_class": "highlight", "use_pygments": True, }, "toc": { "permalink": True, "toc_depth": 3, "permalink_title": "🔗", }, "pymdownx.tasklist": { "custom_checkbox": True, }, } ``` --- ## Caching Strategy ### How It Works 1. **First request**: Markdown rendered to HTML, cached 2. **Subsequent requests**: Served from cache (instant) 3. **Server restart**: Cache cleared automatically ### Cache Location ```bash # Default cache directory CACHE_ROOT=./__cache__ # Custom cache directory CACHE_ROOT=/tmp/docs-cache ``` ### Cache Files ``` __cache__/ ├── index.html # Cached homepage ├── quick-start.html # Cached page ├── user-guide/ │ └── installation.html ├── llms.txt # Cached llms.txt └── llms-full.txt # Cached full content ``` ### Manual Cache Clear ```bash # Remove cache directory rm -rf __cache__ # Server will recreate on next request ``` --- ## Security Settings ### Path Traversal Protection Built-in security prevents directory traversal: ```python # These are blocked: /../../../../etc/passwd ❌ /../secret.md ❌ /../../config.yml ❌ # These work: /user-guide/install.md ✅ /api/endpoints.md ✅ ``` ### Safe Path Validation All file paths are validated before serving: ```python def is_safe_path(path: str, base_path: Path) -> bool: """Validate path is within allowed directory.""" abs_base = base_path.resolve() abs_path = (base_path / path).resolve() return os.path.commonpath([abs_base, abs_path]) == str(abs_base) ``` --- ## URL Routing ### HTML Mode Serves rendered HTML: ``` http://localhost:8080/index.html → Rendered http://localhost:8080/api/endpoints.html → Rendered ``` ### Raw Markdown Mode Serves original markdown: ``` http://localhost:8080/index.md → Raw markdown http://localhost:8080/api/endpoints.md → Raw markdown ``` ### Static Assets Direct file serving: ``` http://localhost:8080/assets/logo.svg → Static file http://localhost:8080/assets/doc.pdf → Static file ``` ### Special Endpoints ``` http://localhost:8080/ → Redirects to /index.html http://localhost:8080/health → Health check JSON http://localhost:8080/llms.txt → AI assistant index http://localhost:8080/llms-full.txt → Full documentation ``` --- ## MCP Cache Considerations ### Kubernetes / k3s Deployments When deploying to Kubernetes or k3s with MCP enabled: **Cache Persistence:** - MCP search index is stored in `CACHE_ROOT/mcp/` - Each pod builds its own index on first startup (~200ms for typical docs) - Cache persists across container restarts if volume is mounted - Recommended: Use emptyDir volume for cache (ephemeral, fast) ```yaml # Example volume mount for cache volumes: - name: cache emptyDir: {} volumeMounts: - name: cache mountPath: /app/cache ``` **Horizontal Scaling:** - Each pod maintains its own independent search index - Index rebuilds automatically when docs change (hash-based validation) - No shared state required between pods - Rate limiting is per-pod (each pod has 120 req/min limit) **Startup Performance:** - First startup: ~200ms to build index (100 docs) - Subsequent startups: ~10ms to load from cache - Health check passes immediately (MCP initialization is async) **Environment Variables:** ```yaml env: - name: MCP_ENABLED value: "true" - name: MCP_RATE_LIMIT_REQUESTS value: "120" - name: CACHE_ROOT value: "/app/cache" ``` ## Production Checklist Before deploying to production: - [ ] Set `DEBUG=false` - [ ] Configure `BASE_URL` for llms.txt - [ ] Use proper `DOCS_ROOT` path - [ ] Set up cache directory with write permissions - [ ] Configure reverse proxy (nginx/caddy) - [ ] Enable HTTPS - [ ] Set proper PORT if needed - [ ] Add health check monitoring - [ ] Configure log aggregation - [ ] Set up backup for docs - [ ] For k8s/k3s: Configure emptyDir volume for cache - [ ] For k8s/k3s: Consider per-pod rate limit scaling --- ## Troubleshooting ### Server won't start Check port availability: ```bash lsof -i :8080 # See what's using port 8080 ``` ### Files not found Verify `DOCS_ROOT`: ```bash echo $DOCS_ROOT ls $DOCS_ROOT # Should show index.md, sidebar.md, topbar.md ``` ### Styling broken Check for required files: ```bash ls $DOCS_ROOT/sidebar.md ls $DOCS_ROOT/topbar.md ``` ### Cache issues Clear and restart: ```bash rm -rf __cache__ uv run python -m docs_server ``` --- ## Advanced Configuration ### Custom Port ```bash PORT=3000 uv run python -m docs_server ``` ### Multiple Environments ```bash # Development cp .env.development .env uv run python -m docs_server # Production cp .env.production .env uv run python -m docs_server ``` ### Environment File Create `.env`: ```bash DOCS_ROOT=./docs CACHE_ROOT=./__cache__ PORT=8080 DEBUG=false BASE_URL=https://docs.mysite.com ``` Load with: ```bash source .env && uv run python -m docs_server ``` --- ## Next Steps - **[Deployment Guide](deployment/docker.md)** - Deploy to production - **[API Reference](api/endpoints.md)** - HTTP endpoints - **[Examples](examples/basic.md)** - Configuration examples