docfx.json
|
This content was generated with the assistance of AI and should be verified against the official documentation of each tool before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
This page was written against DocFX 2.81.0 (released on 2026-09-25, the latest release at the time) and checked on
2026-10-26. Every example was run with that version in the mcr.microsoft.com/dotnet/sdk:10.0 Docker image against a
small Pocket Units documentation project. docfx.json is the one file that tells DocFX what the project contains, so
this page goes through its sections and keys in the order you meet them. The generation of the API reference itself is
the subject of DotNet API Docs, and the stages that consume the file
are described in Basic Concepts and Pipeline.
What docfx.json is
A directory that contains a docfx.json is the root of a DocFX project. The commands docfx metadata, docfx build
and docfx pdf (or plain docfx, which runs them in sequence) read it, and every relative path inside it is resolved
against the directory of the file, not against the directory you run the command from. Passing another file name works
too (docfx build site.json), which is useful when one repository holds several sites.
The file has four top-level properties:
-
metadata: an array of metadata jobs, each turning .NET projects, solutions, assemblies or source files into YAML API description files (or Markdown, seeoutputFormatbelow). It is used bydocfx metadata. -
build: one object that describes the site: which files are content or resources, what metadata they get, which template renders them and where the output goes. It is used bydocfx build. -
pdf: the PDF generation settings, described in PDF Output. -
rules: overrides of the severity of individual log codes.
The file is read as JSON, but the parser used by 2.81.0 accepted a // comment and a trailing comma in the test
below, so both are safe to use in a hand-written file. The repository publishes a JSON schema,
https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json, which you can reference with a
$schema property to get completion and validation in editors that support it; DocFX ignores the property itself.
A complete example
The project used on this page has this layout. The library under src is the Pocket Units C# library, and the
overwrite, includes, old and meta folders exist to exercise the keys described below.
docfx.json
filterConfig.yml
toc.yml
index.md
articles/
toc.yml
dotnet/getting-started.md
dotnet/front-matter.md
python/intro.md
includes/note.md
images/logo.svg
meta/global.json
old/legacy.md
overwrite/converter.md
src/PocketUnits/{PocketUnits.csproj,Converter.cs,LengthUnit.cs}
The configuration, which built without warnings:
{
"$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json",
"metadata": [
{
"src": [
{ "src": "src", "files": ["**/*.csproj"], "exclude": ["**/bin/**", "**/obj/**"] }
],
"dest": "api",
"properties": { "TargetFramework": "net8.0" },
"filter": "filterConfig.yml",
"namespaceLayout": "flattened",
"memberLayout": "samePage",
"enumSortOrder": "declaringOrder",
"disableGitFeatures": true
}
],
"build": {
"content": [
{ "files": ["api/**.yml", "api/index.md"] },
{ "files": ["articles/**/*.{md,yml}", "toc.yml", "*.md", "old/**.md"], "exclude": ["includes/**"] }
],
"resource": [
{ "files": ["images/**"] }
],
"overwrite": [
{ "files": ["overwrite/**.md"] }
],
"globalMetadata": {
"_appTitle": "Pocket Units",
"_appName": "Pocket Units",
"_enableSearch": true,
"description": "from globalMetadata"
},
"globalMetadataFiles": ["meta/global.json"],
"fileMetadata": {
"description": {
"articles/dotnet/**.md": "from fileMetadata (dotnet)",
"articles/**.md": "from fileMetadata (articles)"
},
"_noindex": { "old/**.md": true }
},
"xref": ["https://learn.microsoft.com/en-us/dotnet/.xrefmap.json"],
"template": ["default", "modern"],
"output": "_site",
"sitemap": {
"baseUrl": "https://example.com/pocket-units/",
"priority": 0.5,
"changefreq": "monthly",
"fileOptions": {
"api/**.yml": { "priority": 0.3 },
"index.md": { "priority": 0.9, "changefreq": "weekly" }
}
},
"postProcessors": [],
"markdownEngineProperties": { "markdigExtensions": ["FootNotes"] },
"disableGitFeatures": true
}
}
Source: DocFX docs: docfx.json reference
Running it needs only the tool and the .NET SDK. The tool was installed in the container with a pinned version:
dotnet tool install docfx --version 2.81.0 --tool-path /tools/docfx
cd /w && /tools/docfx/docfx docfx.json
Source: DocFX docs: CLI overview
The last lines of the real output were:
Applying templates to 12 model(s)...
XRef map exported.
Extracting index data from 8 html files
Sitemap file is successfully exported to /w/_site/sitemap.xml
Build succeeded.
0 warning(s)
0 error(s)
File mappings
content, resource and overwrite in build, and src in metadata, all take a list of file mappings. A mapping
is either a plain glob string (the short form) or an object (the expanded form).
{
"build": {
"content": [
"**/*.md",
{ "files": ["**/*.yml", "*.md"], "exclude": ["**/*Private*"], "src": "../api", "dest": "api" }
]
}
}
Source: DocFX docs: File mappings
| Key | Meaning |
|---|---|
|
A glob or an array of globs. Relative to |
|
A glob or an array of globs removed from the match. Use it for fragments that are included by other files (see the pitfalls below). |
|
The source directory, relative to |
|
A folder name prefixed to the output path of every matched file. |
The glob syntax has four wildcards: * matches zero or more characters inside one path segment, ? matches exactly
one character, ** matches zero or more directories, and {a,b} expands a comma-separated set. In the examples above
api/**.yml and articles/**/*.{md,yml} both work.
DocFX publishes each file at the URL given by its path relative to docfx.json, with an .html extension (so
docs/urls.md becomes docs/urls.html). Use src and dest together to change that. This configuration, run on a
project whose only page was articles/getting-started/installation.md, produced _site/docs/getting-started/installation.html:
{
"build": {
"content": [
{ "files": "**/*.{md,yml}", "src": "articles", "dest": "docs" }
],
"output": "_site"
}
}
Source: DocFX docs: URL management
When a pattern matches nothing, DocFX does not fail. It logs a line such as the following and carries on, which is easy to miss when a path is mistyped:
No files are found with glob pattern nothing/**.md, excluding <none>, under directory "/w"
The metadata section
metadata is an array, so one docfx.json can generate several API sets (for example one per product). Each entry
reads its inputs from src and writes YAML files to dest. The table lists every key of the reference; the
behaviour of the .NET-specific ones is explained in DotNet API Docs.
| Key | Meaning |
|---|---|
|
File mappings that select the inputs: |
|
Output folder of the generated files, relative to |
|
|
|
Path of a filter file whose |
|
MSBuild properties used when reading project files, for example |
|
Skip |
|
Extra assembly references, used for assembly and source-file input (not for solution or project input). |
|
|
|
|
|
Both default to |
|
Name used for the global namespace; empty by default. |
|
Continue generation when the code does not compile. |
|
Do not render the triple-slash comments as Markdown. |
|
Base directory for resolving |
|
Disables the generation of View Source links. |
|
Hides View Source links for matching source document paths without removing the APIs. New in 2.81.0. |
The output of the metadata job in the example is the folder api with PocketUnits.yml, PocketUnits.Converter.yml,
PocketUnits.LengthUnit.yml, a toc.yml and a .manifest file. The Reset method of the sample library carries
<exclude /> in its comment and does not appear in the built page.
The build section
The keys of build fall into five groups.
Choosing the files
| Key | Meaning |
|---|---|
|
Files transformed to HTML: Markdown articles, the YAML files produced by |
|
Files copied to the output unchanged: images, downloads, fonts. In the example |
|
Conceptual Markdown files whose YAML header carries a |
|
One or more xref maps (a string or an array of strings: file paths or http, https and file URLs) used to resolve
|
|
Maps a group name to an output folder ( |
Metadata, templates and output
| Key | Meaning |
|---|---|
|
Key-value pairs applied to every file, inline or loaded from JSON files. |
|
Per-key maps from glob patterns to values, inline or loaded from JSON files. |
|
A template name or an array. Later templates override earlier ones when file names collide. When the key is omitted
the embedded |
|
Extra style layers applied over the template, a string or an array. If omitted, no theme is applied. |
|
Output folder of the site ( |
Processing
| Key | Meaning |
|---|---|
|
Settings object for the Markdown engine. The documented use is |
|
An array of post processor names. The built-in HTML processor is always added, so an empty array is valid. |
|
Name of an |
|
Maximum parallelism; |
|
Sitemap generation, described below. |
|
Skips fetching Git information for articles. Default |
Debugging
debug and debugOutput enable debug mode and set its output folder, exportRawModel and rawModelOutputFolder write
the data model that templates receive as .raw.json files, exportViewModel and viewModelOutputFolder write the model
after the template preprocessor as .view.json, and dryRun skips applying templates so that only those model files are
produced. They are mostly used when writing templates.
Metadata and its precedence
Metadata are key-value attributes attached to a file. Some shape the page (title, description, _appTitle) and
some are only read by templates. They come from four places:
-
the YAML front matter at the top of an article;
-
fileMetadata(andfileMetadataFiles), matched by glob; -
globalMetadata(andglobalMetadataFiles), applied to every file; -
for
toc.ymlfiles, the metadata declared inside the TOC file.
When a key is defined in several places, front matter wins over fileMetadata, which wins over globalMetadata. For TOC
files the order is fileMetadata, then metadata inside toc.yml, then globalMetadata, so a fileMetadata entry can
override a generated TOC.
Source: DocFX docs: Config, metadata
The example project makes the order visible with the description key. The four pages below were built from the
configuration above and the rendered <meta name="description"> is:
| Page | Defined in | Rendered description |
|---|---|---|
|
|
from globalMetadata |
|
|
from fileMetadata (articles) |
|
two matching |
from fileMetadata (articles) |
|
front matter and |
from front matter |
The third row shows how overlapping patterns inside one fileMetadata key behave: the page matched both
articles/dotnet/**.md and articles/**.md, and the value of the entry listed last won. When the two entries were
swapped in a second build the dotnet value was rendered, so the order of patterns matters. The reference states this rule for
sitemap fileOptions; for fileMetadata it is an observation of 2.81.0, so list the general pattern first and the more
specific one after it.
globalMetadataFiles accepted a JSON file that defines _appFooter and the footer text was rendered in the
page. Predefined keys understood by the built-in templates include _appTitle (suffix of every page title),
_appName, _appFooter, _appLogoPath and _appFaviconPath (paths from the output root, so the files must be in
resource), _enableSearch, _enableNewTab, _disableNavbar, _disableBreadcrumb, _disableToc, _disableAffix,
_disableContribution, _gitContribute, _gitUrlPattern and _noindex. The default and modern templates
do not support all of them identically; the differences are described in
Templates and Customization.
Source: DocFX docs: Predefined metadata
Redirects
A redirect is an article whose only content is a redirect_url in its front matter. The target can be relative or an
absolute URL. The file has to be part of content (the example includes old/**.md).
---
redirect_url: ../articles/dotnet/getting-started.html
---
Source: DocFX docs: URL redirects
The built _site/old/legacy.html is a small page with a meta refresh and no content:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0;URL='../articles/dotnet/getting-started.html'">
</head>
</html>
This is a client-side redirect, so it works on any static host, but it is not an HTTP status redirect. Keep the old file in the source tree for as long as the old URL must keep working.
Cross references: xref
build.xref lists xref maps, files that map UIDs to URLs. DocFX writes its own xrefmap.yml into the output so that
other projects can consume it. Adding the .NET base class library map lets articles link to framework types. In the example
a <xref:System.String> link in articles/python/intro.md was rendered as an anchor to
https://learn.microsoft.com/dotnet/api/system.string, and the build log reported 1 external references found in xref maps.
The syntax of the links is described in
Links and Cross References.
A UID that exists nowhere gives a warning, here for <xref:Missing.Type>:
/w/articles/python/intro.md: warning UidNotFound: 1 invalid cross reference(s) "<xref:Missing.Type>".
/w/articles/python/intro.md: Details for invalid cross reference(s): "<xref:Missing.Type>" in line 4
The top-level rules property changes the severity of a log code. With the rule shown below, which lowers UidNotFound
to info, the same build finished with 0 warnings. Supported values are verbose, info, suggestion, warning and error.
{
"rules": {
"UidNotFound": "info"
}
}
Sitemap
The sitemap object makes the build write sitemap.xml. baseUrl is mandatory: without it, no sitemap is generated.
In a build with the baseUrl key removed, _site/sitemap.xml did not exist and the log did not mention it. The reference
says the value must begin with the protocol and end with a trailing slash. The other keys are lastmod (default: the
build time), changefreq (always, hourly, daily, weekly, monthly, yearly or never; default daily),
priority (0.0 to 1.0, default 0.5) and fileOptions, a map from glob to overriding options in which later matches
overwrite earlier ones. The sample produced entries such as:
<url>
<loc>https://example.com/pocket-units/index.html</loc>
<lastmod>2026-10-26T11:04:11+00:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
Source: DocFX docs: Config, sitemap
Version notes and the manifest
DocFX writes manifest.json in the output. Since 2.81.0 it includes a docfx_version field (in this build
2.81.0+ba844df625370a6bd7c1ecab0d0ec4d1d9128ac4), and it also echoes the sitemap options, which makes it a convenient way
to check which configuration a deployed site was built with. The 2.81.0 release also added metadata.sourceLinkExclude;
2.80.1 made metadata generation stop when the restore fails. Custom template JavaScript is limited by timeouts and a statement cap
since 2.81.0, see Templates and Customization.
Errors and pitfalls
-
Invalid JSON. A missing brace gives a stack trace beginning
FatalError: System.Text.Json.JsonException: Expected depth to be zero at the end of the JSON payload. The first line names the JSON path and position. -
Unknown template. With the
templatekey set to a name that does not exist, the build still succeeded, with the warningsNo template bundles were found, no template will be applied to the documentsandUnknownContentTypeForTemplate. The output then contained no HTML pages (checked withfind), so treat these warnings as failures (the--warningsAsErrorsoption of the build command does that; see CLI; with the option the same build exited with code 255). -
Misspelled keys are ignored. An extra key named
templatesbesidetemplateraised no message. The official template page contains such a typo in one of its examples; the correct key istemplate. -
Missing
baseUrl. No sitemap and no message, as shown above. -
Included Markdown published twice. Files pulled in with
[!INCLUDE]should not be incontent, otherwise they are also built as pages. The example excludesincludes/**, and the included text still rendered insidearticles/dotnet/getting-started.html. -
Relative paths. Paths such as
filterConfig.ymlormeta/global.jsonare relative to the configuration file, not to the working directory. -
Output folder.
outputcan be overridden with-oon the command line; the build then wrote its site to that folder.