Tech writer at work blog.

Living and writing documentation at Documatt, small team of programmers that write documentation too.

Best Sphinx tips

Over the years writing documentation in Sphinx, I found I do the same tweaks in every Sphinx project's again and again. Here are the best ones.

Most developers have the same first new year's todo: update the year in copyright in all their apps and webs.

-2020, Documatt
+2021, Documatt

You don't have to be one of them! Because is regular Python file, import datetime from the standard library, and use it to obtain current year:

from datetime import date


copyright = f'{}, Documatt'

Every time you rebuild the project, the current year will be used.

Repeating text snippets

How many times do you type project name in the project documentation? What if the project has to be renamed or use new spelling (e.g., "MyProject" vs. "myProject")? As every programmer I hate repeating things. Constants like project name are ideal candidate to be available from every project document.

In Sphinx, you can append/prepend any markup with rst_epilog or rst_prolog options. List your common words or sentences as substitution definition in one of them. For example, project name from the project option and commonly used text snippets:

rst_epilog = f'''
.. |project| replace:: {project}
.. |dfb| replace:: Don't forget to backup before proceeding.

and use it anywhere in the docs:


In the current release of |project| you have to update dependencies. |dfb|


Remove "documentation" from the page title

By default, generated HTML <title> has the value {project} {release} documentation. E.g. Tech writer at work 1.0 documentation.

If you don't have's release set, it is e.g., Tech writer at work documentation (please note two spaces among "work" and "documentation").

If you don't like word "documentation" or two-space issue, you have to set custom title in html_title option. For example, let's set it to the same value as a project option.

project = 'Tech writer at work blog'


html_title = project

Turn off or set different default syntax highlighting

Code examples are highlighted by default syntax highlight language, if not configured otherwise for a particular example. Sphinx default syntax highlighting mode is 'python3'.

Python3 highlighting:


    def name():

Also Python3 highlighting:

.. code-block::

   from datetime import date
   copyright = f'{}, Documatt'

Maybe as Sphinx is mainly used in Python projects, it is reasonable value, but I personally almost always change it to 'none' that turns off syntax highlighting

highlight_language = 'none'

... until I set it for a particular code-block:::

If you want different highlighting, you have to se it manually:

.. code-block:: javascript

   for (let i = 0; i < 3; i++) {        // shows 0, then 1, then 2

Disable primary domain

Another Sphinx default variable aimed toward documenting Python code is primary_domain. Its default value is py, a Python code documenting. I recommend to turn it off to None, i.e. you will always have to specify a domain.

primary_domain = None

Quick recap on domains

Domain is a way to group related roles and directives with prefix to don't pollute "global" namespace. E.g. builtin py domain, aimed to document Python code, contains directive called function to describe a Python function. If no default domain is set, you will have to use py:function to call it:

.. py:function:: lumache.get_random_ingredients(kind=None)

   Return a list of random ingredients as strings.

   :param kind: Optional "kind" of ingredients.
   :type kind: list[str] or None
   :return: The ingredients list.
   :rtype: list[str]

For referencing previously listed object, there are corresponding roles. E.g., to make a link to a function, you use a function role. If no default domain is set, role name needs to be py:function.

The ``kind`` parameter should be either ``"meat"``, ``"fish"``,
or ``"veggies"``. Otherwise, :py:func:`lumache.get_random_ingredients`
will raise an exception

Be nitpicky


Sphinx contains less known option called nitpicky. When it is true, it will turn on warn about all invalid references. Sadly, by default it is false.

If there is no target settings defined, but referred:

Please see :ref:`settings` for details.

you are not warned about it by default! With nitpicky = True:

/path/to/document.rst:1036: WARNING: undefined label: settings

nitpicky = False also suppress non-existing target warnings used in :py:class:, :js:func: and all other similar referencing roles.



It is not, nitpicky_ignore, but nitpick_ignore.

Close relate option is nitpick_ignore which fine-tune warnings you intentionally want to suppress. It is list of (type, target) tuples, where type is a role name (including domain) which causes the warning.

For example, when I document the following JavaScript function that accept one string parameter:

.. js:function:: encodeURIComponent(uri)

   Encodes passed URI to include characters safe URI only.

   :param string uri: URI to encode.

Sphinx is nice and will warn me I forget to define a string type:

/path/to/document:939: WARNING: js:func reference target not found: string

To suppress warnings about these builtin types, configure nitpick_ignore like this

nitpick_ignore = [
   ('js:func', 'string'),
   ('js:func', 'boolean'),
   # ...


There is also nitpick_ignore_regex works similar way, but decides whether to warn based on regular expressions.