Practical Quarto: Patterns, templates, and tooling @ posit::conf(2026)
You write a document.
Render it, and you get an HTML document.
A template: boilerplate, with named holes.
Part of the template renders the title block.
Pull it out into its own file, now its a partial.
Quarto does this for many parts of the page.
Replace a partial without touching the rest of the template
The Bureau of Regional Statistics publishes a quarterly release as a standalone HTML file.

(Optional) Follow along: 03-partials/00-setup
Pull the brand:
Copy templates/title-block.html into the folder.
Register it:
Add a masthead key to the YAML of report.qmd:
Add this line to title-block.html, right after <header ...>:
Render.
Challenge: Provide the alt text via metadata too.
Exercise: 03-partials/01-masthead
Write in the format you are targeting: HTML here
Anything inside $...$ or ${...} is Pandoc’s template syntax.
| Write | Get |
|---|---|
$title$ |
the value of the title metadata key |
$brs-release.period$ |
reach into nested metadata with a dot |
$title-block.html()$ |
include a partial — the () mean a file |
Already in your YAML, and shown by nothing:
Copy, then complete, this line to title-block.html, below the subtitle’s $endif$:
Render. What happens when you remove brs-release from report.qmd?
Exercise: 03-partials/02-period-and-region
report.qmd
Every top-level name you invent is a bet that Quarto will never claim it.
Nest, and you place that bet once instead of once per field.
Read as if subtitle has a value, then….
Prevents empty <p></p> in the document.
Add status: Provisional under brs-release: in report.qmd.
In title-block.html, below the reference period, show the status in a <span class="report-status"> — but only when brs-release.status is set.
Render. Then delete the status: line and render again — the badge should disappear, leaving nothing behind.
Exercise: 03-partials/03-release-status
| Write | Get |
|---|---|
$if(x)$ … $else$ … $endif$ |
conditionals |
$for(x)$ … $endfor$ |
loop over an array |
$sep$ |
inside a loop: emitted between items, never after the last |
${x/uppercase} |
a pipe — also lowercase, length, reverse, nowrap, … |
$-- |
a comment, to the end of the line |
No color. No size. No position. Just a class.
Three classes:report-masthead,report-period, report-status.
Don’t edit title-block.html.
Ask Posit Assistant to style your title block. Start with the prompt below then describe what you want.
Render. Not what you asked for? Say what is wrong and go again.
Skim custom.scss. Change one of the brand variables used and render again.
Example prompt:
Exercise: 03-partials/04-style

/*-- scss:rules --*/
// Accent rule under the whole masthead block.
#title-block-header {
border-bottom: 3px solid $primary;
padding-bottom: 1rem;
margin-bottom: 1.5rem;
// Clear the floated masthead so the description/metadata sit below.
overflow: hidden;
}
// Logo floats to the right of the title text.
.report-masthead {
float: right;
width: auto;
max-height: 4rem;
margin-left: 1.5rem;
}
.subtitle {
color: $secondary;
}
// Release period reads as secondary metadata.
.report-period {
color: $text-muted;
font-size: 0.9rem;
margin-bottom: 0.75rem;
}
// Status pill. color-contrast() picks a readable foreground from the
// brand background instead of hard-coding black or white.
.report-status {
display: inline-block;
padding: 0.25em 0.75em;
border-radius: 999px;
background-color: $brand-forest;
color: color-contrast($brand-forest);
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
}title-block for format: htmltitle-slide 💅 in format: revealjsformat: typstThey exist! https://quarto.org/docs/journals/templates.html
document-metadata.latex
passoptions.latex
doc-class.tex
fonts.latex
font-settings.latex
common.latex
pandoc.tex
tables.tex
graphics.tex
citations.tex
babel-lang.tex
tightlist.tex
biblio-config.tex
after-header-includes.latex
hypersetup.latex
before-title.tex
title.tex
before-body.tex
toc.tex
before-bib.tex
biblio.tex
after-body.tex
numbering.typ
definitions.typ
typst-template.typ
page.typ
typst-show.typ
notes.typ
biblio.typ
metadata.html
title-block.html
title-metadata.html
_title-meta-author.html
toc.html
toc-slide.html
title-slide.html
passoptions.latex
doc-class.tex
fonts.latex
font-settings.latex
common.latex
pandoc.tex
tables.tex
graphics.tex
citations.tex
babel-lang.tex
tightlist.tex
biblio-config.tex
after-header-includes.latex
hypersetup.latex
before-title.tex
title.tex
before-body.tex
toc.tex
before-bib.tex
biblio.tex
after-body.tex
Replacing an entire template offers full control of output but comes with the risk of omitting required variables that can break Pandoc/Quarto features.
Safer approaches:
Selectively replace partials that exist within the master LaTeX or HTML template
Replace the entire LaTeX or HTML template, but then include partials provided with Quarto to ensure that your template takes advantage of all Pandoc and Quarto features
Everything you built, in one folder someone else can install:
Example: brs-format
template.htmltitle-block.htmlQuarto picks one for you based on your YAML, and the docs link to the wrong one for the default:
| Your YAML | Partial that renders |
|---|---|
| (nothing — Bootstrap default) | templates/title-block.html ← you used this one |
title-block-banner: true |
templates/banner/title-block.html |
title-block-style: manuscript |
templates/manuscript/title-block.html |
title-block-style: none |
pandoc/title-block.html — Pandoc’s plain block |
format: revealjsformat: pdfHard-coding “Table of contents” in a partial breaks the moment someone sets lang:.
Since Quarto 1.10, the strings Quarto already translates are template variables:
lang: en |
lang: fr |
|---|---|
| Table of contents | Table des matières |
| Abstract | Résumé |