Documentation Guidelines

The Apache Traffic Control documentation is written in RST and uses the Sphinx documentation build system to convert these into the desired output document format. This collection of guidelines does not aim to be a primer in RST, but merely a style guide regarding how the components of the document ought to be formatted and structured. It may also point out some features of the markup language of which a writer may not be aware.


This documentation uses the Sphinx documentation build system, and as such requires a Python3 version that is at least 3.4.1. It also has dependency on Sphinx, and Sphinx extensions and themes. All of these can be easily installed using pip by referencing the requirements file like so:

#120 Run from the Repository’s Root Directory
python3 -m pip install --user -r docs/source/requirements.txt

Once all dependencies have been satisfied, build using the Makefile at docs/Makefile.

Alternatively, it is also possible to Build Using pkg or to Build Using docker-compose, both of which will output a documentation “tarball” to dist/.


When writing documentation, the most important things to remember are:

  • Spell Check. Most text editors have this built-in (e.g. F6 in Sublime Text) or have plugins that will do this for you.

  • Proof-Read. Spell-checkers won’t catch grammatical errors or poor wording, so it’s very important to actually proof-read all documentation before submitting it in a Pull Request.

  • Make Sure the Documentation Actually Builds. Please actually verify the documentation not only builds, but builds correctly. That means there probably shouldn’t be any warnings, no malformed tables etc. and it also means that new documentation is actually accessible once built. It’s not enough to create a new something.rst file, that file must actually be linked to from some other, already included document. Some warnings may be considered acceptable, but do be prepared to defend them.

  • Traffic Ops UI is Dead. Do not ever create documentation that references or includes images of the Traffic Ops UI. That is officially dead now, and if the documentation being created is best made with references to a user-friendly UI, such references, examples and/or images should all be to/of Traffic Portal.


Whenever possible, avoid specifying manual line breaks, except as required by RST syntax. Extremely long lines will be wrapped by the user-agent, compiler, or output format as necessary. A single blank line may be used to separate paragraphs. This means that the ‘flow break’ character should never need to be used, i.e. no line in the documentation should ever match the regular expression ^\|$.


When using an abbreviation, acronym or initialism for the first time on a page, it must be named fully and followed by the abbreviation in parentheses e.g. “Fully Qualified Domain Name (FQDN)”. Strictly speaking, the best way to create an abbreviation is to always fully name it in parentheses immediately following the abbreviation using the :abbr: RST text role e.g. :abbr:`FQDN (Fully Qualified Domain Name)`, but it’s not reasonable to expect that of everyone. Some abbreviations can be assumed to be understood by the documentation’s target audience, and do not need full naming; they are general, basic networking and computing terms including (though not strictly limited to):

  • API

  • CSS

  • DNS

  • HTML

  • HTTP


  • IP/IPv4/IPv6

  • ISO

  • JPG

  • JSON

  • PDF

  • PNG

  • RPM

  • SQL

  • SSL

  • SVG

  • TCP

  • TLS

  • UDP

  • URL

  • URI

  • XML

  • YAML

Please do not abbreviate Traffic Control terms e.g. Cache Group, Delivery Service. See Terms for the proper way to use these terms.

Floating Objects

“Floating objects” are images, tables, source code listings, and equations. These may not be placed relative to other content exactly as shown in the source RST document, as it may be necessary to move them for e.g. page breaks in PDF documents so they are not split across pages.


Images should always be included inside of a .. figure directive. Always caption figures to make their purpose clear, as well as to make them directly link-able inside of the document and include them in figure listings. Though not syntactically required, figures should, in general be sized explicitly. The size should not be absolute, however; i.e. use 70% not 540px. Figures should, in general, be centered on the page. When drawings, graphs, or diagrams are included they should ideally be provided in both SVG and PNG formats, and included using globbing as filename.*. This will use the appropriate format for the output type.

Source Code Listings

