Open-source Markdown documentation framework with built-in AI chat.
Write your docs in Markdown. Add your API key. Every page gets an AI assistant that answers questions from your documentation.
- Markdown-based — write docs in Markdoc/MDX, organized by folders
- AI chat on every page — readers ask questions, get answers grounded in your docs
- Built-in search — Cmd+K command palette with fuzzy search, zero API calls
- Bring your own LLM — OpenAI, Anthropic, Ollama, or any OpenAI-compatible endpoint
- Self-hosted — your data, your infra, no vendor lock-in
- Your API key, your control — key never leaves the server
- Graph-backed retrieval — cross-references between pages enrich AI context
- Prompt protection — built-in jailbreak prevention keeps AI grounded in your docs
- Beautiful default theme — dark/light mode, responsive, sidebar navigation
# Clone and install
git clone https://github.com/jm27/smartdocs.git my-docs
cd my-docs
npm install
# Build the page index (required for AI + search)
npm run build:graph
# Configure AI (copy the example and add your key)
cp .env.example .env
# Edit .env and add your API key
# Start dev server
npm run devOpen http://localhost:3000 — your docs are live.
- Home: http://localhost:3000
- Quickstart: http://localhost:3000/docs/getting-started/quickstart
- Configuration: http://localhost:3000/docs/guides/configuration
- API Reference: http://localhost:3000/docs/api/reference
Press Cmd+K (Mac) or Ctrl+K (Windows) on any page. Type to get instant fuzzy results.
Click the chat bubble (bottom-right) on any page. Ask a question to see a streaming response grounded in your docs content.
To test chat, set your API key first:
echo "SMARTDOCS_API_KEY=sk-..." > .env
npm run build:graphGenerates .smartdocs/page-index.json and .smartdocs/graph.json from content/.
npx tsc --noEmitnpm run build| Environment Variable | Required | Description |
|---|---|---|
SMARTDOCS_AI_PROVIDER |
No | openai, anthropic, or openai-compatible (default: openai) |
SMARTDOCS_API_KEY |
Yes (for chat) | Your LLM provider API key |
SMARTDOCS_MODEL |
No | Model name (default: gpt-4o-mini) |
SMARTDOCS_OPENAI_API_MODE |
No | OpenAI request mode: auto (default), chat, or responses |
SMARTDOCS_BASE_URL |
No | Custom endpoint (for Ollama, etc.) |
SmartDocs supports both OpenAI Chat Completions and Responses APIs when SMARTDOCS_AI_PROVIDER=openai.
SMARTDOCS_OPENAI_API_MODE=auto(recommended):- prefers the most compatible OpenAI route for the selected model
- supports fallback between
/v1/chat/completionsand/v1/responsesfor model routing failures
SMARTDOCS_OPENAI_API_MODE=chat: force Chat CompletionsSMARTDOCS_OPENAI_API_MODE=responses: force Responses first, then fallback to Chat Completions on model routing errors
Use plain OpenAI model IDs on the native OpenAI endpoint (for example gpt-4o-mini or gpt-5-nano).
Provider-prefixed IDs like openai/gpt-5-nano are typically for gateway providers and may fail on api.openai.com.
SmartDocs draws inspiration from Andrej Karpathy's LLM Wiki pattern — the idea that knowledge should be compiled once and kept current, not re-derived on every query. Instead of traditional RAG (chunking documents into a vector database), SmartDocs builds a lightweight graph of your documentation at build time.
- Build time —
scripts/build-graph.jsparses your Markdown files, extracts cross-references between pages (links, related topics), and builds a lightweight graph index. No embeddings, no vector DB, no external services — just page structure. - Query time — When a reader asks a question, SmartDocs finds the most relevant page(s) using keyword matching, then follows cross-reference links in the graph to pull in related context pages.
- LLM call — The full contents of the relevant pages (3-5 pages) are sent to your configured LLM as context. Modern context windows (128K-200K tokens) handle this easily.
- Streaming response — The answer streams back through the chat widget in real time.
All LLM calls happen server-side. Your API key never reaches the browser.
Inspired by: Andrej Karpathy's LLM Wiki — a pattern for building persistent, interlinked knowledge bases using LLMs.
smartdocs/
├── content/ ← Your Markdown docs (example pages provided)
│ ├── index.md
│ ├── getting-started/
│ ├── guides/
│ └── api/
├── app/ ← Next.js App Router
│ ├── layout.tsx ← Root layout (sidebar + search + chat widget)
│ ├── page.tsx ← Home page
│ ├── docs/[...slug]/ ← Dynamic doc pages
│ ├── api/chat/ ← AI chat endpoint (POST /api/chat)
│ └── globals.css ← Tailwind + theme
├── components/
│ ├── Sidebar.tsx ← Navigation sidebar
│ ├── SearchBar.tsx ← Cmd+K search (Fuse.js)
│ └── ChatWidget.tsx ← Floating AI chat bubble
├── lib/
│ └── markdoc.ts ← Markdoc → React rendering
├── scripts/
│ └── build-graph.js ← Build-time graph + index generator
├── .smartdocs/ ← Build output (gitignored)
│ ├── page-index.json
│ └── graph.json
└── public/
└── .smartdocs/ ← Client-accessible page index (for search)
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Content | Markdoc 0.5.8 (Markdown → React) |
| Styling | Tailwind CSS 4 |
| Search | Fuse.js (offline fuzzy search) |
| AI Chat | Server-side API route with multi-provider support |
| Graph | Custom JSON index at build time |
MIT
