Publishing Docs
DocPlatform can serve your documentation as a website — complete with a navigation sidebar, syntax highlighting, and SEO metadata. No separate static site generator required. By default, published docs are visible only to authenticated workspace members. Admins can opt in to make them fully public.
How publishing works
Published docs are served at /p/{site-slug}/{page-path}:
http://localhost:3000/p/my-docs/ → index.md
http://localhost:3000/p/my-docs/quickstart → quickstart.md
http://localhost:3000/p/my-docs/api/auth → api/auth.md
Pages are rendered from Markdown to HTML on request using goldmark (CommonMark-compliant) with Chroma syntax highlighting (Dracula theme) for code blocks.
Slug limitation: site slugs must be a single path segment. A slug containing
/breaks routing both on/p/URLs and on custom domains (custom-domain requests are internally rewritten to/p/{slug}/...). Use a slug likemy-docs, notteam/my-docs.
What appears on the published site
Whether a page appears on the published site is a three-source decision, evaluated in this order (later sources win):
- Frontmatter
publish:flag on the page - The
pages.publishcolumn in the database (kept in sync with frontmatter) - The
.docplatform/publish.yamloverlay — an entry for the page’s path overrides frontmatter
Unpublished pages return 404 on the published site — for everyone, including workspace members. The separate frontmatter status: field (draft / published / archived) is editorial metadata and does not control published-site visibility — only publish: does.
Enable publishing
Per-page
Set publish: true in the page’s frontmatter:
---
title: API Authentication
description: How to authenticate with the API.
publish: true
---
Or toggle the Publish switch in the frontmatter form of the web editor.
Bulk control with the publish overlay
To manage publish decisions as code (visible in code review), use the .docplatform/publish.yaml overlay — see Workspace Settings.
Themes
DocPlatform ships with 7 built-in themes for published documentation:
| Theme | Description |
|---|---|
| Default | Clean light theme with blue accents |
| Dark | Dark background with high-contrast text |
| Forest | Green-toned natural palette |
| Rose | Warm pink and red accents |
| Amber | Warm amber and gold tones |
| Minimal | Stripped-down, typography-focused |
| Corporate | Professional blue/gray palette |
Set the theme in Workspace Settings → Publishing (PUT /api/v1/workspaces/:id/admin/settings with {"theme": "dark"}), or in .docplatform/workspace.yaml:
# .docplatform/workspace.yaml
theme: dark
Invalid theme names fall back to default.
Published site features
Navigation
The published site generates a sidebar navigation from your page hierarchy by default.
To customize it, either arrange navigation groups in Workspace Settings → Publishing → Navigation (PUT /api/v1/workspaces/:id/admin/navigation), or maintain a .docplatform/nav.yaml file in the workspace:
# .docplatform/nav.yaml
version: 1
tree:
- file: index.md
- section: "Getting Started"
children:
- file: getting-started/installation.md
- file: getting-started/quickstart.md
See Workspace Settings for all node types. Use the frontmatter nav_order field for simple ordering hints without a full nav file.
Syntax highlighting
Code blocks are highlighted using Chroma (Dracula theme). Over 200 languages are supported.
Specify the language after the opening triple backticks:
```python
def hello(name: str) -> str:
return f"Hello, {name}!"
```
SEO
DocPlatform generates SEO metadata automatically from your page frontmatter:
| Tag | Source |
|---|---|
<title> |
Frontmatter title |
<meta name="description"> |
Frontmatter description |
<meta property="og:title"> |
Frontmatter title |
<meta property="og:description"> |
Frontmatter description |
<link rel="canonical"> |
Generated from page path |
sitemap.xml |
Auto-generated at /p/{slug}/sitemap.xml |
robots.txt |
Auto-generated at /p/{slug}/robots.txt |
| RSS feed | Auto-generated at /p/{slug}/rss.xml |
AI discoverability
Every published site also exposes endpoints designed for AI agents and LLM ingestion:
| Endpoint | Content |
|---|---|
/p/{slug}/llms.txt |
Plain-text index of the site’s published pages |
/p/{slug}/llms-full.txt |
Full Markdown content of all published pages (capped at 200 pages) |
/p/{slug}/manifest.json |
Machine-readable workspace manifest |
All discovery endpoints respect the site’s visibility setting.
Access control
By default, published docs require viewer authentication — only logged-in workspace members can read them. This protects your documentation from accidental public exposure.
To make a workspace’s published docs fully public (world-readable without login), a workspace admin must explicitly set the visibility to “public” in the workspace settings:
PUT /api/v1/workspaces/:id/admin/settings
{ "visibility": "public" }
| Visibility | Who can read | When to use |
|---|---|---|
| authenticated (default) | Logged-in workspace members only | Internal docs, client portals, team knowledge bases |
| public | Anyone with the URL | Open-source docs, product documentation, public guides |
When visibility is “authenticated”:
- Visitors who are not logged in are redirected to
/#/login?next=<url> - After signing in, they are returned to the page they requested
- Any workspace member (any role, including Viewer) can read published pages
- Non-members are redirected away even after logging in
- Sitemaps, robots.txt, and RSS feeds are also protected
Server-level override: The PUBLISH_REQUIRE_AUTH=true environment variable forces authentication on all published sites, regardless of their per-workspace visibility setting. This is useful for fully private installations where no documentation should ever be public.
Built-in components
Published docs support 15 custom components that render as rich, interactive elements. Here are the most commonly used ones (see Markdown & Components for the full list):
Callout
:::callout[info]
This is an informational callout.
:::
:::callout[warning]
Be careful with this operation.
:::
:::callout[danger]
This action is irreversible.
:::
:::callout[tip]
Pro tip: use keyboard shortcuts for faster editing.
:::
Types: info, warning, danger, tip, note
Tabs
:::tabs
::tab[npm]
npm install docplatform
::
::tab[yarn]
yarn add docplatform
::
::tab[pnpm]
pnpm add docplatform
::
:::
Accordion
:::accordion[How does sync work?]
DocPlatform uses a hybrid git engine that combines go-git for small repositories
with native git CLI for large ones. Changes are synced via polling or webhooks.
:::
Cards
:::cards
::card[Getting Started, link="/getting-started"]
Install and configure DocPlatform in under 10 minutes.
::
::card[User Guide, link="/guides/editor"]
Learn the web editor, git sync, and publishing features.
::
:::
Steps
:::steps
::step[Install]
Download the binary or pull the Docker image.
::
::step[Initialize]
Run `docplatform init` to create your workspace.
::
::step[Start]
Run `docplatform serve` and open the browser.
::
:::
API Block
:::api[GET /api/v1/content/{workspace}/{...path}]
Retrieve a single page by workspace and path.
**Parameters:**
- `workspace` (path, required) — Workspace slug
- `path` (path, required) — Page file path
**Response:** `200 OK`
```json
{
"page_id": "01HJKL...",
"title": "Getting Started",
"content": "..."
}
:::
## Custom domains
DocPlatform supports per-workspace custom domains with automatic TLS provisioning via Caddy integration.
### Setup
1. **Configure Caddy** as your reverse proxy with the on-demand TLS ask endpoint:
{ on_demand_tls { ask http://localhost:3000/internal/caddy/ask } }
:443 { tls { on_demand } reverse_proxy localhost:3000 }
2. **Set environment variables:**
```bash
export BASE_DOMAIN=docs.yourcompany.com
export CADDY_ADMIN_URL=http://localhost:2019
export CADDY_ASK_SECRET=your-shared-secret
- Assign a custom domain to a workspace via the API or workspace settings:
curl -X PUT /api/v1/workspaces/{id}/custom-domain \
-H "Authorization: Bearer ..." \
-d '{"domain": "docs.yourcompany.com"}'
- Point DNS — Add a CNAME or A record pointing to your DocPlatform server.
DocPlatform verifies DNS automatically and provisions TLS certificates on first request. No manual certificate management required. If CADDY_ASK_SECRET is empty, the ask endpoint rejects all requests (fail-closed) — custom-domain TLS will not provision until it is set.
Managing custom domains
Requires the workspace Admin role:
| Operation | Endpoint |
|---|---|
| Set domain | PUT /api/v1/workspaces/:id/custom-domain |
| Check status | GET /api/v1/workspaces/:id/custom-domain |
| Remove domain | DELETE /api/v1/workspaces/:id/custom-domain |
Caching
Published pages are cached for performance:
| Header | Value | Description |
|---|---|---|
Cache-Control |
public, max-age=300 |
Browsers and CDNs cache for 5 minutes |
ETag |
Content hash | Enables conditional requests (304 Not Modified) |
The cache key is based on the page’s content hash. When content changes, the ETag changes automatically and cached versions are invalidated.
Uploaded images
Images uploaded through the editor are served from the workspace’s uploads endpoint. On published sites with public visibility, uploads referenced by published pages are publicly readable.
Static export
Export your published docs as a self-contained static HTML ZIP for CDN deployment or offline distribution.
Via CLI
docplatform export --workspace {workspace-id} --output ./my-docs-export.zip
Via API
GET /api/v1/workspaces/{id}/export # build and download the ZIP (synchronous)
POST /api/v1/workspaces/{id}/export # same behavior (compatibility alias)
The export is synchronous — the ZIP is rendered and streamed in the same request; there is no job to poll.
The export contains:
- Rendered HTML for all published pages
sitemap.xmlandrobots.txt- Sidebar navigation and CSS
- Ready to deploy to any static file host (Netlify, Vercel, S3, GitHub Pages)
Preview before publishing
Preview published docs locally without building a static export:
docplatform preview --workspace {workspace-id} --port 4000
This starts a lightweight local server that renders pages in real-time — useful for reviewing changes before deploying.