# Diplodoc Platform — Documentation Reference
Diplodoc is an open-source "Documentation as Code" platform for building, managing, and publishing technical documentation. It processes **Yandex Flavored Markdown (YFM)** — a CommonMark superset with extended elements including callouts, cuts, tabs, variables, conditional operators, and content reuse — and compiles it into static HTML sites. The platform supports multilingual projects, single-source publishing, OpenAPI integration, plugin extensions, and deployment to S3 or GitHub Pages. It is designed around the `@diplodoc/cli` npm package (`yfm` CLI command) and a YAML-driven project configuration system.
Core functionality centers on the `yfm build` command which reads a project directory containing a `.yfm` config, a `toc.yaml` table of contents, markdown content files, and optional `presets.yaml` variable files — then outputs a ready-to-serve static HTML site. The platform's extension system (Extensions API) allows hook-based customization of every build stage via TypeScript, and the includer subsystem enables automatic documentation generation from OpenAPI specs, tarballs, or any external markdown-producing tool. Variables, conditional operators, and preset files support single-source multi-audience builds from one content repository.
---
## CLI Installation and Initial Setup
Install the `@diplodoc/cli` package globally via npm. The `yfm` command is the primary interface for all build, publish, and lint operations.
```bash
# Install globally (requires Node.js v22+)
npm i @diplodoc/cli -g
# Initialize a new project interactively
yfm init
# Minimal project structure created manually
doc-folder/
├── .yfm # Project configuration (YAML)
├── toc.yaml # Table of contents definition
├── presets.yaml # Variable presets (optional)
└── index.yaml # Leading (landing) page
```
---
## `yfm build` — Build Documentation to HTML
Compile a documentation project from a source directory to static HTML. The `--input` and `--output` flags are required; all other settings can come from the `.yfm` config file.
```bash
# Basic build: source → HTML output
yfm build -i ./docs -o ./docs-html
# Short form (input defaults to current directory)
yfm -o ./docs-html
# Build with variable preset selection
yfm build -i ./docs -o ./docs-html --varsPreset external
# Strict mode: treat warnings as errors
yfm build -i ./docs -o ./docs-html --strict
# Build to YFM intermediate format (for single-source branching)
yfm build -i ./docs -o ./docs-md --output-format=md --apply-presets
# Single-page build (all pages merged into one HTML file)
yfm build -i ./docs -o ./docs-html --singlePage
# Watch mode: incremental rebuild + browser live-reload
yfm build -i ./docs -o ./docs-html --watch
# Remove hidden TOC items from output
yfm build -i ./docs -o ./docs-html --remove-hidden-toc-items
# View all available flags
yfm build --help
```
---
## `.yfm` — Project Configuration File
The `.yfm` file at the project root (YAML format) controls all build and viewer settings. Pass a custom path with `--config`.
```yaml
# .yfm — complete example configuration
allowHtml: true # Allow raw HTML in markdown (required for OpenAPI includer)
langs: ['en', 'ru'] # Supported languages for multilingual projects
breaks: true # Carriage return = line break (set false for two-space breaks)
linkify: true # Auto-convert URL strings to links
conditionsInCode: false # Do not evaluate {% if %} inside code blocks
disableLiquid: false # Keep variable substitution enabled
supportGithubAnchors: true # Also generate GitHub-compatible header anchors
lang: en # Default locale for UI text
needToSanitizeHtml: true # Sanitize generated HTML
disableCsp: false # Inject CSP meta tags
vars: # Inline variable definitions
version: '2.0'
product: MyApp
search:
provider: local # Built-in lunr.js search
analytics:
gtm:
id: GTM-XXXXXXX
mode: notification # Show cookie consent before sending events
resources:
style:
- _assets/style/custom.css
extensions:
- name: mdit-plugins
plugins:
- '@diplodoc/transform/lib/plugins/checkbox'
- github-vcs
preprocess:
mergeIncludes: true
# S3 publish settings (used with --publish flag)
storageEndpoint: https://storage.example.com
storageBucket: my-docs-bucket
storageKeyId: KEY_ID # or set YFM_STORAGE_KEY_ID env var
storageSecretKey: SECRET # or set YFM_STORAGE_SECRET_KEY env var
storagePrefix: v2.0 # Optional: organizes builds into versioned folders
```
---
## `toc.yaml` — Table of Contents
Defines the documentation structure and navigation hierarchy. Only files referenced in `toc.yaml` are included in the build.
```yaml
# toc.yaml — complete structure example
title: "{{ product }} Documentation" # Supports variable substitution
href: index.yaml
items:
- name: Getting Started
href: quickstart.md
- name: Reference
expanded: true # Section open by default (first-level only)
items:
- name: API Overview
href: api/index.md
- name: Configuration
href: config.md
when: version >= 2 # Conditional visibility based on variable
- name: Secret Internals
href: internal.md
hidden: true # Accessible by direct URL only
# Include another toc.yaml as a subsection
- name: SDK Reference
include:
path: sdk/toc.yaml # path relative to doc root by default
# Merge another toc.yaml at the same level (no wrapper section)
- include: { path: changelog/toc.yaml }
# Include with relative path using merge mode
- include: { mode: merge, path: ../shared/toc.yaml }
# Include with link mode: structure unchanged, links rewritten
- name: Shared Guides
include:
path: shared/guides
mode: link
```
---
## `presets.yaml` — Variable Presets
Define groups of variables to produce multiple documentation variants from a single source. Pass the preset name at build time with `--varsPreset`.
```yaml
# presets.yaml
default:
product: MyApp
version: '2.0'
users:
- Alice
- Bob
internal:
audience: internal
show_internal: true
external:
audience: external
show_internal: false
```
```bash
# Build for external audience
yfm build -i ./docs -o ./out --varsPreset external
# Build for internal audience
yfm build -i ./docs -o ./out --varsPreset internal
# Override individual variables inline
yfm build -i ./docs -o ./out --vars '{"version":"3.0"}'
```
---
## `index.yaml` — Leading (Landing) Page
Create a grid-style landing page linking to major documentation sections. Supports variable substitution and conditional visibility.
```yaml
# index.yaml
title: "{{ product }} Docs"
description: "Full documentation for {{ product }} version {{ version }}."
meta:
title: "{{ product }} – Official Docs"
noIndex: false
links:
- title: Getting Started
description: Install and run your first build.
href: quickstart.md
- title: Configuration Reference
description: All .yfm options documented.
href: config.md
- title: Internal Guide
description: For internal teams only.
href: internal.md
when: audience == 'internal' # Hidden when building external preset
- title: "{% if version >= '2.0' %}New API{% else %}Legacy API{% endif %}"
description: "{{ link_description }}"
href: api/index.md
```
---
## YFM Syntax — Basic Markup
Yandex Flavored Markdown extends CommonMark with superscript, monospace inline, and configurable anchor IDs on headers.
```markdown
**Bold text** _Italic_ **_Bold italic_**
~~Strikethrough~~ Super^script^ ##Monospaced##
# Page Title (h1)
## Section (h2) {#custom-anchor}
### Subsection (h3)
#### Detail (h4)
> Blockquote
>> Nested blockquote
Super\^not-a-script^
Red text
```
---
## YFM Syntax — Notes (Callouts)
Highlight important content with typed callout blocks. All four types support optional custom headers.
```markdown
{% note info %}
This is an informational note.
{% endnote %}
{% note tip %}
This is a helpful tip.
{% endnote %}
{% note warning %}
This is a warning — pay attention.
{% endnote %}
{% note alert %}
This is a critical alert.
{% endnote %}
{% note info "Custom Header" %}
A note with a custom title instead of the default.
{% endnote %}
{% note info "" %}
A note with no header at all.
{% endnote %}
```
---
## YFM Syntax — Cuts (Collapsible Sections) and Tabs
Interactive elements for hiding optional content and organizing mutually-exclusive instructions.
```markdown
{% cut "Show advanced options" %}
Any YFM content here — tables, code blocks, images...
```yaml
advanced:
option: value
```
{% endcut %}
{% list tabs group=os %}
- macOS
```bash
brew install my-tool
```
- Linux
```bash
sudo apt-get install my-tool
```
- Windows
```powershell
choco install my-tool
```
{% endlist %}
{% list tabs group=os %}
- macOS
Run: `my-tool start`
- Linux
Run: `sudo my-tool start`
- Windows
Run: `my-tool.exe start`
{% endlist %}
```
---
## YFM Syntax — Variables and Conditional Operators
Use template variables for substitution, conditional content inclusion, loops, and string filters. Variables come from `.yfm`, `presets.yaml`, or the `--vars` flag.
```markdown
Welcome to {{ product }} version {{ version }}!
Use not_var{{ literal_braces }} in your template.
{% if OS == 'iOS' %}
Download from the [App Store](https://apple.com/app-store/).
{% elsif OS == 'Android' %}
Download from [Google Play](https://play.google.com).
{% else %}
Download from our [website](https://example.com/download).
{% endif %}
Tap {% if OS == 'iOS' %}Settings{% else %}Preferences{% endif %} to continue.
{% for user in users %}
- Hello, {{ user }}!
{% endfor %}
Hello, {{ user.name | capitalize }}!
Total users: {{ users | length }}
Hello P{{ user.name.slice(1) }}!
```
```yaml
# presets.yaml providing the above variables
default:
product: MyApp
version: '2.0'
OS: iOS
user:
name: masha
users:
- Alice
- Bob
```
---
## YFM Syntax — Content Reuse with `{% include %}`
Extract repeated content into shared files stored in `_`-prefixed directories, then include them anywhere.
```markdown
{% include [Note about authentication](_includes/auth-note.md) %}
{% include notitle [Auth note](_includes/auth-note.md) %}
{% include [Part 2 only](reference.md#part2) %}
```
```markdown
## Authentication Requirements {#auth}
All API calls require a valid Bearer token in the `Authorization` header.
## Rate Limits {#limits}
Requests are limited to 1000/hour per API key.
```
```markdown
{% include [Auth requirements](_includes/auth-note.md#auth) %}
```
---
## YFM Syntax — Links, Media, and Code
Standard linking, image embedding with size control, file download links, and syntax-highlighted code blocks.
```markdown
[Visit Diplodoc](https://diplodoc.com "Official site")
[{#T}](./api/index.md)
[See configuration options](config.md#settings)
My favorite tool is [Diplodoc][1].
[1]: https://diplodoc.com "Diplodoc Platform"
{width=800}
[{width=120}](https://diplodoc.com)
{% file src="data:text/plain;base64,SGVsbG8=" name="hello.txt" %}
```typescript showLineNumbers
import { Build } from '@diplodoc/cli';
const ext = new MyExtension();
ext.apply(program);
```
Run `yfm build -i ./docs -o ./out` to compile.
```
---
## YFM Syntax — Page Metadata and Comments
Add YAML front matter for SEO metadata and non-rendering author comments.
```markdown
---
title: API Reference
description: Complete reference for the MyApp REST API.
---
[//]: # (TODO: add authentication examples before launch)
# API Reference
Content starts here...
```
---
## Includers — Auto-generated Documentation
Includers connect external content sources into the documentation build via `toc.yaml`. They run as a pipeline and can be chained.
```yaml
# toc.yaml — chain of includers: unarchive tarball then render with generic includer
title: Documentation
href: index.yaml
items:
# Generic includer: import any pre-generated markdown directory
- name: SDK Docs
include:
path: sdk-docs
includers:
- name: generic
input: generated/sdk # path to markdown files
autotitle: true # use file headings as nav labels
linkIndex: true # make index.md the clickable section href
mode: link
# OpenAPI includer: generate API reference from OpenAPI 3.x spec
- name: REST API
include:
path: api-reference
includers:
- name: openapi
input: openapi.yaml # OpenAPI 3.x spec file
mode: link
# Unarchive → generic pipeline: unpack tarball then render
- name: External Docs
include:
path: external
mode: link
includers:
- name: unarchive
input: docs.tar # tarball with markdown content
output: unpacked # temp directory for extracted files
- name: generic
input: unpacked # use unarchive's output as input
```
```yaml
# index.yaml — link to includer-generated sections
title: Documentation
links:
- title: SDK Docs
href: sdk-docs/
- title: REST API
href: api-reference/
- title: External Docs
href: external/
```
---
## OpenAPI Includer — Advanced Configuration
Fine-tune how OpenAPI specs are rendered: customize tag names, filter endpoints, control sandbox tabs, and manage search indexing.
```yaml
# toc.yaml — full OpenAPI includer configuration
title: API Docs
href: index.yaml
items:
- name: API Reference
include:
path: api
mode: link
includers:
- name: openapi
input: openapi.yaml
# OpenAPI-specific options (set alongside include)
tags:
__root__:
name: All Endpoints # rename the top-level TOC entry
alias: endpoints # rewrite URL slug
authentication:
name: Auth
alias: auth
hidden: false
internal:
hidden: true # hide this tag from navigation
leadingPage:
name: API Overview
spec:
renderMode: inline # include raw spec on leading page (or: hidden)
sandbox:
tabName: Try It
host: 'https://api.example.com' # base URL for sandbox requests
filter:
endpoint: tags contains "nobuild" != true # exclude draft endpoints
noindex:
tag: name == "noindex" # prevent search indexing for tagged sections
```
```yaml
# openapi.yaml — hide a field using x-hidden extension
paths:
/users:
get:
parameters:
- name: internal_id
in: query
schema:
type: string
x-hidden: true # this parameter won't appear in the rendered docs
```
---
## S3 Publishing
Publish built documentation directly to S3-compatible object storage using the `--publish` flag.
```bash
# Publish using environment variables for credentials
export YFM_STORAGE_KEY_ID=AKIAIOSFODNN7EXAMPLE
export YFM_STORAGE_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
yfm build -i ./docs -o ./out --publish \
--storageEndpoint https://storage.yandexcloud.net \
--storageBucket my-docs-bucket \
--storagePrefix v2.0
```
```yaml
# .yfm — equivalent S3 config (credentials via env vars)
storageEndpoint: https://storage.yandexcloud.net
storageBucket: my-docs-bucket
storagePrefix: v2.0 # each build version in its own folder
```
---
## GitHub Actions — Automated Builds
Integrate Diplodoc builds into CI/CD using the official GitHub Actions.
```yaml
# .github/workflows/docs.yml — build and deploy to GitHub Pages
name: Build and Deploy Docs
on:
push:
branches: [main]
paths: ['docs/**']
push:
tags: ['v*.*.*']
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
# Build docs using the official action
- name: Build docs
uses: diplodoc-platform/docs-build-static-action@v1
with:
src-root: './docs'
build-root: './docs-html'
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './docs-html'
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
# Versioned release to S3
release:
runs-on: ubuntu-latest
steps:
- name: Release versioned docs
uses: diplodoc-platform/docs-release-action@v2
with:
revision: "${{ github.sha }}"
version: "${{ github.ref_name }}"
storage-bucket: ${{ secrets.DIPLODOC_STORAGE_BUCKET }}
storage-access-key-id: ${{ secrets.DIPLODOC_ACCESS_KEY_ID }}
storage-secret-access-key: ${{ secrets.DIPLODOC_SECRET_ACCESS_KEY }}
```
---
## Extensions API — Hook-based CLI Customization
Extend the Diplodoc build pipeline using TypeScript extensions. Extensions tap into hooks exposed by `Program` (CLI setup) and `Run` (build execution) context objects.
```typescript
// my-extension/index.ts
import { Build } from '@diplodoc/cli';
import { Option } from 'commander';
import {
getBaseHooks,
getTocHooks,
getMarkdownHooks,
getLeadingHooks,
getMetaHooks,
} from '@diplodoc/cli/hooks';
export class MyExtension {
apply(program: Build) {
// 1. Command Extension: add a custom CLI flag
getBaseHooks(program).Command.tap('MyExtension', (command) => {
command.addOption(new Option('--my-flag ', 'Custom flag'));
});
// 2. Processing Extension: hook into build execution
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
const tocHooks = getTocHooks(run.toc);
const markdownHooks = getMarkdownHooks(run.markdown);
const leadingHooks = getLeadingHooks(run.leading);
const metaHooks = getMetaHooks(run.meta);
// Modify every TOC item during resolution
tocHooks.Item.tapPromise('MyExtension', async (item) => {
if (item.name) {
item.name = `[DRAFT] ${item.name}`;
}
return item;
});
// Transform markdown content before rendering
markdownHooks.Resolved.tapPromise('MyExtension', async (content) => {
return content.replace(/TODO:/g, '⚠️ TODO:');
});
// Enrich leading page data from an external API
leadingHooks.Resolved.tapPromise('MyExtension', async (page) => {
const extra = await fetchExternalMetadata();
return { ...page, ...extra };
});
});
// 3. Cleanup after each run
getBaseHooks(program).AfterAnyRun.tap('MyExtension', (run) => {
console.log('Build complete:', run.output);
});
}
}
```
```yaml
# .yfm — register the extension
extensions:
- name: my-extension
path: ./my-extension/index.ts
```
---
## Summary
Diplodoc serves two primary use cases: **standalone technical documentation sites** for software products and APIs, and **enterprise documentation platforms** that consolidate multiple teams' docs under one roof. In the standalone case, teams write content in YFM markdown, define their `toc.yaml` navigation, and run `yfm build` locally or in CI to produce a static HTML site ready for GitHub Pages, S3, or any web server. The variable and preset system means the same source repository can produce separate internal and external builds, user-tier builds, or multi-language editions — without duplicating a single content file. The built-in OpenAPI includer makes Diplodoc a natural fit for teams wanting hand-written prose alongside auto-generated REST API reference pages.
For integration, Diplodoc fits into any Node.js-capable CI/CD pipeline. The official `diplodoc-platform/docs-build-static-action` and `docs-release-action` GitHub Actions handle build and versioned S3 publish in a few YAML lines. The Extensions API exposes a TypeScript hook system modeled after webpack's tapable library, enabling teams to write reusable build plugins that add CLI flags, transform content, integrate external data sources, or customize the VCS, search, and metadata services. The `@diplodoc/cli` package is the single install target; the `.yfm` config file wires together extensions, analytics (GTM, Yandex Metrika), CSP rules, search providers (local lunr.js or Algolia), and custom CSS — making the entire documentation infrastructure reproducible from a single version-controlled configuration.