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, see outputFormat below). It is used by docfx 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 by docfx 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:

docfx.json
{
  "$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
  }
}

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

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" }
    ]
  }
}
Key Meaning

files

A glob or an array of globs. Relative to src when src is present, otherwise to the directory of docfx.json.

exclude

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).

src

The source directory, relative to docfx.json. It may point outside the project, for example ... The src prefix does not appear in the output URL.

dest

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"
  }
}

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

src

File mappings that select the inputs: .csproj projects, .sln solutions or source files, or assemblies (.dll).

dest, output

Output folder of the generated files, relative to docfx.json. The reference describes both names, and the command line option --output overrides or prefixes the value as that page states. The example above uses dest.

outputFormat

mref (default, ManagedReference YAML), apiPage (ApiPage YAML) or markdown.

filter

Path of a filter file whose apiRules hide APIs. disableDefaultFilter turns off the default filter.

properties

MSBuild properties used when reading project files, for example { "TargetFramework": "net8.0" }. When the input is source files only DefineConstants and AllowUnsafeBlocks are honoured, other properties are ignored silently.

noRestore

Skip dotnet restore. By default DocFX restores the projects and, since 2.80.1, stops when the restore fails.

references

Extra assembly references, used for assembly and source-file input (not for solution or project input).

namespaceLayout, categoryLayout, memberLayout

flattened or nested namespaces; flattened, nested or none categories (only for the apiPage and markdown formats); samePage or separatePages members.

enumSortOrder

alphabetic (default) or declaringOrder.

includePrivateMembers, includeExplicitInterfaceImplementations

Both default to false.

globalNamespaceId

Name used for the global namespace; empty by default.

allowCompilationErrors

Continue generation when the code does not compile.

shouldSkipMarkup

Do not render the triple-slash comments as Markdown.

codeSourceBasePath

Base directory for resolving <code source="..."> in XML comments.

disableGitFeatures

Disables the generation of View Source links.

sourceLinkExclude

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

content

Files transformed to HTML: Markdown articles, the YAML files produced by metadata, and toc.yml files.

resource

Files copied to the output unchanged: images, downloads, fonts. In the example images/logo.svg was copied to _site/images/logo.svg. Files referenced by a predefined metadata key such as _appLogoPath must be listed here.

overwrite

Conceptual Markdown files whose YAML header carries a uid. They add to or replace parts of the generated API pages. In the example, overwrite/converter.md (with a uid of PocketUnits.Converter and a summary header) replaced the summary of the Converter class page with its own text.

xref

One or more xref maps (a string or an array of strings: file paths or http, https and file URLs) used to resolve <xref:...> links to UIDs defined outside the project. See below.

groups

Maps a group name to an output folder ("groups": { "v1": { "dest": "output_dir_v1" } }).

Metadata, templates and output

Key Meaning

globalMetadata, globalMetadataFiles

Key-value pairs applied to every file, inline or loaded from JSON files.

fileMetadata, fileMetadataFiles

Per-key maps from glob patterns to values, inline or loaded from JSON files.

template

A template name or an array. Later templates override earlier ones when file names collide. When the key is omitted the embedded default template is used. The example uses ["default", "modern"], which layers the modern template over the default one. Template contents are covered in Templates and Customization.

theme

Extra style layers applied over the template, a string or an array. If omitted, no theme is applied.

output

Output folder of the site (_site in all examples). The command-line --output argument overrides it.

Processing

Key Meaning

markdownEngineProperties

Settings object for the Markdown engine. The documented use is { "markdigExtensions": ["FootNotes"] } to switch on extra Markdig extensions. Other settings, such as the custom alert definitions, are covered in Markdown.

postProcessors

An array of post processor names. The built-in HTML processor is always added, so an empty array is valid.

customLinkResolver

Name of an ICustomHrefGenerator class.

maxParallelism

Maximum parallelism; 0 (default) uses the number of CPU cores.

sitemap

Sitemap generation, described below.

disableGitFeatures

Skips fetching Git information for articles. Default false. Set it to true when that step is slow on a huge repository.

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 (and fileMetadataFiles), matched by glob;

  • globalMetadata (and globalMetadataFiles), applied to every file;

  • for toc.yml files, the metadata declared inside the TOC file.

flowchart LR FM["YAML front matter"] --> WIN["Value used"] FILE["fileMetadata"] --> WIN GLOB["globalMetadata"] --> WIN FM -. "beats" .-> FILE FILE -. "beats" .-> GLOB

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.

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

index.md

globalMetadata only

from globalMetadata

articles/python/intro.md

fileMetadata pattern articles/**.md

from fileMetadata (articles)

articles/dotnet/getting-started.md

two matching fileMetadata patterns

from fileMetadata (articles)

articles/dotnet/front-matter.md

front matter and fileMetadata

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.

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).

old/legacy.md
---
redirect_url: ../articles/dotnet/getting-started.html
---

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>

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 template key set to a name that does not exist, the build still succeeded, with the warnings No template bundles were found, no template will be applied to the documents and UnknownContentTypeForTemplate. The output then contained no HTML pages (checked with find), so treat these warnings as failures (the --warningsAsErrors option 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 templates beside template raised no message. The official template page contains such a typo in one of its examples; the correct key is template.

  • Missing baseUrl. No sitemap and no message, as shown above.

  • Included Markdown published twice. Files pulled in with [!INCLUDE] should not be in content, otherwise they are also built as pages. The example excludes includes/**, and the included text still rendered inside articles/dotnet/getting-started.html.

  • Relative paths. Paths such as filterConfig.yml or meta/global.json are relative to the configuration file, not to the working directory.

  • Output folder. output can be overridden with -o on the command line; the build then wrote its site to that folder.