Table of Contents

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 (the latest release, published 2026-09-25) and checked on 2026-10-26. A table of contents (TOC) tells DocFX how documents are grouped and ordered, which tree is shown in the sidebar of a page and what the navigation bar at the top contains. The examples use the Pocket Units library and were built with DocFX 2.81.0 in the mcr.microsoft.com/dotnet/sdk:10.0 Docker image, with the default and modern templates combined.

What a TOC is and why it exists

DocFX does not infer navigation from the folder layout. Every site needs at least one TOC file, normally named toc.yml, that lists the pages in the order the reader should see them. The build turns each TOC into a toc.json file next to the pages (plus a toc.html when the default template is part of the build), and writes two metadata tags into every page: docfx:tocrel points to the TOC that belongs to that page and docfx:navrel points to the TOC that fills the navigation bar.

The same file type serves three purposes, and which one a file plays depends only on where it is and how other TOCs link to it:

  • a sidebar tree for a group of pages, such as the guides or the API reference;

  • a fragment that other TOCs embed (a nested TOC), so one list is maintained once;

  • the root toc.yml next to docfx.json, which becomes the top navigation bar.

Root toc.yml pointing to a guides TOC and an API TOC, and the guides TOC nesting a reusable fragment

The figure shows the files of the example site: the root TOC links to the folders guides/ and api/ with reference entries, and guides/toc.yml embeds a reusable fragment with a nested entry. The API TOC is generated by docfx metadata (see .NET API docs).

The YAML format

A TOC is a YAML tree of nodes. The root can be a list of nodes or a mapping with an items list; the mapping form is needed when the file carries its own properties such as order. The official page documents these node properties:

Key Meaning

name

Display text of the node. It is optional: when omitted, DocFX uses the title metadata or the first level 1 heading of the referenced article, or the name of the API item for a uid.

href

Where the node leads: a file path relative to the TOC file, an absolute URL, another TOC file or a folder ending in a slash. It is optional, because a node can exist only to group other nodes.

items

The children of the node.

uid

The UID of an article or API item, used instead of href. DocFX looks up the page that owns the UID and links to it.

expanded

Shows the children when the page loads. It works only with the modern template.

The example below is the sidebar of the Pocket Units guides. It uses every node form: a plain page, a group with an expanded subtree, a nested TOC, a node with only a uid, and a group without a link.

guides/toc.yml
items:
- name: Getting started
  href: getting-started.md
- name: Conversions
  expanded: true
  items:
  - href: lengths.md
  - name: Rounding rules
    href: rounding.md
- name: API types
  href: reference/toc.yml
- uid: PocketUnits.Converter
- name: Release notes

Building the site produces this guides/toc.json, formatted here for reading:

{
  "items": [
    { "name": "Getting started", "href": "getting-started.html", "topicHref": "getting-started.html" },
    {
      "name": "Conversions",
      "expanded": true,
      "items": [
        { "name": "Lengths", "href": "lengths.html", "topicHref": "lengths.html" },
        { "name": "Rounding rules", "href": "rounding.html", "topicHref": "rounding.html" }
      ]
    },
    {
      "name": "API types",
      "includedFrom": "~/guides/reference/toc.yml",
      "items": [
        { "name": "Converter", "href": "../api/PocketUnits.Converter.html", "topicUid": "PocketUnits.Converter" },
        { "name": "LengthUnit", "href": "../api/PocketUnits.LengthUnit.html", "topicUid": "PocketUnits.LengthUnit" }
      ]
    },
    { "name": "Converter", "href": "../api/PocketUnits.Converter.html", "topicUid": "PocketUnits.Converter" },
    { "name": "Release notes" }
  ]
}

Source: output of docfx docfx.json (DocFX 2.81.0); the topicHref entries of the API nodes were left out of the listing to keep it short.

What this output shows:

  • href values are written relative to the TOC file and rewritten to the output file names (.md becomes .html).

  • Lengths has no name in the source; DocFX took the heading Lengths from lengths.md.

  • The node with only uid: PocketUnits.Converter got its name Converter and its link from the API page.

  • Release notes has neither href nor items: it is rendered as a label without a link.

  • The nested TOC is embedded with a marker, includedFrom, that records which file supplied the items.

  • Properties that DocFX does not know are not rejected. A node written with a misspelled key such as expand: true was copied to the output as it is and had no effect, and no warning was printed.

