A reusable Office document template render engine for DOCX, XLSX, and PPTX.
Project description
Stencil
Stencil is a Python render engine for reusable Office document templates.
It is designed for workflows where a .docx, .xlsx, or .pptx template contains placeholders, loops, and conditionals, and application data fills the template to produce a finished Office document or PDF.
stencil render invoice.docx data.json --output invoice.pdf
The project starts with DOCX because it is the fastest path to a useful internal tool. XLSX and PPTX are planned as separate format engines behind the same public API.
Status
Pre-alpha DOCX MVP.
What exists now:
uv-compatible Python package metadata- Python
>=3.12 stencilimport packagerender()API for DOCX templatesstencil renderCLI command for JSON data- DOCX-first roadmap in local ignored docs
What does not exist yet:
- Stable public API
- PDF conversion worker
- XLSX rendering
- PPTX rendering
Naming
The product, import package, and CLI command are named stencil.
The PyPI distribution name is currently office-stencil because stencil is already taken on PyPI by an old package.
[project]
name = "office-stencil"
[project.scripts]
stencil = "stencil.cli:app"
API
from stencil import render
document = render(
template_path="invoice.docx",
data={
"customer": "Acme",
"line_items": [
{"description": "Implementation", "amount": 1200},
],
},
output_format="docx",
)
Phase 1 supports DOCX input and DOCX output only. The exact API may change while the project is pre-alpha.
CLI
stencil render invoice.docx data.json --output invoice.docx
The CLI reads a top-level JSON object from the data file and writes the rendered document bytes to the output path.
PDF output is planned for a later phase.
Example
See examples/ for a runnable DOCX example with:
examples/templates/invoice.docxexamples/data/invoice.jsonexamples/templates/styled-status-report.docxexamples/data/status-report.json
uv sync --dev
uv run stencil render examples/templates/invoice.docx examples/data/invoice.json --output examples/out/invoice.docx
uv run stencil render examples/templates/styled-status-report.docx examples/data/status-report.json --output examples/out/styled-status-report.docx
Roadmap
- Foundation and proof of shape
- DOCX MVP
- PDF conversion and reliability
- Internal package polish
- XLSX engine
- PPTX engine
- Optional service layer and operations
The detailed local roadmap lives in docs/, which is intentionally ignored by git because it is personal planning material.
Dependencies
Runtime dependencies:
jinja2: template expressions, conditionals, and loopsdocxtpl: DOCX rendering for the first production milestonelxml: Office XML parsing and manipulationopenpyxl: XLSX workbook inspection and future spreadsheet supporttyper: CLI framework
Optional API dependencies:
fastapi: future HTTP service layeruvicorn[standard]: ASGI server for the optional API
Optional worker dependencies:
rq: lightweight Redis-backed queue optioncelery: larger distributed worker optionredis: queue/backend client
Development dependencies:
pytest: test runnerpytest-cov: coverage reportingruff: linting and import sortingmypy: static type checking
External system dependency:
- LibreOffice /
soffice: planned conversion engine for PDF output
Local Development
This repo uses uv, but dependencies have not been installed yet.
Install dependencies when ready:
uv sync --dev
Run tests:
uv run pytest
Run linting:
uv run ruff check .
Run type checking:
uv run mypy
Publishing
The repo includes a GitHub Actions workflow at .github/workflows/publish.yml.
It publishes to PyPI when changes land on main:
- Check out the repo.
- Install
uv. - Set up Python 3.12.
- Install dependencies with
uv sync --dev. - Run tests with
uv run pytest. - Run linting with
uv run ruff check .. - Build the package with
uv build. - Publish with the
PYPI_API_TOKENGitHub Actions secret.
One-time PyPI token setup:
- Create or use the PyPI project named
office-stencil. - Create a PyPI API token. Prefer a project-scoped token for
office-stencilafter the first release exists. - Add the token to GitHub as an Actions secret named
PYPI_API_TOKEN. - The publish workflow uses
user: __token__andpassword: ${{ secrets.PYPI_API_TOKEN }}.
PyPI requires every upload to have a new version. Before merging a feature branch into main, update the version in pyproject.toml.
Dependabot
The repo includes .github/dependabot.yml.
Dependabot checks weekly for:
uvdependency updates frompyproject.toml- GitHub Actions updates from
.github/workflows/
Dependabot will open pull requests. Those PRs should go through the same CI and branch-protection rules as feature branches.
Design Notes
Office files are zipped XML packages, but each format has different failure modes.
- DOCX can split template tags across Word text runs.
- XLSX often stores text in shared strings, so naive replacement can mutate unrelated cells.
- PPTX repeated slides require cloning slide XML, relationships, presentation ordering, and content type entries.
- PDF conversion through LibreOffice needs timeouts, retries, cleanup, and worker isolation.
Stencil should stay milestone-driven: ship a reliable DOCX engine first, then use real needs to decide when XLSX, PPTX, and service infrastructure are worth the extra complexity.
License
MIT. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file office_stencil-0.1.0.tar.gz.
File metadata
- Download URL: office_stencil-0.1.0.tar.gz
- Upload date:
- Size: 122.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddba499214c65e71a4c045492dee8f22df420726a447a367fedf8657a91f5898
|
|
| MD5 |
3953a4d276aa2a118f25b2e0f643d810
|
|
| BLAKE2b-256 |
83a819eea82150ff79ef838c84af25b4da54c9aed0d2ee7940e3100902565daa
|
File details
Details for the file office_stencil-0.1.0-py3-none-any.whl.
File metadata
- Download URL: office_stencil-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
434cada10564f2c3e3e7a2b4804f589d3b89dde7ce1fcaafcff23deb3503def1
|
|
| MD5 |
2981db9831da7b233876f6f28eae763a
|
|
| BLAKE2b-256 |
256f6cf63ad1d87a3e084efcc8344303a0daa6280284cbc519fecafe61b69150
|