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 converted with an older Documenteer may not have the target yet; documenteer technote update adds it, rewriting the Makefile and tox.ini that provide it (see Update a technote).

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 update 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 when it writes the file.

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. The canonical URL is written in the same normalized form the technote’s own pages publish — a bare host such as https://sqr-000.lsst.io gains the trailing slash — so CITATION.cff and the page state the technote’s location the same way.

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 — 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. The command says so whenever it writes the file, or reports it stale. technote.date_created is the day the technote was started, not the day it was released, and is never used for the citation.

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. A check that finds the file current is silent: it reports nothing about the metadata the file had to do without, because it wrote no file to do without it.

This is the mechanism to keep the file current: run it where the technote is built anyway, and a metadata or title change that was not synced fails with the command to run. The technote’s own repository already runs it: make lint — or tox run -e technote-lint directly — runs this check right after documenteer technote lint, so whatever runs the repository’s lint target enforces the file.

Rubin’s shared technote workflow does not run the check itself: it runs the Pre-commit hooks, the build, and the upload. A repository that relies on that workflow alone is therefore not yet checked in CI; adding the check there is tracked in rubin-sphinx-technote-workflows#12.

documenteer technote lint reports the same staleness as TN106, using this same comparison, so the two commands the lint target runs never disagree about whether the file is stale.