my-brand
|-- README.md
|-- _extensions
| `-- my-brand
| |-- _extension.yml
| `-- brand.yml
|-- _quarto.yml
`-- example.qmd
2 directories, 5 filesFormatting & Branding
Session 5
Session Overview
Session 5: Formatting & Branding
- Theming & Brand.yml
- Bootstrap 5 theme basics and
brand.ymlfor cross-format consistency. - Colour palettes, typography, and logo management.
- Using the
brand.ymlR and Python packages in code outputs.
- Bootstrap 5 theme basics and
- Brand Extensions &
quarto use brand- Packaging
brand.ymlas a Quarto extension for organisational reuse. - Importing brand configurations with
quarto use brand. - Automation flags for CI workflows.
- Packaging
- Pandoc Templating
- Understanding Pandoc’s templating syntax fundamentals.
- Variables, conditionals, and loops for dynamic content.
- Modifying partials for custom output.
- Typst Customisation (Optional)
- 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 branding capabilities, focusing on brand.yml as the central tool for unified branding across formats, the brand.yml R and Python packages for applying brand guidelines in code outputs, packaging brand configurations as extensions, and importing them with quarto use brand.
Learning Objectives
By the end of this session, participants will be able to:
- Create unified branding across multiple output formats using
brand.yml. - Use the
brand.ymlR and Python packages to apply brand guidelines in code outputs. - Develop brand extensions for organisational reuse.
- Import and manage external brand configurations with
quarto use brand. - Understand Pandoc’s templating syntax for dynamic content generation.
- Understand the basics of Bootstrap theming in Quarto.
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- Theme + customisation.
yaml
format:
html:
theme: [cosmo, custom.scss]See HTML Theming and More About Quarto Themes for YAML options and SCSS customisation.
For most branding needs, brand.yml provides a simpler and more portable approach than custom SCSS, as we will see next.
brand.yml Foundation
Understanding Brand.yml
brand.yml is a single YAML file that codifies your organisation’s brand guidelines into a machine-readable format. It is used by Quarto, Shiny, and the brand.yml R and Python packages to create branded outputs across multiple formats and tools.
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. - R/Python: Available via the
brand.ymlpackages for plots, tables, and applications.
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.yml in R and Python
Brand Guidelines in Code Outputs
brand.yml is not limited to document theming. The R and Python packages let you apply brand colours, fonts, and logos directly in your code outputs.
Supported integrations:
- Quarto (websites, presentations, dashboards, Typst documents).
- Shiny for Python and Shiny for R (via bslib).
- Custom R and Python visualisations (ggplot2, plotnine, great_tables, etc.).
See brand.yml for full documentation.
Using brand.yml in R
Install the package:
r
install.packages("brand.yml")Read the brand and access its properties:
r
library(brand.yml)
brand <- read_brand_yml()
brand[["color"]][["palette"]][["primary"]]
brand[["color"]][["foreground"]]
brand[["typography"]][["base"]]Apply to a ggplot2 visualisation:
r
library(ggplot2)
ggplot(data) +
aes(x = x, y = y) +
geom_point(colour = brand[["color"]][["palette"]][["primary"]]) +
theme_minimal(base_family = brand[["typography"]][["base"]])Using brand_yml in Python
Install the package:
bash
pip install brand_ymlRead the brand and access its properties:
python
from brand_yml import Brand
brand = Brand.from_yaml("_brand.yml")
brand.color.primary
brand.color.palette
brand.typography.baseApply to a plotnine visualisation:
python
from plotnine import ggplot, aes, geom_point, theme, element_text
(
ggplot(data, aes("x", "y"))
+ geom_point(colour=brand.color.primary)
+ theme(text=element_text(family=brand.typography.base))
)The brand.yml packages ensure that your data visualisations match your document branding without manual colour copying.
Hands-On Exercise: Setting Up a Brand
Exercise Overview
Objective: Create a _brand.yml file from scratch with a colour palette, typography, logos, and test it across multiple output formats.
Part 1: Create Brand Identity
Create a new Quarto project:
bash
quarto create project default my-branded-project cd my-branded-projectCreate a
_brand.ymlfile with:meta: Organisation name and link.color: A palette with at least primary, secondary, foreground, and background colours, plus semantic mappings.typography: One or two Google Fonts for base and headings.logo: References to logo files (add placeholder images to anassets/directory).
Add
brandto your theme in_quarto.yml:yaml
format: html: theme: [default, brand]
Part 2: Test Across Formats
Add content to your
index.qmdwith headings, text, code blocks, and lists.Render and verify branding in HTML:
bash
quarto renderTest in RevealJS:
bash
quarto render index.qmd --to revealjsVerify that colours, fonts, and logo appear consistently across both formats.
Part 3: Apply to Code Outputs
Add a code block (R or Python) that uses brand colours from
_brand.ymlin a plot.Verify that the plot colours match the document branding.
Success Criteria
- Create a working
_brand.ymlwith colour palette, typography, and logo. - Consistent branding across HTML and RevealJS formats.
- Logo displayed correctly in the output.
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.
- Importable - Use with
quarto use brandfor easy adoption.
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.
quarto use brand
Importing Brand Configurations
The quarto use brand command copies brand files from an external source into your project’s _brand/ directory, making it easy to adopt shared organisational branding.
Supported sources:
- Local directory:
quarto use brand ./path/to/brand. - GitHub repository:
quarto use brand myorg/shared-brand. - URL zip archive:
quarto use brand https://example.com/brand.zip.
How quarto use brand Works
The command follows a structured workflow with user confirmations:
- Confirms trust for remote sources.
- Creates
_brand/directory if needed. - Prompts before overwriting existing files.
- Copies all files from the source to
_brand/. - Asks whether to remove local files not present in the source.
The result ensures your _brand/ directory matches the source exactly, making it easy to stay synchronised as shared brands evolve.
Flags for Automation
Preview changes without modifying files:
bash
quarto use brand myorg/shared-brand --dry-runSkip all confirmation prompts for automated or CI workflows:
bash
quarto use brand myorg/shared-brand --forceUse --dry-run first to review what will change, then --force in CI pipelines. See Brand for complete documentation.
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.
Appendix: Typst Customisation (Optional)
This section is optional supplementary material. It covers Typst customisation for participants interested in advanced PDF output.
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 filesModify 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.