Skip to content

Developer documentation


The Datadog Agent developer site is built with Zensical from Markdown in docs/public. It uses the classic theme variant and the configuration in mkdocs.yml. The writing guidelines cover how to organize and author pages; this page describes the build and the repository's customizations.

Configuration and source files

Key configuration and customization files include:

Location Purpose
mkdocs.yml Defines the site URL, navigation, theme, Markdown extensions, and additional assets.
docs/public Contains the site's Markdown pages and static assets.
docs/public/.hooks/inject_variables.py Supplies Markdown variables and repository-link macros.
docs/public/.snippets Contains shared link definitions and abbreviations.
docs/overrides/main.html Adapts the theme's navigation for independent roots.
docs/public/assets/javascripts/navigation-roots.js Implements the keyboard shortcut for returning from an independent navigation root to the main docs.
docs/public/assets/css/custom.css Customizes the site's appearance.
.dda/extend/commands/run/docs Implements the documentation commands.
.dda/extend/pythonpath/utils/docs/deps.py Declares the documentation tool dependencies.

The generated site is written to site/. The site_url setting includes the published /datadog-agent/ prefix. Links between documentation pages use relative Markdown paths so Zensical can resolve them for local previews and the published site.

Build and preview commands

Run these commands from the repository root after installing the development tooling.

Command Behavior
dda run docs serve Serves a live preview at http://localhost:8000; --port changes the port and --launch opens a browser.
dda run docs build Builds the site; --check also checks its links.
dda run docs check-links Checks links in an existing site/ build.

The build and serve commands install the declared dependencies into a dedicated environment. The link checker runs separately with the settings in .lychee.toml. Published-site URLs are remapped to the local build, so links to newly added pages can be checked before deployment. Repository links generated by the macros are validated during rendering and excluded from network checks.

The documentation workflow defines the automated build, link checks, and publication to GitHub Pages.

Variable injection

The zensical.extensions.macros Markdown extension loads docs/public/.hooks/inject_variables.py through module_name. Its define_env function registers variables and macros before Markdown is converted to HTML. Undefined variables and macro errors fail the build.

The custom delimiters avoid collisions with Go composite literals, GitHub Actions expressions, and Markdown attribute lists:

Template construct Opening delimiter Closing delimiter
Variable or macro expression <<< >>>
Block <<% %>>
Comment <<# #>>

For example, this source inserts the Go version from the repository:

Install Go <<<GO_VERSION>>>.

Examples of injected variables include:

Variable Source and content
GO_VERSION The stripped contents of .go-version.
PYTHON_VERSION The stripped contents of .python-version.
VSCODE_EXTENSIONS Markdown links for the VS Code extensions listed in the selected build image's configuration.

The hook fetches remote content from commit- or tag-based URLs selected by the repository's build configuration. Content is cached in .docs-cache/ so subsequent builds can reuse it without contacting GitHub. This cache is separate from Zensical's build cache. The hook is the source of truth for the available variables and how their values are selected.

Macros run throughout a page, including inside fenced code blocks. Literal examples require raw blocks, as shown in the repository-path guidelines. Shared snippets are expanded after macros and do not evaluate macro expressions.

The hook registers repo(path, text=None, *, match=None) and repo_url(path, *, match=None). Both accept a repository-relative path; match is a keyword-only regular expression that must match exactly one line of a regular file. repo produces a Markdown link, while repo_url produces the URL for uses such as HTML attributes.

The macros validate that paths exist with the correct casing, use blob URLs for files and tree URLs for directories, and reject Markdown pages under docs/public, which must use relative site links. Line matches are resolved at build time so source edits do not leave stale line numbers in the docs.

The target repository comes from repo_url in mkdocs.yml. The source ref is selected from DOCS_REF when set, otherwise the current branch, otherwise the commit for a detached checkout, with main as the fallback when Git information is unavailable. Preview links therefore refer to the source being built; the branch or commit must exist on GitHub for readers to open them.

The repository-defined extra.navigation_roots setting gives selected top-level sections independent navigation within the same generated site. Architecture is one example. Each configured entry identifies a section by its first child's generated URL, rather than by its display title, so renaming the section does not change the match.

Setting Meaning
extra.navigation_roots Lists independent top-level sections; an absent or empty list leaves Zensical's normal navigation in place.
url Identifies the section's landing page using its generated URL relative to the site root, such as architecture/.
back_label Sets the return-link text, which defaults to "Back to main docs".
back_key Sets the return shortcut, which defaults to b. Use an unused lowercase letter, or "" to disable it.

Several top-level sections can have independent roots. Nested roots are not supported, and each section's first child must be its landing page. The configuration instructions describe when a new root is appropriate and how to add one.

Outside a root, that section appears as a single link to its landing page. Inside it, the section's direct children become the top-level tabs, and their children supply sidebar entries and sections. The logo points to the root's landing page. A final navigation entry returns to the main homepage on desktop and mobile, and the b shortcut activates that link. Search and Previous/Next navigation remain shared across the entire site.

The template in docs/overrides/main.html extends base.html and changes the navigation passed to the stock theme. It preserves Zensical's tab and sidebar rendering without copying their partials. The template also emits the return destination in the page content for the keyboard handler.

JavaScript and CSS

The extra_javascript and extra_css settings in mkdocs.yml load additional browser assets. Local paths are relative to docs/public; external assets are listed by URL. These are Zensical's supported asset customization mechanisms.

The site enables navigation.instant, which replaces page content without a full browser reload. Page-dependent JavaScript uses Zensical's document$ observable to initialize after each page change.

The custom stylesheet includes branding and typography adjustments. Theme options, such as the logo and color scheme, remain in mkdocs.yml.

Markdown extensions and snippets

The markdown_extensions list in mkdocs.yml configures authoring features such as syntax highlighting and admonitions. The macros extension renders injected content before the other Markdown processing described above.

The snippets extension searches both docs/public/.snippets and the repository root, with missing paths treated as errors. It appends links.txt and abbrs.txt to every page for shared links and abbreviation tooltips. The repository-root search path also allows pages to include existing source documents without maintaining a separate copy of their text.