Do not ever use the double-colon (:: ) directive to mark a section of text as a source code listing. This not only doesn’t support direct linking or provide a caption, but also uses the default “domain” - which is Python - for syntax highlighting. Instead, use .. code-block to include source code in the documentation. Source code must always be left-aligned, so do not provide any configuration options that would alter the default.

#121 Example Usage of the code-block Directive
.. code-block:: syntax
    :caption: A short, meaningful caption

    ``:linenos:`` is an optional field which will include line numbers in the listing. 'syntax'
    should be the name of a valid Pygments syntax.

Tables should be included in .. table directive bodies, never as a floating, block-quoted tabular environment. This ensures that all tables will be captioned, which makes their purpose clear and makes them directly link-able in the output as well as includes them in table listings. Tables should avoid wrapping lines until they reach 215 characters in width in the source reStructuredText document (including indention which should be counted as 4 characters per TAB). No table may ever exceed 215 characters in width. Tables should, in general be left-aligned (which is the default configuration). For the usage or command-line flags or options of a utility, use an “option list” or the .. program and .. option directives instead of a table.


Firstly, indentation of a text paragraph is rarely required. Doing so does not “link” the text with a heading in any way, text falls beneath a section or sub-section purely by being literally beneath that heading. When placing source code into a source code listing, any indentation may be used for the source code (typically should represent the actual preferred indentation of the code’s respective project were it included in the repository), but to avoid ambiguity in indentation used in the documentation versus indentation used in the source code, all documentation indentation should be done using one (1) TAB character and never spaces.


When making a list, consider first what kind of list it is. A list only needs to be enumerated if the enumeration has meaning e.g. a list of hierarchically ordered data or a sequential list of steps to accomplish a task or desired state. When enumerating list items, use #. instead of literal numbers, as this will enumerate automatically which makes modification of the list much easier at a later date. Unordered lists may use - or * for each item. Lists do not need to be indented beyond the current paragraph level. If a list is an unordered list of terms and their definitions, use a “definition list” instead of any other kind of list. If a list is a list of fields in a document or object, use a “field list” instead of any other kind of list. If a list is a list of parameters, arguments, or flags used by a command-line utility, use an “option list” instead of any other kind of list.

Notes and Footnotes

Instead of **NOTE** or similar, consider using the .. note directive, or one of the appropriate admonitions supported by RST:


The default admonition that calls attention to something without any specific semantics or attached context. Use when none of the others seem appropriate.


Includes cautionary information. Should be used when advising the reader that the containing section includes instructions or information that frequently confuse people/trip people up, and how to avoid these pitfalls.


Advises the reader of potential security risks or system damage that could occur as a result of following instructions in the containing section, or as a result of making assumptions about and/or improperly utilizing information in the containing section.


Denotes an error. This has limited uses in the ATC documentation.


Offers a hint to nudge readers in the direction of a solution. This has limited uses in the ATC documentation.


Contains information describing the details of an implementation of a feature described in the containing section. For an example, see the DSCP section of the Delivery Services page.


This is an extension provided by the ATC documentation build system, and will not appear in the Sphinx project documentation nor the reStructuredText standard.


Contains information that is important to consider while reading the containing section. Typically content that is related to a section’s content in an important way should appear as content of that section, but if a section is in danger of readers “skimming” it for information this can be useful to catch their eye.


Used to segregate content that is only tangentially related to the containing section, but is noteworthy nonetheless. Historically the most used admonition, containing caveats, exceptions etc.


Provides the reader with information that can be helpful - particularly to users/administrators/developers new to ATC - but not strictly necessary to understand the containing section.


Warns the reader about possible unintended consequences of following instructions/utilizing information in the containing section. If the behavior warned about constitutes a security risk and/or serious damage to one or more systems - including clients and origins - please use .. danger instead.

