# Simulate some computed values
<- "admin"
user_type <- TRUE
is_debug <- "2.1.0" current_version
This vignette demonstrates how to use write_yaml_metadata_block()
to dynamically set metadata in Quarto documents based on R computations. This functionality addresses a key limitation where Quarto metadata must traditionally be static and defined in the document header.
Important: To use this function in Quarto documents, you must include the output: asis
chunk option (or #| output: asis
) in your R code chunks. Without this option, the YAML metadata will be displayed as text instead of being processed as metadata.
Let’s start with a basic example where we set some metadata dynamically:
# Simulate some computed values
<- "admin"
user_type <- TRUE
is_debug <- "2.1.0" current_version
Now we can set metadata based on these computed values. Here is the R cell used in the vignette source. Note the #| output: asis
chunk option - this is essential:
```{r}
#| label: metadata-block
#| output: asis
::write_yaml_metadata_block(
quartouser_level = user_type,
debug_mode = is_debug,
app_version = "2.1.0",
generated_at = format(Sys.time(), "%Y-%m-%dT%H:%M:%S%z")
)```
This will generate a YAML metadata block that looks like this in the body of your document:
---
user_level: admin
debug_mode: true
app_version: 2.1.0
generated_at: 2025-07-28T13:15:31+0200
---
Quarto will process this metadata block as an additional metadata block to the frontmatter one. And so, it will make the metadata available for use throughout the document.
They can be used in various ways, such as in shortcodes or conditional content.
Using {{< meta key >}}
shortcodes to access metadata values: https://quarto.org/docs/authoring/variables.html#meta
Using when-meta
attributes to conditionally show/hide content based on metadata values: https://quarto.org/docs/authoring/conditional.html#matching-against-metadata. The metadata values must be a boolean.
Each metadata block will be merged with previous metadata blocks, and existing metadata values can be overwritten by subsequent blocks.
Now that we’ve set the metadata, we can use it with Quarto’s conditional content features:
Current user level: admin
App version: 2.1.0
Debug mode: true
Debug Information
This content is only visible when
debug_mode
is true. Since we set it to TRUE, this message should be visible.Generated at: 2025-07-28T13:15:31+0200
Another powerful use case is making Quarto parameters available as metadata for conditional content. This allows you to control document behavior through parameters while leveraging Quarto’s conditional content features.
Here’s an example that demonstrates creating different versions of a sales report based on parameters:
---
title: "Sales Report"
format: html
params:
region: "North America"
show_confidential: false
quarter: "Q1"
---
```{r}
#| echo: false
#| output: asis
::write_yaml_metadata_block(
quartoparams = params
)```
# {{< meta params.quarter >}} Sales Report - {{< meta params.region >}}
::: {.content-visible when-meta="params.show_confidential"}
::: {.callout-warning}## Confidential Information
This section contains sensitive financial data and competitor analysis.
Region: {{< meta params.region >}}
Quarter: {{< meta params.quarter >}}
:::
```{r}
# Show detailed financial breakdown
cat("Detailed revenue breakdown by product line...")
cat("\nConfidential metrics and competitor analysis...")
```
:::
::: {.content-visible unless-meta="params.show_confidential"}
::: {.callout-note}## Public Summary
This report shows general performance metrics suitable for public distribution.
`{r} params$region`
Region: `{r} params$quarter`
Quarter:
:::
```{r}
# Show summary metrics only
cat("Overall performance summary for", params$region)
cat("\nPublic-facing metrics for", params$quarter)
```
:::
This approach is particularly useful for:
You can render different versions by passing parameters:
# Internal report with confidential data
::quarto_render("sales-report.qmd",
quartoexecute_params = list(
region = "North America",
show_confidential = TRUE,
quarter = "Q2"
))
# Public report without confidential data
::quarto_render("sales-report.qmd",
quartoexecute_params = list(
region = "Europe",
show_confidential = FALSE,
quarter = "Q2"
))
The key insight is that write_yaml_metadata_block(params = params)
makes all your document parameters available as metadata. The boolean ones can then be used with Quarto’s when-meta
and unless-meta
conditional attributes for dynamic content control.
One powerful application of dynamic metadata is variant emails using Quarto’s email format. This example shows how to randomly select an email variant and conditionally display different content based on that selection:
This approach is particularly useful when deploying email reports through Posit Connect Quarto integration, which supports email customization for automated report distribution.
---
title: test conditional emails
format: email
email-preview: true
---
Pick variant
```{r}
<- sample(1:3, 1)
variant ```
```{r}
#| echo: false
#| output: asis
::write_yaml_metadata_block(
quarto.list = setNames(
list(TRUE),
nm = sprintf("is_email_variant_%d", variant)
)
)```
::: {.email}
`{r} variant`
This email was sent from Quarto! With conditional output for condition
::: {.content-visible when-meta="is_email_variant_1"}
email body 1
```{r}
head(mtcars)
```
::: {.subject}
subject 1
:::
:::
::: {.content-visible when-meta="is_email_variant_2"}
email body 2
```{r}
head(palmerpenguins::penguins)
```
::: {.subject}
subject 2
:::
:::
::: {.content-visible when-meta="is_email_variant_3"}
email body 3
```{r}
::praise()
praise```
::: {.subject}
subject 3
:::
:::
::: {.email-scheduled}
TRUE
:::
:::
## Logging
`{r} variant`
Case:
`{r} Sys.time()` Report run:
This example demonstrates several advanced concepts:
sample()
to randomly choose one of three email variantssprintf()
and setNames()
.subject
divs and .email-scheduled
metadataThe write_yaml_metadata_block()
function generates a YAML metadata block that can be inserted into the document body. It accepts named arguments or a list, which are converted to YAML format. The yaml R package is used for YAML serialization: https://github.com/vubiostat/r-yaml
Look for the documentation of this package for more details on how YAML is formatted and structured from R objects.
Currently, this package does write YAML with additional specific handlers, for non-default behavior:
TRUE
and FALSE
are converted to true
and false
in YAML, respectively.