Pre-generated dumps
Your docs site is a Node project, and you don’t want to add a Python toolchain to build it.
griffe dump writes the whole API surface of a package to one JSON file. The plugin can read that
file instead of running Griffe. The build machine then needs no uv, no interpreter, and no Python
at all. The Python project produces the file, and the docs site only reads it.
This method also works for a package with an environment that is hard to reproduce, for example one with compiled extensions, private dependencies, or a pinned Python version. It is also how versioned documentation freezes the API surface of a release.
What a dump costs you
Section titled “What a dump costs you”A dump is a snapshot. The docs build cannot refresh it. The pages describe the API as it was when
you wrote the file, until something writes a new one: a release workflow, a scheduled job, or you at
the keyboard. For a pinned release, that is exactly what you want. For a dump that tracks main, it
will go stale without warning.
Three things change at build time:
- Griffe never runs, so the options that configure it (
docstringStyle,docstringOptions,extensions, andforceInspection) have no effect on a package with asource. Set them in the command that produces the dump instead. Member filters, source links, the sidebar, and search still apply, because these are rendering concerns. - There are no Python files to watch, so
astro devdoes not reload when you regenerate a dump. Restart the dev server. versions: { refs }(version annotations) extracts each ref from a git checkout, so you cannot combine it withsource. The plugin throws an error telling you to document that release as its ownpackagesentry.
Generate, publish, point the config at it
Section titled “Generate, publish, point the config at it”-
Extract the API surface in the Python project, running from the repository root:
Terminal window uvx --from griffe griffe dump -f -d google --search src mypkg -o api.jsonYou need both
-fand-d. Griffe does not warn you if you leave either one out. See the command in detail. -
Publish the file where the docs build can read it. Dumps are read-only build inputs and compress well, so a release asset is enough:
.github/workflows/api-dump.yml name: Publish API dumpon:release:types: [published]permissions:contents: writejobs:dump:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v7- uses: astral-sh/setup-uv@v7- name: Extract the API surfacerun: uvx --from griffe griffe dump -f -d google --search src mypkg -o api.json- name: Attach it to the releaseenv:GH_TOKEN: ${{ github.token }}run: gh release upload "${{ github.event.release.tag_name }}" api.json -
Point the package entry at the published URL:
astro.config.mjs starlightPydocs({packages: [{name: 'mypkg',source: { url: 'https://github.com/you/mypkg/releases/download/v2.1.0/api.json' },},],});
Point at a tag for a pinned version. Or upload to a stable location, such as an S3 bucket, a
latest release, or a file on gh-pages, and let revalidation keep the site current.
Downloads and the cache
Section titled “Downloads and the cache”url must be an http(s) URL. The plugin caches the download under cacheDir
(node_modules/.astro by default), together with the ETag and Last-Modified headers the server
sent. The cache option decides what the next build does with it:
cache |
Behaviour |
|---|---|
'revalidate' |
Default. Sends If-None-Match / If-Modified-Since; a 304 reuses the cached copy. |
'force' |
Never contacts the server when a cached copy exists. Fastest, and offline-safe. |
'bypass' |
Downloads on every build. |
If the host is unreachable, or answers with an error, and a cached copy exists, the build logs a warning and uses the cached copy. A documentation build should not fail just because a release asset was briefly unavailable. With no cached copy, the build fails, and the error message names the URL and the status.
Committing the dump instead
Section titled “Committing the dump instead”Ship the dump inside the docs repository. The build then touches no network, and you can review the change in a pull request:
starlightPydocs({ packages: [{ name: 'mypkg', source: { file: './dumps/mypkg.json' } }],});The plugin resolves file relative to the Astro project root. A missing file fails the build, and
the message names the path it looked for. A dump is a large JSON file, so expect noisy diffs. If
your repository cannot tolerate that, use the URL form instead.
Extraction order
Section titled “Extraction order”The plugin gets a dump in a fixed order: an explicit runner.command first, then a source dump,
then uvx --from griffe, then python -m griffe. A runner.command therefore beats source. If
you set one globally, every package runs it, including packages that carry a source.
The command in detail
Section titled “The command in detail”Without uvx, when griffe is already installed:
griffe dump -f -d google --search src mypkg -o api.jsonThis is exactly what the plugin runs for itself. The flags:
-f(--full) adds file paths, line numbers, and visibility flags. Source links, member filtering, and provenance all need this data. Without-f, every object arrives as a bare stub.-d <style>parses docstrings into structured sections. Set<style>togoogle,numpy,sphinx, orauto. Without-d, a docstring stays one raw string, and the plugin cannot render a parameter table, returns block, or admonition.--search(-s) points at the directory containing the package, and can be repeated.-owrites the JSON to a file. Without it, griffe writes to standard output.
Add the flags your package needs, and keep them in step with what the docs site expects to render.
A pydantic model layer needs the Griffe extension installed alongside Griffe (--with) and enabled
(-e). -D takes parser options as JSON:
uvx --with griffe-pydantic --from griffe griffe dump -f -d google \ -D '{"returns_named_value": false}' -e griffe_pydantic --search src mypkg -o api.jsonSource links with a dump from elsewhere
Section titled “Source links with a dump from elsewhere”Griffe builds source links from the paths it recorded, which are relative to the directory where
griffe ran. Run the dump command from the repository root, and {path} is already
repository-relative. This is what a forge URL needs:
starlightPydocs({ packages: [ { name: 'mypkg', source: { url: 'https://…/v2.1.0/api.json' },
// No root: the paths in the dump are already // relative to the repository. sourceLink: { host: 'github', repo: 'you/mypkg', ref: 'v2.1.0', }, }, ],});Do not set sourceLink.root for a dump produced on another machine. The plugin applies root to
the absolute path griffe recorded, and that path belongs to the CI runner, so it means nothing
locally. root is for the case where extraction runs on this machine and the sources sit outside
the Astro project. See Source links.
Griffe’s own source_link is another option. Griffe 2 records a commit-pinned blob URL for each
object when it runs inside a git checkout. A dump made in CI often carries working links with no
sourceLink configuration at all.
Checking a dump
Section titled “Checking a dump”A dump is an object keyed by package name, with the whole tree underneath:
jq 'keys' api.json # ["mypkg"]jq '.mypkg.members | keys' api.json # the top-level surfacejq '.mypkg.members.Report.docstring.parsed[0].kind' api.json # "text" if -d ranIf docstring.parsed is missing, the dump was made without -d. The pages will then carry
signatures with no parameter tables or admonitions. If objects have no filepath, the dump was made
without -f. Source links and the visibility-based member filters then have nothing to work from.
The plugin cannot detect either problem for you: both only produce thinner pages, not a failed
build. Check a dump the first time a new pipeline produces one. A file that is not a griffe dump, or
does not contain the configured package, does fail the build. The error names the file and lists
what the dump does contain.