my-brand
|-- README.md
|-- _extensions
| `-- my-brand
| |-- _extension.yml
| `-- brand.yml
|-- _quarto.yml
`-- example.qmd
2 directories, 5 files
Formatting & Branding
Session 5
Session Overview
Session 5: Formatting & Branding
- Bootstrap Theming & Customisation
- Bootstrap 5 integration and built-in theme selection.
- Progressive customisation from YAML options to light CSS.
- Theme layering and CSS custom properties.
- Unified Branding with Brand.yml
- Brand.yml systems for cross-format consistency.
- Colour palettes, typography, and logo management.
- Integration with Bootstrap and format-specific options.
- Pandoc Templating & Extensions
- Understanding Pandoc’s templating syntax fundamentals.
- Variables, conditionals, and loops for dynamic content.
- Developing brand extensions for organisational reuse.
- Typst Customisation
- Typst templates and partials for PDF branding.
- Template structure and brand.yml integration.
- Creating custom Typst formats with consistent visual identity.
Session Objectives
This session explores Quarto’s advanced theming and branding capabilities, covering Bootstrap 5 customisation, brand.yml systems for unified branding, Pandoc templating syntax, and Typst customisation for professional PDF output.
Learning Objectives
By the end of this session, participants will be able to:
- Implement professional themes with Bootstrap 5 customisation.
- Apply progressive customisation from YAML to light CSS.
- Create unified branding across multiple output formats using
brand.yml. - Develop brand extensions for organisational reuse.
- Understand Pandoc’s templating syntax for dynamic content generation.
- Customise Typst templates and partials for branded PDF output.
Theming (Bootstrap & Customisation)
Bootstrap in Quarto
Quarto HTML format uses Bootstrap 5, providing:
- Several built-in themes from Bootswatch.
- Responsive grid system.
- Component library (e.g., buttons, cards, navigation).
- Customisation system via CSS variables.
Theme Selection
Available themes: default, cerulean, cosmo, cyborg, darkly, flatly, journal, litera, lumen, lux, materia, minty, morph, pulse, quartz, sandstone, simplex, sketchy, slate, solar, spacelab, superhero, united, vapor, yeti, zephyr.
See HTML Theming for more.
- Single theme.
yaml
format:
html:
theme: cosmo- Light/dark theme pair.
yaml
format:
html:
theme:
light: cosmo
dark: darkly- Theme + customisation.
yaml
format:
html:
theme: [cosmo, custom.scss]Can also be written as:
yaml
format:
html:
theme:
- cosmo
- custom.scssBasic Customisation
yaml
format:
html:
theme: cosmo
# Typography
fontsize: 1.1em
linestretch: 1.6
mainfont: "Inter"yaml
format:
html:
theme: cosmo
# Typography
fontsize: 1.1em
linestretch: 1.6
mainfont: "Inter"
# Colours
linkcolor: "#2E86AB"
backgroundcolor: "#FFFFFF"yaml
format:
html:
theme: cosmo
# Typography
fontsize: 1.1em
linestretch: 1.6
mainfont: "Inter"
# Colours
linkcolor: "#2E86AB"
backgroundcolor: "#FFFFFF"
# Layout
max-width: 1200px
margin-left: 2rem
margin-right: 2remSee HTML Theming - Basic Options for more.
Progressive Enhancement
Move to SCSS for more control:
yaml
format:
html:
theme:
- cosmo
- styles.scssCustom SCSS file follows a specific structure using comments:
styles.scss
/*-- scss:defaults --*/
$h2-font-size: 1.6rem !default;
$headings-font-weight: 500 !default;
/*-- scss:rules --*/
h1, h2, h3, h4, h5, h6 {
text-shadow: -1px -1px 0 rgba(0, 0, 0, .3);
}See More About Quarto Themes for more.
brand.yml Foundation
Understanding Brand.yml
brand.yml is a single YAML file that codifies your organisation’s brand guidelines into a format that can be used by Quarto (but not limited to) to create branded outputs across multiple formats.
Key benefits:
- Cross-format consistency - HTML, PDF, presentations share the same design.
- Organisational standards - Teams work with unified branding.
- Easy maintenance - Update once, apply everywhere.
- Simple syntax - No complex CSS knowledge required.
Basic brand.yml Structure
Create a _brand.yml file in your project root:
_brand.yml
1meta:
name: "Your Organisation"
link: "https://yourorg.com"
2color:
palette:
primary: "#2E86AB"
secondary: "#A23B72"
light: "#F8F9FA"
dark: "#343A40"
primary: primary
foreground: dark
background: light
3logo:
small: "assets/logo-small.png"
medium: "assets/logo-medium.png"
large: "assets/logo-large.png"
4typography:
fonts:
- family: "Inter"
source: "google"
base: "Inter"
headings: "Inter"- 1
- Basic brand identity.
- 2
- Colour palette system.
- 3
- Logo management.
- 4
- Typography system.
Colour Palette System
The palette defines named colours that can be referenced throughout your brand:
_brand.yml
color:
1 palette:
ocean-blue: "#2E86AB"
coral-pink: "#A23B72"
sunshine: "#F4A261"
forest: "#2A9D8F"
charcoal: "#264653"
pearl: "#F8F9FA"
# Semantic assignments
primary: ocean-blue
secondary: coral-pink
success: forest
warning: sunshine
foreground: charcoal
background: pearl- 1
- Define a palette of named colours.
Cross-format usage:
- HTML: Available as
$brand-primary(SCSS),--brand-primary(CSS), etc. - Typst: Available as
brand-color.primary, etc.
Typography Configuration
Define your organisation’s font system:
yaml
typography:
fonts:
# Google Fonts (automatically loaded)
- family: "Inter"
source: "google"
weight: [300, 400, 500, 600, 700]
# System fonts (fallback)
- family: "system-ui"
source: "system"
# Font assignments
base: "Inter" # Body text
headings: "Inter" # All headings
monospace: "SF Mono" # Code blocksSee Typst Brand YAML for troubleshooting fonts in Typst.
Logo Management
Provide logos at different sizes for various contexts:
yaml
logo:
# Favicon and small contexts
small: "brand/favicon.png"
# Navigation bars, headers
medium: "brand/logo-nav.png"
# Hero sections, print materials
large: "brand/logo-full.png"| Format | Location | Logo Preference (high to low) |
|---|---|---|
html/dashboard |
Top navigation bar | small > medium > large |
html |
Side navigation | medium > small > large |
typst |
Top left, control with format: typst: logo |
medium > small > large |
revealjs |
Bottom right corner of slides | medium > small > large |
website/book project |
favicon shown in browser tab |
small |
See Logo Configuration for more.
Brand Integration
Combine brand.yml with Bootstrap customisation:
_quarto.yml
format:
html:
theme:
- cosmo
- brand
- styles.scss
1 css: custom-components.css- 1
-
Prefer
brand.ymlor SCSS for component customisation.
The brand colours become available as CSS variables and SCSS variables automatically.
Brand Extensions Development
What Are Brand Extensions?
Brand extensions are Quarto extensions that provide a brand.yml file and its assets, packaged for easy distribution and reuse.
Key features:
- Portable branding - Install everywhere.
- Team consistency - Everyone gets the same brand.
- Asset management - Logos and fonts included.
- Version control - Track brand changes over time.
Creating a Brand Extension
Step 1: Scaffold Extension
bash
quarto create extension brand my-brand
cd my-brandThis creates:
Step 2: Configure Extension
Quarto
title: My-brand
author: First Last
version: 1.0.0
quarto-required: ">=1.9.0"
contributes:
metadata:
project:
brand: brand.ymlStep 3: Design Brand System
_extensions/my-brand/brand.yml
meta:
name: "My Organisation"
link: "https://myorg.com"
color:
palette:
# Primary brand colours
brand-blue: "#2E86AB"
brand-coral: "#A23B72"
brand-gold: "#F4A261"
# Supporting colours
neutral-light: "#F8F9FA"
neutral-dark: "#343A40"
success-green: "#28A745"
warning-amber: "#FFC107"
# Semantic mappings
primary: brand-blue
secondary: brand-coral
success: success-green
warning: warning-amber
foreground: neutral-dark
background: neutral-light
logo:
small: assets/logo/favicon.png
medium: assets/logo/logo-horizontal.png
large: assets/logo/logo-vertical.png
typography:
fonts:
- family: "Source Sans Pro"
source: "google"
weight: [300, 400, 600, 700]
base: "Source Sans Pro"_extensions/my-brand/brand.yml
defaults:
bootstrap:
defaults:
# Enhanced navigation
navbar-padding-y: 1rem
navbar-brand-font-size: 1.5rem
# Improved buttons
btn-padding-y: 0.5rem
btn-padding-x: 1.5rem
btn-font-weight: 600
# Better spacing
spacer: 1rem
rules: |
/* Professional enhancements */
.navbar-brand {
font-weight: 700;
}
.btn-primary {
border-radius: 2rem;
transition: all 0.3s ease;
}
.btn-primary:hover {
transform: translateY(-1px);
}
/* Content styling */
.title-block-header {
padding: 3rem 2rem;
margin-bottom: 2rem;
border-radius: 0.5rem;
}Step 4: Add Assets
Organise brand assets:
txt
_extensions/my-brand/
├── _extension.yml
├── brand.yml
└── assets/
├── logo/
│ ├── favicon.png
│ ├── logo-horizontal.png
│ └── logo-vertical.png
└── fonts/
└── custom-font.woff2Step 5: Create Example
example.qmd
---
title: "Brand Extension Showcase"
subtitle: "Demonstrating consistent branding"
author: "Your Name"
format:
html:
theme:
- quartz
- brand
---
# Welcome to Our Brand System
This document demonstrates the power of brand extensions in Quarto.
[Primary Action]{.btn .btn-primary}
[Secondary Action]{.btn .btn-secondary}Brand extensions require a _quarto.yml project file to work.
Hands-On Exercise: Building Your Brand Extension
Exercise Overview
Objective: Create a comprehensive brand extension that demonstrates unified branding across formats using brand.yml and light CSS customisation.
Example Code:
bash
tar -xzf "05a-exercises.tar.gz" -C "05-formatting-branding"Part 1: Brand Extension Setup
Generate extension scaffold:
bash
quarto create extension brand my-company-brand cd my-company-brandDefine your brand identity.
Add styling.
Part 2: Testing
Build test project:
bash
quarto create projectTest across formats:
bash
# Test HTML output quarto render example.qmd --to html # Test presentation quarto render example.qmd --to revealjs # Test Typst output quarto render example.qmd --to typstVerify brand consistency.
Success Criteria
✅ You’ve successfully completed the exercise if you can:
- Create a working brand extension with consistent visual identity.
- Implement styling using
brand.ymland light (S)CSS. - Test the brand system across multiple formats.
- Demonstrate cross-format consistency.
- Build a reusable brand asset for teams.
- Apply design principles effectively.
Pandoc Templating System
Understanding Pandoc Templates
Quarto uses Pandoc’s templating system to generate output.
Key concepts:
- Variables -
$variable$inserts YAML metadata. - Conditionals -
$if(variable)$...$endif$for optional content. - Loops -
$for(variable)$...$endfor$for repeated content. - Partials - Reusable template components.
See Pandoc Template Syntax for complete documentation.
Basic Variable Syntax
Variables from YAML front matter are inserted using $variable$:
Quarto Document
---
title: "My Report"
author: "Jane Smith"
date: "2025-01-15"
---Template Input
Title: $title$
Author: $author$
Date: $date$Template Output
Title: My Report
Author: Jane Smith
Date: 2025-01-15Use $variable$ in any template file (.typ, .tex, .html, etc.).
See Article Templates for templates and partials.
Conditional Content
Show content only when a variable exists:
Quarto Document
---
title: "Report"
subtitle: "Q4 Analysis"
# No author specified
---Use $if(variable)$...$else$...$endif$ for alternative content.
Template Input
Title: $title$
$if(subtitle)$
Subtitle: $subtitle$
$endif$
$if(author)$
Author: $author$
$endif$Template Output
Title: Report
Subtitle: Q4 Analysis$if(variable)$ in Pandoc templates checks if a variable is:
- Defined (exists in the metadata).
- Non-empty (has a value).
- Not explicitly false.
Loops for Multiple Items
Process lists from YAML metadata:
Quarto Document
---
authors:
- name: Jane Smith
email: jane@example.com
- name: John Doe
email: john@example.com
---Template Input
Authors:
$for(authors)$
- $it.name$ ($it.email$)
$endfor$Template Output
Authors:
- Jane Smith (jane@example.com)
- John Doe (john@example.com)Use $it$ to reference the current item in a loop. Use $sep$ followed by the separator string for separators.
Separator Usage
Add separators between items:
Quarto Document
---
tags:
- Research
- Data Science
- Machine Learning
---Template Input
Tags: $for(tags)$$it$$sep$, $endfor$Template Output
Tags: Research, Data Science, Machine LearningTemplate Input
Tags: $for(tags)$$it$$endfor$Template Output
Tags: ResearchData ScienceMachine LearningHands-On Exercise: Pandoc Templating
Exercise Overview
Objective: Modify a partial template to display additional metadata using Pandoc templating syntax.
Example Code:
bash
tar -xzf "05b-exercises.tar.gz" -C "05-custom-partials"Part 1: Template Modification
Retrieve the partials described in Article Templates
Modify the title slide partial from Reveal.js to underline the corresponding author:
- Use
$if(by-author)$to check forby-authormetadata. - Loop through
by-authorto find the corresponding author and underline their name. - See Author Schema for details.
- Use
Part 2: Customise Further
Add additional metadata to the title slide, such as affiliations or ORCID IDs.
Test the changes by rendering a sample presentation with multiple authors with affiliations and a corresponding author.
Success Criteria
✅ You’ve successfully completed the exercise if you can:
- Modify a Quarto/Pandoc partial template using conditionals and loops.
- Display dynamic content based on YAML metadata.
- Test and verify the output in a Reveal.js presentation.
Typst Customisation (For the Curious)
Typst in Quarto
Typst is a modern typesetting system for creating beautiful PDFs, designed to be simpler than LaTeX.
Why Typst?
- Fast - Instant PDF generation.
- Simple - Markdown-like syntax.
- Flexible - Easy template customisation.
See Typst Basics for more.
Typst Template Structure
Quarto’s Typst templates use two key files:
typst-template.typ- Defines document layout:
typst-template.typ
- 1
- Page setup.
- 2
- Typography settings.
- 3
- Conditional title block.
- 4
- Main content insertion.
typst-show.typ- Captures YAML metadata using Pandoc syntax:
typst-show.typ
#show: doc => article(
$if(title)$
title: [$title$],
$endif$
1 $if(by-author)$
authors: [$for(by-author)$$it.name.literal$$sep$, $endfor$],
$endif$
doc,
)- 1
-
Use
by-authorto get Quarto’s extended author metadata.
Notice the Pandoc template syntax: $if()$, $for()$, $variable$.
Simple Customisation Example
typst-template.typ
#let article(
title: none,
body
) = {
let primary = rgb("#2E86AB")
if title != none {
block(
fill: primary,
inset: 1em,
radius: 0.5em,
width: 100%
)[
#align(center)[
#text(
fill: white,
weight: "bold",
size: 1.5em,
title
)
]
]
}
body
}typst-show.typ
#show: doc => article(
$if(title)$
title: [$title$],
$endif$
doc,
)
Creating a Typst Format
Step 1: Scaffold Extension
bash
quarto create extension format:typst my-format
cd my-formatThis creates:
my-format
|-- README.md
|-- _extensions
| `-- my-format
| |-- _extension.yml
| |-- typst-show.typ
| `-- typst-template.typ
`-- template.qmd
2 directories, 5 files
Modify the generated typst-template.typ file to customise your layout.
Step 2: Integration with brand.yml
_brand.yml
color:
primary: "#2E86AB"
logo:
medium: "assets/logo.png"typst-show.typ
#show: doc => article(
$if(title)$
title: [$title$],
title_colour: brand-color.primary,
$endif$
doc,
)page.typ
$if(logo)$
#set page(
header: context {
if counter(page).get().first() == 1{
place(top + left, dy: 0.5cm, image("$logo.path$", width: 2cm))
}
}
)
$endif$typst-template.typ
#let article(
title: none,
title_colour: "#000000",
body
) = {
set text(size: 11pt)
if title != none {
align(center)[
#text(
fill: rgb(title_colour),
weight: "bold",
size: 1.5em,
title
)
]
}
body
}Hands-On Exercise: Creating a Format Extension
Exercise Overview
Objective: Create a custom format extension that bundles brand.yml and styling into a reusable format for your organisation.
Example Code:
bash
tar -xzf "05c-exercises.tar.gz" -C "05-format-extension"Part 1: Format Extension Setup
Generate format extension scaffold:
bash
quarto create extension format:html company-report cd company-reportAdd brand.yml and configure extension in _extension.yml`:
yaml
contributes: formats: typst: template-partials: - assets-typst/typst-template.typ - assets-typst/typst-show.typ - assets-typst/page.typ metadata: project: brand: brand.yml
Part 2: Customise and Test Your Format
Define your template in
typst-template.typandtypst-show.typ.Use your format in
template.qmd:yaml
--- title: "Quarterly Report" format: company-report-typst ---Render and verify:
bash
quarto render template.qmd
Part 3: Optional HTML Variant
Add HTML output to your format:
Add HTML format to
_extension.yml.Create/Modify simple template. (See HTML partials)
Test both formats:
bash
quarto render template.qmd --to company-report-html quarto render template.qmd --to company-report-typst
Success Criteria
✅ You’ve successfully completed the exercise if you can:
- Create a working format extension with bundled branding.
- Apply custom styling through brand.yml and SCSS.
- Test the format with sample documents.
- (Optional) Add HTML variant.