Griffonner¶
Template-first Python documentation generator that gets out of your way.
From French “griffonner” (to scribble/draft) - because Griffe finds it, you sketch it out
Overview¶
Griffonner uses Griffe to parse Python code and Jinja2 templates to generate documentation in any format. It has zero opinions about output structure - you control everything through templates.
Core flow: Python Code → Griffe Parser → Template Engine → Your Output
Basic example¶
Let’s document Python’s built-in json
module to show how Griffonner works.
Step 1: Create a template¶
First, create a simple template at docs/templates/python/simple/module.md.jinja2
:
# {{ obj.name }} module
{{ obj.docstring.summary if obj.docstring else "No description available" }}
{% if obj.docstring and obj.docstring.description %}
{{ obj.docstring.description }}
{% endif %}
## Functions
{% for name, func in obj.members.items() %}
{% if func.kind.value == "function" and not name.startswith('_') %}
### `{{ func.name }}({{ func.signature.parameters | map(attribute='name') | join(', ') if func.signature }})`
{{ func.docstring.summary if func.docstring else "No description" }}
{% if func.signature and func.signature.parameters %}
**Parameters:**
{% for param in func.signature.parameters %}
- `{{ param.name }}`: {{ param.annotation if param.annotation else "Any" }}
{% endfor %}
{% endif %}
{% if func.signature and func.signature.returns %}
**Returns:** {{ func.signature.returns }}
{% endif %}
---
{% endif %}
{% endfor %}
## Classes
{% for name, cls in obj.members.items() %}
{% if cls.kind.value == "class" and not name.startswith('_') %}
### {{ cls.name }}
{{ cls.docstring.summary if cls.docstring else "No description" }}
{% endif %}
{% endfor %}
---
*Generated with Griffonner from {{ griffe_target }}*
Step 2: Create a page with frontmatter¶
Create docs/pages/json-module.md
:
---
template: "python/simple/module.md.jinja2"
output:
- filename: "json-module.md"
griffe_target: "json"
custom_vars:
title: "JSON module documentation"
---
This page documents Python's built-in JSON module.
Step 3: Generate documentation¶
# Install griffonner
pip install griffonner
# Generate the documentation
griffonner generate docs/pages/json-module.md --output docs/output
Step 4: Result¶
This generates docs/output/pages/json-module.md
with content like:
# json module
JSON (JavaScript Object Notation) encoder and decoder.
## Functions
### `loads(s, *, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)`
Deserialise a JSON document from a string.
**Parameters:**
- `s`: str
- `cls`: Optional[Type[JSONDecoder]]
- `object_hook`: Optional[Callable[[Dict[Any, Any]], Any]]
- `parse_float`: Optional[Callable[[str], Any]]
**Returns:** Any
---
### `dumps(obj, *, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)`
Serialise obj to a JSON formatted str.
**Parameters:**
- `obj`: Any
- `skipkeys`: bool
- `ensure_ascii`: bool
**Returns:** str
---
## Classes
### JSONDecoder
Simple JSON decoder.
### JSONEncoder
Extensible JSON encoder for Python data structures.
---
*Generated with Griffonner from json*
Key features¶
- Zero opinions: Templates control all formatting and structure
- Frontmatter-driven: Configuration lives in your markdown files
- Format agnostic: Generate Markdown, RST, HTML, JSON - anything
- Template ecosystem: Share and reuse templates across projects
- Griffe-powered: Rich Python code analysis and parsing
CLI commands¶
# Generate all files in a directory
griffonner generate docs/pages/ --output docs/output
# Generate a single file
griffonner generate docs/pages/api.md --output docs/output
# List available templates
griffonner templates
# Validate template syntax
griffonner validate python/default/module.md.jinja2
# Watch mode - live reload during development
griffonner watch docs/pages/ --output docs/output
Watch mode¶
Watch mode provides live reload functionality for development workflows:
# Start watching a directory
griffonner watch docs/pages/
# Watch with custom output directory
griffonner watch docs/pages/ --output docs/generated
# Watch with additional template directories
griffonner watch docs/pages/ --template-dir custom-templates/
When files are modified, Griffonner automatically processes them - regenerating output files for those with frontmatter and copying files without frontmatter directly.
Template discovery¶
Griffonner automatically searches for templates in these locations:
docs/templates/
(project templates)templates/
(current directory)- Built-in templates (shipped with Griffonner)
# List all available templates
griffonner templates
# Search for specific patterns
griffonner templates --pattern "**/*class*"
# Include custom template directories
griffonner templates --template-dir custom-templates/
Get started¶
Ready to create your first documentation? Check out our getting started guide to learn the basics, or explore the template development guide to create custom templates.