Markdown TOCs

DocFX 2.81.0 also reads a TOC written as a Markdown file named toc.md, where headings give the nesting level and each heading holds a link. The official TOC page documents only the YAML form, so prefer toc.yml for new sites.

mdtoc/toc.md
# [Intro](intro.md)
## [Sub page](sub.md)
## [Docs site](https://example.org/docs)

Source: the DocFX reader for Markdown TOCs, MarkdownTocReader.cs

The build of this file produced one top node Intro with two children, Sub page and the external Docs site, with the same JSON structure as a YAML TOC. A line that does not match the supported patterns stops the build with an Invalid toc file error that names the line.

Which TOC does a page show

Every page is associated with one TOC. The rule from the official page is:

  • If exactly one TOC lists the page through href, that TOC is shown.

  • If several TOCs list the page, or none lists it, DocFX picks the TOC that is the nearest by the number of directory jumps.

  • The property order at the top of a TOC file overrides that pick: TOCs with a smaller order are tried first. The default order is 0.

  • Nested TOCs get order: 100 by default, so a TOC that embeds them wins over them.

flowchart TD A["Page P"] --> B{"Listed by exactly one TOC?"} B -->|yes| C["Use that TOC"] B -->|"no: several or none"| D["Sort candidate TOCs by order, smallest first"] D --> E{"Tie on order?"} E -->|no| F["Use the lowest order"] E -->|yes| G["Use the nearest TOC by directory jumps"]

The decision above is a reading of the official text, not an additional rule from the source code. The effect was checked on the example site. The API pages PocketUnits.Converter.html are listed both by api/toc.yml and by guides/toc.yml (through the uid node and through the nested fragment). In the default build the page picked the nearest TOC:

<meta name="docfx:tocrel" content="toc.html">

Source: api/PocketUnits.Converter.html, generated by DocFX 2.81.0.

After adding order: -1 as the first line of guides/toc.yml, the same page pointed to the guides TOC:

<meta name="docfx:tocrel" content="../guides/toc.html">

Source: api/PocketUnits.Converter.html, generated by DocFX 2.81.0 after the change.

The namespace page api/PocketUnits.html kept toc.html, because only api/toc.yml listed it. A TOC with order therefore changes the sidebar of every page it lists, not only of one page.

Nested TOCs

To include one TOC in another, set href of a node to the path of a toc.yml file. The items of that file are placed under the node. This is also the way to reuse a list in several TOC files.

guides/reference/toc.yml
items:
- name: Converter
  uid: PocketUnits.Converter
- name: LengthUnit
  uid: PocketUnits.LengthUnit

Together with the entry href: reference/toc.yml in guides/toc.yml, this renders the node API types with the two children shown in the JSON above. The generated guides/reference/toc.json carries an order of 100, the default order of a nested TOC.

Reference TOCs

A reference TOC links to another TOC without copying its items. Set href to a folder and end the value with /. The node becomes a link to the first article of the TOC in that folder, and that folder’s TOC is the one that appears in the sidebar once the reader opens the page. Reference TOCs suit entries that lead to independent sections:

- name: System
  href: System/
- name: System.Collections
  href: System.Collections/

If the node should open a different page than the first article, the data model also has a topicHref property. It was not documented on the official TOC page, so the following was only tried, not specified: a node with href: reference/ and topicHref: lengths.md produced the output keys href with the value lengths.html and tocHref with the value reference/toc.html in guides/toc.json, so the link opens lengths.html while the sidebar comes from reference/toc.yml.

The root TOC as navigation bar

The toc.yml that sits in the same folder as docfx.json fills the navigation bar at the top of every page. It normally uses reference TOCs, so each entry opens a section with its own sidebar. This is the root TOC of the example site; it also shows that an absolute URL is a valid href:

toc.yml
- name: Guides
  href: guides/
- name: Reference
  href: api/
- name: Source
  href: https://github.com/example/pocket-units

The generated root toc.json resolved the two folders to their first articles and linked every page to it through docfx:navrel:

