Important
This is a proof of concept.
This repo builds Quarto templates and filters into a public gallery of CI-built sample PDFs.
The workflow is manifest-driven:
templates.ymlis the readable inventory snapshot aligned with the canonical list.data/template-overrides.ymlholds the entries that CI should actually build.data/template-manifest.ymlis the generated manifest used by CI.scripts/build-manifest.Rmerges the inventory and overrides.scripts/write-render-matrix.Rturns enabled entries into the GitHub Actions matrix..github/workflows/publish.ymlinstalls each enabled entry withquarto use template, renders it, collects PDFs, generatesindex.qmd, and publishes the site on pushes tomain.
Most entries only need these fields in data/template-overrides.yml:
engine:typstorlatex. This controls extra setup like fonts or TinyTeX.ci.install_target: the value passed toquarto use template.ci.input: the file to render.ci.output_pdf: the PDF expected after render.ci.needs_r: install R for examples that execute R.ci.extra_files: extra assets to copy in when Quarto does not materialize them.
These CI defaults are filled in automatically and usually do not need to be written per entry:
ci.path: "."ci.render_target: file
For unusual templates, there are a few optional advanced fields:
ci.extra_system_packages: extra Ubuntu packages to install before renderingci.extra_r_packages: extra CRAN packages needed only for a specific templateci.extra_tex_packages: extra TinyTeX packages to installci.render_args: extra arguments passed toquarto render
To enable a new template or filter in CI:
- Make sure it exists in
templates.yml. - Add a matching block in
data/template-overrides.yml. - Set
engine,ci.install_target,ci.input, andci.output_pdf. - Add
ci.needs_r: trueonly if the example actually executes R code. - Add
ci.extra_filesonly for assets thatquarto use templatedoes not materialize.
A typical template entry looks like:
my-template:
slug: my-template
kind: template
engine: typst
ci:
install_target: christopherkenny/my-template
input: template.qmd
output_pdf: template.pdfA typical filter entry looks like:
my-filter:
slug: my-filter
kind: filter
ci:
install_target: christopherkenny/my-filter
input: example.qmd
output_pdf: example.pdfThe workflow assumes a Quarto CLI install-and-render path for all enabled entries:
quarto use template <install_target> --no-prompt- Render the example file from the materialized directory
- Copy the expected PDF into
assets/pdfs - Merge all
result.ymlfiles intodata/build-results.yml - Generate
index.qmdfrom the manifest plus build results
For file renders, the workflow tries ci.input first. If that file is not present after materialization and there is exactly one top-level .qmd, it renders that file instead and expects the matching .pdf. This is what lets entries like apsr.qmd or cv.qmd work without maintaining one-off filename logic per repo.
Each matrix build uploads a template-<slug> artifact. The files that matter are:
result.yml: final status and failure detailsrender-tail.log: the last 200 lines of render outputfiles.txt: recursive file listing after rendermaterialize.log: output fromquarto use template
The most useful result.yml fields are status, failure_class, and failure_detail.
When an entry fails, start with the template-<slug> artifact:
- Check
result.ymlforfailure_classandfailure_detail. - Check
render-tail.logfor the actual error. - Use
files.txtto confirm what Quarto materialized and what was produced after render.
The gallery site also includes a status table so the current CI state is visible without opening the Actions run.