In a similar vein, instead of e.g. “(See also: some-link-or-reference)” please use the special .. seealso admonition. If the same admonition is required more than twice on the same page, it most likely ought to be a footnote instead. Footnotes should ideally use human-readable labels or, failing that, be labeled sequentially in the order of appearance. Footnotes should appear at the end of the major section in which they first or last appear. In practice, however, placement of the footnote is left to the writer’s discretion.

Section Headings

When deciding on the name of a section heading, it is important to select a name that both accurately reflects the content it contains and is suitable for reference later e.g. “Health Protocol” is good, but “Configuring Multi-Site Origin” as the title of a page which not only explains MSO configuration but also the concept is not good. Section headings follow a hierarchy, and for consistency’s sake should follow this particular hierarchy:

  1. Document title. There should only be one of these per page, and it should be the first heading on the page. This will also make the contained text the “Page Title” in HTML output (i.e. <title>Page Title</title> in the <head>).

    #122 Document Title
    Document Title
  2. Section header. This should represent a main topic of the page

    #123 Section Header
    Section Header
  3. Subsection header. This should represent a key piece of a main topic on the page

    #124 Subsection Header
    Subsection Header
  4. Sub-Subsection header. This represents a group of content logically separate from the rest of the subsection but still related to the content thereof. It is also acceptable to use this as an “aside” containing information only tangentially related to the subsection content.

    #125 Sub-Subsection Header
    Sub-Subsection Header
  5. Aside or Sub-Sub-Subsection header. This is the lowest denomination of header, and should almost always be used exclusively for “asides” which contain information only tangentially related to the sub-subsection content.

    #126 Aside

Section headings should always follow this order exactly, and never skip levels (which will generally cause a failure to compile properly). These can be thought of as the equivalents of the HTML tags <h1> through <h5>, respectively. Sectioning should never require more specificity than can be provided by an “Aside”. Please do not use bold text in lieu of a proper section heading. When referencing information in another section on the same page, please do not refer to the current placement of the referenced content relative to the referencing content. For example, instead of “as discussed below”, use “as discussed in Terms”.


Please always spell out the entire name of any Traffic Control terms used in the definition. For example, a collection of cache servers associated with a certain physical location is called a “Cache Group”, not a “CG”, “cachegroup”, “cache location” etc. A subdomain and collection of cache servers responsible collectively for routing traffic to a specific origin is called a Delivery Service”, not a “DS”, “deliveryservice” etc. Similarly, always use full permissions role names e.g. “operations” not “oper”. This will ensure the Glossary is actually helpful. To link a term to the glossary, use the :term: role. This should be done for virtually every use of a Traffic Control term, e.g. :term:`Cache Group` will render as: Cache Group. Generally speaking, be wary of using the word “cache”. To most people that means the actual cache on a hard disk somewhere. This word is frequently confused with ” cache server”, which - when accurate - is always preferred over “cache”.

Documenting API Routes

Follow all of the formatting conventions in Formatting. Maintain the structural format of the API documentation as outlined in the Traffic Ops API section. API routes that have variable paths e.g. profiles/{{ID}} should use mustache templates not the Mojolicious-specific :param syntax. This keeps the templates generic, familiar, and reflects the inability of a request path to contain procedural instructions or program logic. Please do not include the /api/2.x/ part of the request path for Traffic Ops API endpoints. If an endpoint is unavailable prior to a specific version, use the .. versionadded directive to indicate that version. Likewise, do not make a new page for an endpoint when it changes across versions, instead call out the changes using the .. versionchanged directive. If an endpoint should not be used because newer endpoints provide the same functionality in a better way, use the .. deprecated directive to link to them and explain why they are better.

When documenting an API route, be sure to include all methods, request/response JSON payload fields, path parameters, and query parameters, whether they are optional or not. When describing a field in a JSON payload, remember that JSON does not have “hashes” it has “objects” or even “maps”. When documenting path parameters such as Profile ID in profiles/{{ID}}, consider that the endpoint path cannot be formed without defining all path parameters, and so to label them as “required” is superfluous.