{"items":[
  {"name":"Guides","href":"guides/getting-started.html","tocHref":"guides/toc.html","topicHref":"guides/getting-started.html"},
  {"name":"Reference","href":"api/PocketUnits.html","tocHref":"api/toc.html","topicHref":"api/PocketUnits.html"},
  {"name":"Source","href":"https://github.com/example/pocket-units","topicHref":"https://github.com/example/pocket-units"}
]}

Source: root toc.json generated by DocFX 2.81.0.

The navigation bar can be switched off for the whole site or a page with the template metadata _disableNavbar, and the sidebar tree with _disableToc. Both are described in the docfx.json reference and belong to the template settings covered in Templates and Customization.

Expanding nodes

expanded: true asks the template to show a node’s children when the page opens. The official page states that it works only with the modern template. The key is carried to toc.json (as in the example above), but it is the template’s JavaScript that acts on it. The toc.html produced by the default template for the same file showed the group Conversions with its children in the markup and no expanded marker. This agrees with the documented limit; no browser was used to compare the two renderings visually.

The script of the modern template also marks the ancestors of the current page as expanded when the page loads, so expanded is mostly useful for sections that should be visible from the landing page.

TOCs generated from .NET code

docfx metadata writes its own TOC next to the API YAML files. For Pocket Units it produced api/toc.yml with the namespace and its types:

### YamlMime:TableOfContent
items:
- uid: PocketUnits
  name: PocketUnits
  type: Namespace
  items:
  - uid: PocketUnits.Converter
    name: Converter
    type: Class
  - uid: PocketUnits.LengthUnit
    name: LengthUnit
    type: Enum
memberLayout: SamePage

Source: output of docfx metadata (DocFX 2.81.0).

The shape of this TOC is controlled by docfx.json options of the metadata section: namespaceLayout (flattened by default, or nested), categoryLayout (flattened, nested or none; valid for the apiPage and markdown output formats only) and memberLayout. They are described in .NET API docs. Do not edit the generated file by hand; reference its folder from a hand-written TOC instead, as the root TOC above does with api/.

TOC metadata

A TOC file is a document too, so metadata can be set for it. The precedence is fileMetadata first, then keys written in the toc.yml file itself, then globalMetadata. This lets a build override a setting of a generated TOC. The PDF properties pdf, pdfFileName, pdfCoverPage and pdfTocPage are set this way; see PDF Output. The mapping rules for docfx.json are in docfx.json.

Errors and warnings

TOC files are part of the build, so they must be in the build.content file list (the example lists toc.yml and guides/**/toc.yml); a TOC that the file list does not match is not processed. Broken entries are reported as warnings; these are the messages DocFX 2.81.0 printed when guides/toc.yml contained a missing file and an unknown UID:

/work/guides/toc.yml(0,1): warning InvalidFileLink: Invalid file link:(~/guides/nope.md).
/work/guides/toc.yml: Unable to find file "nope.md" for Href referenced by TOC file "guides/toc.yml"
/work/guides/toc.yml: Unable to find file "nope.md" for TopicHref referenced by TOC file "guides/toc.yml"
/work/guides/toc.yml: warning UidNotFound: Unable to find file with uid "No.Such.Uid" referenced by TOC file "guides/toc.yml"

Source: output of docfx docfx.json (DocFX 2.81.0).

The build still succeeded with 2 warnings. The broken node is kept in the output with its unresolved href for the missing file, and the node with the unknown UID appears without a name or link. Use --warningsAsErrors in continuous integration (see CLI) to turn such warnings into failures.

Pitfalls

  • href is relative to the TOC file that contains it, and the official page requires a trailing slash on a folder reference.

  • A folder reference (guides/) needs a toc.yml in that folder; the generated link is the first article of that TOC.

  • Do not list the same page in several unrelated TOCs unless you set order; the nearest TOC is used otherwise, which can change when files are moved.

  • The modern template is required for expanded. For the other template keys, a file in the wrong template folder silently does nothing (see Templates and Customization).

  • Unknown keys are copied as they are and never reported, so a typo in a key is not detected by the build.

  • An href to an article does not provide the article’s UID. Use uid when links should survive file moves, and see Links and Cross References for how UIDs are resolved.

The C# conventions for XML documentation comments, which feed the API TOC, are covered in C# coding conventions and documentation; the build tooling around them is in C# build and tooling, and the Visual Basic equivalent in Visual Basic XML documentation.