Introduction
OwnDocs turns Markdown files into a documentation site with search, sidebar navigation, and password protection. It runs on Next.js 16, React 19, TypeScript 6, and Tailwind CSS 4.
Use it for an external API reference, an internal knowledge base, or customer-facing product guides. The page structure, components, and hosting setup come ready-made, so you're not building a docs site from scratch.
Why OwnDocs
Most documentation tools make you choose between control and setup time. Static site generators give you control but ask for hours of plugin configuration. Hosted platforms run the infrastructure for you but charge per seat and limit what you can change. OwnDocs ships as source code you own. It works without extra setup, and you can change any part of it.
Pages from files, no configuration. Create an .mdx file and write. OwnDocs
builds the sidebar, search index, breadcrumbs, table of contents, sitemap,
OpenGraph metadata, and static pages for you. There's no routing config or build
plugin to set up.
29 ready-made documentation components. They cover the patterns that keep coming up in technical writing: API endpoint docs, structured parameter fields, tabbed code groups, feature comparisons, step-by-step guides, release notes, and diagrams.
Two access modes, one codebase. One ACCESS_MODE environment variable
switches between private (password-protected) and public (open) access. One
deployment can serve internal team docs, client portals, and public product
docs.
You own the source. OwnDocs is a one-time purchase with an MIT license. No per-seat fees, no monthly subscriptions, no vendor lock-in. Deploy on Vercel, AWS, DigitalOcean, or your own server.
Technology Stack
OwnDocs is built on these libraries:
- Next.js v16 — App Router with Turbopack for sub-second hot reload, server and static rendering, and proxy middleware for authentication
- React v19 — Server Components and concurrent rendering for fast first paint and responsive pages
- MDX v3 — Markdown with embedded React components via
next-mdx-remote - Tailwind CSS v4 — Utility-first styling with OKLCH color space for consistent color themes across all 26 palettes
- Prism.js v1.30 — Client-side syntax highlighting for 65+ programming languages with hydration-safe rendering
- Mermaid v11 — Diagram rendering for 15+ diagram types with DOMPurify SVG sanitization for security
- Jose v6 — JWT-based authentication with HS256 signing for sessions
- DOMPurify v3 — SVG sanitization for all diagram output, which blocks XSS attacks
- Lucide React v1.0 — Icon library used across 29 components
- TypeScript v6 — Type safety across every source file in the project
Core Capabilities
Content Authoring
OwnDocs supports the content formats you'll need in a docs site:
- File-based routing — Every
.mdxfile inapp/becomes a page. The file path is the URL. No routing configuration needed. - MDX support — Write Markdown with embedded React components. 29 custom components are available on every page without imports.
- GitHub Flavored Markdown — Tables, strikethrough, task lists, and
autolinks via
remark-gfm - GitHub-style alerts — Six alert types (note, tip, important, warning, caution, danger) for flagging important information
- Frontmatter support — YAML metadata parsed via
gray-matterfor page descriptions used in SEO and search results - Internal link normalization —
.mdxextensions are stripped from links, so[Features](./features.mdx)and[Features](./features)both work - Copy page as Markdown — A dropdown button next to every page title copies the whole page as Markdown or plain text, ready to paste into ChatGPT, Claude, or Cursor
Code and Diagrams
Technical docs lean on readable code examples and diagrams. OwnDocs covers both:
- Syntax highlighting — 65+ programming languages with Prism.js client-side highlighting and dependency ordering handled for you
- 45 language aliases — Common shortcuts like
js,ts,py,sh,kt,rs,rb,tf,sol, and more - Line numbers — Line numbering with a configurable start offset
- Line highlighting — Highlight specific lines with
{1,3-5}syntax to point out key code - Diff markers — Inline
// [!code ++]and// [!code --]annotations for showing code changes without switching to diff format - Word highlighting — Highlight specific patterns with
/pattern/syntax to call out variables or functions - File titles — Show file path headers with
title="filename"metastring so readers know where code belongs - Collapsible code — Long blocks collapse with
expandableandmaxLines=Nto keep pages scannable while keeping full examples - Code groups — Tabbed code blocks for showing the same concept in multiple languages or package managers (npm/yarn/pnpm)
- Copy to clipboard — One-click code copying with visual feedback on every code block
- Mermaid diagrams — 15+ diagram types including flowchart, sequence, class, state, gantt, pie, ER, gitGraph, journey, mindmap, timeline, quadrant, sankey, and more
- Diagram detection — Mermaid diagrams render without the
mermaidlanguage tag when the content starts with a recognized diagram keyword
Navigation and Search
Readers find what they need from the sidebar, search, and breadcrumbs. OwnDocs builds each one from your file structure:
- Auto-generated sidebar — Built from the file system, with 3-level depth and active page highlighting
- Acronym-aware name formatting — 140+ technical acronyms keep their capitalization (API, REST, GraphQL, MongoDB, JWT, SSO, RBAC, and more)
- Full-text search — Client-side search across all pages with scored ranking and context snippets showing where the match was found
- Keyboard shortcut —
Cmd+KorCtrl+Kopens the search modal from any page, following the ARIA combobox pattern for screen readers - Heading anchors — Auto-generated slug IDs with clickable links via
rehype-slugandrehype-autolink-headingsfor deep-linking - Table of contents — Scroll-spy TOC on desktop that highlights the current section, with a collapsible panel on mobile
- Breadcrumb navigation — Auto-formatted path breadcrumbs on every page for orientation within the site hierarchy
- Previous/next navigation — Sequential page links at the bottom of every article for linear reading
- Auto-generated index —
<DynamicIndexContent />builds a site map with page counts for landing pages - Category index — Directories without an
index.mdxgenerate a landing page that lists all child pages
Documentation Components
OwnDocs ships 29 custom components. Each one is responsive, keyboard-accessible, and styled to match your theme:
- ApiBlock — REST API endpoint documentation with 5 HTTP method badges, color-coded headers, request/response bodies, multi-response tabs, auth indicators, deprecation notices, rate limiting, base URLs, and generated cURL examples
- ParamField — Structured parameter documentation with type, location (path, query, body, header), required/optional markers, default values, and deprecation labels
- ResponseField — Structured response field documentation for API endpoints
- CodeGroup — Tabbed code blocks with keyboard navigation for multi-language examples
- Tabs / TabItem — General-purpose tabbed content panels with ARIA tablist pattern and localStorage sync
- Steps — Numbered step-by-step guides with visual connectors for tutorials
- Card / CardGrid — Feature showcase cards with configurable grid columns and optional icons
- Accordion — Collapsible sections with smooth animation and URL hash deep-linking
- Badge — Inline status indicators in five variants (default, info, success, warning, danger)
- ComparisonTable — Side-by-side feature comparison with 10 visual indicator types and column highlighting
- FileTree — Visual directory structure from indented text
- ChangelogEntry / ChangelogLabel — Technical changelog timeline with 7 label types for developer audiences
- ReleaseNote / ReleaseHighlight — User-facing release announcements with 8 highlight types for public "What's New" pages
- ImageZoom — Click-to-zoom lightbox with keyboard and ARIA support
- Embed — Responsive iframe embeds with URL allowlist (YouTube, GitHub) and sandbox security
Theming
OwnDocs ships 26 color themes. Each theme is a coordinated palette that generates light mode, dark mode, and component-level CSS custom properties:
- 26 built-in palettes — emerald (default), amber, blue, cyan, fuchsia, gray, green, indigo, lime, mauve, mist, neutral, olive, orange, pink, purple, red, rose, sky, slate, stone, taupe, teal, violet, yellow, zinc
- Dark mode toggle — Light, dark, and system modes with
prefers-color-schemedetection and localStorage persistence - CSS custom properties — All colors defined as semantic variables
(
--color-accent,--color-bg-primary, and more) that switch between light and dark - Semantic aliases — Tailwind theme aliases (
surface-*,content-*,edge-*,brand-*) switch with dark mode withoutdark:variant classes - Custom typography — Maven Pro for body text, JetBrains Mono for code with ligatures and slashed zeros
Security
OwnDocs protects private docs in these ways:
- Password protection — JWT sessions with 14-day expiry via
joselibrary - Browser fingerprinting — Sessions are invalidated if the User-Agent or Accept-Language header changes, which stops session hijacking
- Secure cookies —
__Host-prefix,httpOnly,secure,sameSite: lax - Cookie name obfuscation — Cookie name derived from SHA-256 of
COOKIE_SALT, making it unpredictable - Rate limiting — 5 login attempts per IP with 15-minute lockout and timing-safe password comparison to stop brute-force attempts
- Origin validation — CSRF protection on all state-changing auth endpoints
- 9 security headers — HSTS (2-year with preload), CSP, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection (disabled, superseded by CSP), Referrer-Policy, Permissions-Policy, X-Robots-Tag
- 4-layer crawler blocking —
robots.txt, HTML meta robots,X-Robots-Tagheader, and password-gated access (private mode) - Path traversal checks — Slug validation rejects
..and leading/ - DOMPurify — SVG sanitization on all Mermaid diagram output to block XSS
SEO and AI Readiness
In public mode, OwnDocs prepares every page for search engines and AI agents:
- Dynamic sitemap —
sitemap.xmlgenerated from the navigation tree - OpenGraph and Twitter Cards — Per-page
og:title,og:description, andtwitter:cardmeta tags with descriptions pulled from MDX content - Canonical URLs —
<link rel="canonical">on every page to avoid duplicate content - JSON-LD structured data —
TechArticleandBreadcrumbListschema.org markup on every documentation page for rich search results - Dynamic robots.txt — 28+ named bots blocked in private mode, full crawling permitted in public mode
- llms.txt — AI agent index at
/llms.txtlisting all pages with URLs - llms-full.txt — Full documentation content at
/llms-full.txtfor bulk AI context loading - Copy page as Markdown — Dropdown button next to every H1 title with Markdown and plain text copy options for AI tools
Accessibility
OwnDocs follows WCAG guidelines for keyboard and screen reader support:
- Skip to content — Keyboard-accessible skip link visible on focus
- Focus management — H1 focused on route change so screen readers announce it
- Focus-visible indicators — Visible keyboard focus rings on all interactive elements (WCAG 2.4.7)
- ARIA patterns — Combobox on search, tablist on tabs/code groups, dialog on modals, region on code blocks
- Keyboard navigation — Arrow keys, Home/End, Enter/Space across search, tabs, code groups, and accordions
- Focus trapping — Search modal and image zoom trap focus within the dialog
- Body scroll lock — Background scroll disabled when modals are open
- Reduced motion — Respects
prefers-reduced-motionsystem preference - Print stylesheet — Code rendering adjusted for print, interactive elements hidden
- Content-visibility —
content-visibility: autoon prose content to cut rendering work
Public/Private Access Mode
OwnDocs has two access modes set by one environment variable, so the same codebase can serve internal and public docs:
- Private mode (default) — Password-protected access, all search engine and AI crawlers blocked, login required for every page
- Public mode — Open access for all visitors, search engines allowed to index content, login page redirects to home, logout button hidden
Set via the ACCESS_MODE environment variable. The default is private.
Project Structure
Architecture
The diagrams below show how content moves through the build pipeline, how the layout organizes navigation components, and how the security and SEO layers fit in:
Environment Variables
All environment variables are generated by the setup script. You only need to change them if you want to customize the defaults:
ACCESS_MODE—private(default) orpublicAPP_PASSWORD— Access password (private mode only)JWT_SECRET— JWT signing key (private mode only)COOKIE_SALT— Cookie name salt (private mode only)THEME_VARIANT— Color palette (26 options, defaults toemerald)NEXT_PUBLIC_SITE_URL— Site URL for sitemap and OG tags (optional, detected on Vercel)
Run bash scripts/setup-env.sh to generate all secrets, or copy .env.example
as a starting point.
Quick Setup
git clone https://github.com/devops-infinity/owndocs.git my-docs
cd my-docs
bash scripts/setup-env.sh
npm install
npm run devAdding Content
Create any .mdx file under app/ and it becomes a documentation page:
app/guides/deployment.mdx → /guides/deployment
app/api-docs/endpoints.mdx → /api-docs/endpointsDirectories become sidebar categories. Use numeric prefixes like 01-basics/ to
control page ordering. Every new file is added to the sidebar, search index,
sitemap, and navigation with no configuration.
Linting and Formatting
OwnDocs ships a linting and formatting pipeline to keep content and code consistent:
npm run format # Format all files
npm run format:check # Check without modifying
npm run lint # ESLint for TS/JS
npm run lint:mdx # ESLint for MDX
npm run mdx:check # Remark lint for MDX/MarkdownThe pipeline runs ESLint with TypeScript rules, eslint-plugin-mdx for MDX
files, and remark-lint with the recommended and consistent presets. It also
checks heading style, validates links, and runs remark-preset-prettier so
remark rules don't fight Prettier formatting.