The “Response Example” must always exist. “TODO” is not an acceptable Response Example for new endpoints. The “Request Example” must only exist if the request requires data in the body (most commonly this will be for PATCH, POST and PUT methods). It is, however, strongly advised that a request example be given if the endpoint takes Query Parameters or Path Parameters, and it is required if the Response Example is a response to a request that used a query or path parameter. If the Request Example is present, then the Response Example must be the appropriate response to that request. When generating Request/Response Examples, attempt to use the CDN in a Box environment whenever possible to provide a common basis and familiarity to new users who likely set up “CDN in a Box” as a primer for understanding CDNs/Traffic Control. Responses are sometimes hundreds of lines long, and in those cases only as much as is required for an understanding of the structure needs to be included in the example - along with a note mentioning that the output was trimmed. Also always attempt to place structure explanations before any example so that the content of the example can be understood by the reader (though in general the placement of a floating environment like a code listing is not known at compile-time). Whenever possible, the Request and Response examples should include the complete HTTP stack, which captures behavior like Query Parameters, Path Parameters and HTTP cookie operations like those used by e.g. logs. A few caveats to the “include all headers” rule:

  • The Host header ought to reflect the actual hostname of the Traffic Ops server - which should be “trafficops.infra.ciab.test” for the CDN in a Box environment. This can be polluted when requests are made to a remotely running CDN in a Box on a different server.

  • The “mojolicious” cookie is extremely long and potentially insecure to publicly show. As such, a placeholder should be used for its value, preferably “…”.

  • The Content-Type header sent by curl(1) (and possibly others) is always application/x-www-form-urlencoded regardless of the actual content (unless overridden). Virtually all payloads accepted by the API must be JSON, so this should be modified to reflect that when appropriate e.g. application/json.

  • API output is often beautified by inserting line breaks and indentation, which will make the Content-Length header (if any) incorrect. Don’t worry about fixing that - just try to leave the output as close as possible to what will actually be returned by leaving it the way it is.

File names should reflect the request path of the endpoint, e.g. a file for an endpoint of the Traffic Ops API /api/4.0/foo/{{fooID}}/bar/{{barID}} should be named foo_fooID_bar_barID.rst. Similarly, reference labels linking to the document title for API route pages should follow the convention: <component>-api-<path> in all lowercase where <component> is an abbreviated Traffic Control component name e.g. to and <path> is the request path e.g. foo_bar. So a label for an endpoint of the Traffic Ops API at /api/4.0/foo_bar/{{ID}} should be to-api-foo_bar-id.


The ATC documentation provides an extension to the standard roles and directives offered by Sphinx, located at docs/source/_ext/ It provides the following roles and directives:


An admonition directive used to contain implementation-specific notes on a subject.

#127 Example impl-detail usage
.. impl-detail:: Implementation-specific information here.

This example usage renders like so:

Implementation Detail

Implementation-specific information here.


Creates a link to the specified file on the master branch of the ATC repository. For example, “:atc-file:`docs/source/development/documentation_guidelines`” renders as a link to the source of this documenting section like so: docs/source/development/documentation_guidelines. You can also link to directories as well as files.


A text role that can be used to easily link to GitHub Issues for the ATC repository. For example, “:issue:`1`” renders as: Issue #1.


A text role that can be used to easily link to GitHub Pull Requests for the ATC repository. For example, “:pr:`1`” renders as Pull Request 1.


A synonym for pr


A text role that can be used to easily link to the documentation for any Go package, type, or function/method (grouped constants/variables not supported). For example, “:godoc:`net/http.HandlerFunc`” renders as net/http.HandlerFunc.


This is provided for convenience, and is identical to :godoc: except that it is assumed to be relative to the Apache Traffic Control project. For example, :atc-godoc:`lib/go-rfc.MimeType.Quality` renders as


This is provided for convenience, and is identical to :godoc: except that it is assumed to be relative to the package. For example, :to-godoc:`api.APIInfo` renders as