This guide defines the writing, formatting, and diagram conventions for all documentation in docling-pipelines. Every contributor must follow it. It is the single source of truth when in doubt about formatting — do not invent new conventions.
| Location | Purpose |
|---|---|
README.md |
Project overview, setup, quick start |
ARCHITECTURE.md |
System design, component diagrams, design decisions |
QUICKSTART.md |
Fastest path to a running pipeline |
CONTRIBUTING.md |
How to contribute code and docs |
CHANGELOG.md |
Release notes (Keep a Changelog format) |
docs/guides/ |
How-to guides (authoring, security, custom operators, etc.) |
docs/operators/<category>/<operator_name>_readme.md |
Per-operator user guide — one file per operator, no separate config file |
docs/reference/ |
API and schema reference |
docs/integrations/<name>/ |
Integration-specific docs (OpenSearch, Milvus, Prefect) |
docs/internals/ |
Maintainer-facing architectural notes (maintainers only, never linked from user docs) |
Rules
UPPER_SNAKE_CASE.md for root-level docs and lower_snake_case.md for files inside docs/.docs/README.md, CONTRIBUTING.md, or a parent README.md).<name>_config.md files alongside operator READMEs. All parameter and configuration content belongs in README.md. The separate config file pattern is retired.# Title (H1). There is exactly one H1 per file.## Table of Contents section with anchor links is required for any file longer than 80 lines.--- to separate major top-level sections when a visual break aids readability.# H1 — File title only, once per file
## H2 — Major section
### H3 — Sub-section
#### H4 — Detail within a sub-section
## to ####).## \DocpipeFlowManager``).Always use exactly three backticks to open and close a fenced block:
```python
# correct
```
Never use four or more backticks (`````mermaid, ```python`). Editors and renderers are inconsistent about how they handle 4-backtick fences, and it has caused rendering failures in this repository.
Always specify a language tag immediately after the opening fence. Use the following tags consistently:
| Language / format | Tag |
|---|---|
| Python | python |
| Bash / shell commands | bash |
| JSON flow file | json |
| YAML config | yaml |
| Mermaid diagram | mermaid |
| Plain text / output | text |
| SQL | sql |
| Dockerfile | dockerfile |
# correct
export PYTHONPATH="$(pwd)/src:${PYTHONPATH}"
# wrong — no language tag
export PYTHONPATH="$(pwd)/src:${PYTHONPATH}"
Never nest fenced blocks. If you need to show a fence inside a fence (e.g., in a style guide like this one), use a surrounding four-backtick block for the outer wrapper only — and document why you are doing so.
Mermaid diagrams are the standard for all architecture and flow diagrams in this project. Follow these rules to avoid broken renders.
```mermaid
graph TD
A[Start] --> B[End]
- Open with ` ```mermaid ` (exactly three backticks + the word `mermaid`).
- Close with ` ``` ` on its own line.
- No content after the closing fence on the same line.
### Diagram type selection
| Use case | Diagram type |
| --- | --- |
| Component hierarchy, layered architecture | `graph TD` (top-down) |
| Data flows, pipelines, operator chains | `graph LR` (left-right) |
| Class relationships, inheritance | `classDiagram` |
| Sequence of calls between components | `sequenceDiagram` |
| State machines | `stateDiagram-v2` |
### Node labels
- Keep node labels short (1–5 words).
- Use `[Label]` for process/component nodes, `([Label])` for rounded (start/end), `{Label}` for decisions.
- Escape special characters inside labels. Square brackets `[` `]` inside a label must use HTML entities or quotes: `A["Label [with brackets]"]`.
- Do not use the `%%` comment syntax inside a node label. Put `%%` comments on their own line before the node.
### Styles
- Only use `style <NodeId> fill:<color>` for a small set of key nodes that need visual distinction. Do not style every node.
- Use the project colour palette for consistency:
| Layer | Fill colour |
| --- | --- |
| Interface / CLI | `#e1f5ff` |
| Orchestration | `#fff4e1` |
| Data / PyArrow | `#e8f5e9` |
| Integration | `#f3e6ff` |
| Quality operators | `#e6ffe6` |
### Validation
**Test every Mermaid diagram before committing.** Paste the block into [mermaid.live](https://mermaid.live) and confirm it renders without errors. A diagram that does not render is a documentation bug.
### Example — correct diagram
```mermaid
graph LR
A[Ingest] --> B[Extract]
B --> C[Chunk]
C --> D[Embed]
D --> E[VectorDB]
style A fill:#e1f5ff
style E fill:#e8f5e9
| --- | --- |).| ---: | for right-align, | :---: | for centre.| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `chunk_size` | `int` | `512` | Maximum characters per chunk. |
| `overlap` | `int` | `50` | Character overlap between chunks. |
[guide](../guides/FOO.md) not https://github.com/…/FOO.md.[Operator reference](/docling-pipelines/reference/OPERATORS.html) — not [click here] or [here].[Mermaid diagrams](#mermaid-diagrams).[AbstractOperator](src/docpipe/core/operators/abstract_operator.py).- for unordered lists throughout the file — do not mix - and *.1. 2. 3. for ordered lists when sequence matters.GitHub-flavoured Markdown renders > [!NOTE], > [!WARNING], and > [!TIP] as styled callouts. Use them sparingly:
> [!NOTE]
> This behaviour changed in v0.2.0. See the migration guide.
> [!WARNING]
> Do not set `DS_LOG_JSON=True` in development — it disables human-readable output.
> [!TIP]
> Run `docling-pipelines --list-operators --verbose` to see all available parameters.
> **Note:** (plain blockquote bold) — it does not render as a callout.All changes must be recorded in CHANGELOG.md using Keep a Changelog format.
## [Unreleased]
### Added
- `MyNewOperator` — short description of what it does and why. (#123)
### Changed
- `chunker`: `chunk_type` now defaults to `"simple"` instead of `"semantic"`. (#456)
### Fixed
- `VectorDBOperator`: fixed index not being created when `auto_create_index=True`. (#789)
### Deprecated
- `IngestLocalOperator.path` parameter — use `paths` (list) instead. Removed in v2.0.
### Removed
- `OldOperator` — deprecated since v0.3. Use `NewOperator` instead.
Rules:
## [Unreleased] until a release is cut.Every operator file lives at docs/operators/<category>/<operator_name>_readme.md. There is no separate *_config.md file. All content lives in this single file, in the section order below.
Section names are a contract — do not rename them. An agent or developer navigating operator docs must find ## Parameters in the same place in every README.
# OperatorClassName
One-sentence description. Short name: `operator_type` · Category: Functional | Extract | Ingest | Quality | VectorDB
## Overview
What problem it solves. When to use it vs alternatives. 3–5 sentences. No code blocks.
## Key Features
- Feature one (5–8 bullets max, no sub-bullets)
- Feature two
## Operator Configuration
The first code block in the file. A complete, copy-pasteable flow node showing all required
parameters and optional parameters at their default values. Comment each parameter inline.
\```json
{
"name": "my_op",
"type": "operator_short_name",
"depends_on": ["previous_op"],
"config": {
"operator_params": {
"param_name": "value", // required — what it controls
"optional_param": 512 // optional, default 512
}
}
}
\```
## Parameters
Flat table. One row per parameter. Add a "Provider" column when a param applies only to
certain providers. Do not split into sub-sections by provider.
| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `param_name` | `string` | Yes | — | What the parameter controls. |
| `optional_param` | `int` | No | `512` | What it controls. |
## Output Columns
Every column this operator adds to the PyArrow table. Required for agent readability —
downstream operators depend on knowing what columns are available.
| Column | Type | Description |
| --- | --- | --- |
| `column_name` | `string` | What this column contains. |
## Examples
2–3 named examples. Each is a self-contained flow node snippet with a one-line title.
### Example 1: \<use case\>
\```json
{ ... }
\```
### Example 2: \<use case\>
\```json
{ ... }
\```
## Troubleshooting
Format: **Error or symptom** → cause → fix. No prose paragraphs.
**`ConnectionRefusedError` connecting to Ollama** — Ollama is not running. Start it with `ollama serve`.
## Architecture
Optional. Maintainers only. Always the last section.
Move hexagonal architecture diagrams, adapter patterns, and internal class details here —
or link to `docs/internals/OPERATOR_ARCHITECTURE_<name>.md` for long content.
What is forbidden in an operator README:
## Architecture (the last section)CHANGELOG.md<name>_config.md file in the same directory## Contributing, ## License, or ## Version History sectionsdocs/reference/OPERATORS.md — link instead| Mistake | Fix |
|---|---|
| ` ````mermaid ` (four backticks) | Change to ` ```mermaid ` |
| Mermaid block never closed | Add ` ``` ` on its own line after the last diagram line |
Typo in node label (ExtactOperator) |
Verify node labels against actual class names |
| Missing language tag on code fence | Add the appropriate tag (e.g., python, bash, json) |
Skipped heading level (## → ####) |
Insert the missing ### level |
Bare URL for internal doc (https://github.com/.../FOO.md) |
Replace with relative path (../guides/FOO.md) |
| Link text is “here” or “click here” | Use descriptive text ([Operator reference](…)) |
| No header separator in table | Add \| --- \| --- \| after the header row |
Mixed - and * in the same list |
Standardise on - |
| Future tense (“will return”) | Change to present tense (“returns”) |
| Created multiple files in one operator directory | Merge all content into the single <operator_name>_readme.md |
Architecture content above ## Troubleshooting |
Move to ## Architecture (last section) or docs/internals/ |
## Operator Configuration shows partial snippet |
Show a complete flow node JSON with all required params and defaults |
Missing ## Output Columns section |
Add a table of every column this operator adds to the PyArrow table |
Questions about this guide? Open a GitHub Discussion or propose a change via pull request.