Generating a CITATION.cff#

A technote is a citable document: it has a DOI, authors with ORCIDs, a publisher, and a handle like SQR-000. GitHub surfaces that citation through a CITATION.cff file at the repository’s root — the “Cite this repository” button in the sidebar.

Documenteer generates that file from technote.toml and the technote’s own document, so the citation GitHub shows is the same metadata the technote itself is published with.

documenteer technote sync-cff

Run the command from the technote’s repository root, or point it elsewhere with the -d/--dir option. The command builds the technote to read its title, so it needs the technote extra — pip install documenteer[technote], which a technote’s requirements.txt declares anyway.

A technote’s own tooling runs it for you, alongside make sync-authors:

make sync-cff

That target runs the command inside the same tox environment make html builds the technote in, so a technote you can build is one you can sync. Technotes created or migrated with an older Documenteer may not have the target yet; Migrate legacy reStructuredText/Sphinx technical notes writes the Makefile and tox.ini that provide it.

technote.toml is the canonical source#

CITATION.cff is fully managed: every run regenerates it from scratch, and the generated file says so in a comment on its first line. To change the citation, edit technote.toml and run the command again — an edit made directly to CITATION.cff is lost on the next sync.

The one field technote.toml does not usually supply is the title: a technote is titled by its document’s top-level heading unless the [technote] table declares a title, and documenteer technote migrate never writes one. The command therefore builds the technote with Sphinx — quietly, writing nothing, in a temporary directory — and takes the title from the document Sphinx read, so CITATION.cff names the technote the same way the published page does. A technote-series repository with no conf.py is not built by Sphinx, and is generated from technote.toml alone.

Generation is deterministic. The same technote.toml and the same document always produce byte-identical output, so re-running the command on an up-to-date file changes nothing at all. Nothing in the generated file comes from the clock or from the network: in particular the release date is read from technote.toml, never defaulted to the day the file was generated.

What gets generated#

The Citation File Format allows only software or dataset as a file’s top-level type, and a technote is neither. The top level is therefore a stub describing the repository, and the technote itself is the file’s preferred-citation — a report reference, which is what GitHub renders and what carries the technote’s handle and publishing institution. The DOI and the release date are written in both places: not every tool reads preferred-citation, and one that cites only the top-level record should still get a dated, identified citation.

CITATION.cff#
# Generated by documenteer technote sync-cff from technote.toml — do not edit
cff-version: 1.2.0
message: If you use this technote, please cite it using the metadata from this file.
title: The LSST DM Technical Note Publishing Platform
type: software
authors:
  - family-names: Sick
    given-names: Jonathan
    orcid: https://orcid.org/0000-0003-3001-676X
    affiliation: Rubin Observatory Project Office
repository-code: https://github.com/lsst-sqre/sqr-000
url: https://sqr-000.lsst.io/
doi: 10.71929/rubin/2570308
date-released: 2026-08-24
preferred-citation:
  type: report
  title: The LSST DM Technical Note Publishing Platform
  authors:
    - family-names: Sick
      given-names: Jonathan
      orcid: https://orcid.org/0000-0003-3001-676X
      affiliation: Rubin Observatory Project Office
  institution:
    name: Vera C. Rubin Observatory
  number: SQR-000
  doi: 10.71929/rubin/2570308
  url: https://sqr-000.lsst.io/
  date-released: 2026-08-24

Each field is read from technote.toml, except the title:

title

technote.title, or — as is normal, since technote.toml usually declares no title — the top-level heading of the technote’s own document, read by building it. A technote that has a title in neither place is cited by its ID, and the command says so.

authors

The [[technote.authors]] entries, in order. An author’s orcid is written as an orcid.org URL however technote.toml spells it, and the first of their [[technote.authors.affiliations]] supplies the affiliation — the Citation File Format records one affiliation per person.

number

technote.id, the technote’s handle within its series.

doi

technote.doi, normalized to its bare 10.NNNN/suffix form, on both the top level and the preferred citation. A technote that has no DOI yet still generates a valid file; the doi field is simply omitted.

institution

technote.organization.name, the organization that publishes the series.

url and repository-code

technote.canonical_url and technote.github_url.

date-released

technote.date_updated, the day the technote was last published, written on both the top level and the preferred citation. A technote that declares no date_updated generates a file with no date-released at all, and the command says so — the Citation File Format requires the field at neither level, so an undated technote is written as undated rather than as dated to a day nobody published on. technote.date_created is the day the technote was started, not the day it was released, and is never used for the citation. The citation the technote’s own pages display follows the same rule; see Technotes with no date.

See also

Maintaining author metadata for keeping the [[technote.authors]] entries in sync with Rubin’s author database, which is where the ORCIDs and affiliations come from.

Checking the file in CI#

The --check option compares the file on disk against what the technote generates, without writing anything:

documenteer technote sync-cff --check

It exits non-zero only when CITATION.cff exists and is stale. A repository with no CITATION.cff has simply not adopted the file, and passes — before the technote is built at all, so a repository that never opted in is not failed by a document Sphinx cannot read.

This is the mechanism to keep the file current: run it in CI, where the technote is built anyway, and a metadata or title change that was not synced fails the build with the command to run. Rubin’s shared technote workflow runs it for you.

documenteer technote lint reports the same staleness as TN106, using this same comparison, so a technote’s CI catches an unsynced file whether it runs the linter, this check, or both.