Project Profiles
Project profiles adapt a project’s configuration, environment, and
content for different scenarios from a single source: render a
website with freeze: true locally but always execute on CI, build
a basic and an advanced version of the same material, or keep
production-only options out of your everyday preview.
When a profile named production is active:
_quarto-production.ymlis merged over_quarto.yml;- variables from
_environment-productionare applied (see Project Environment Files); - content marked
when-profile="production"appears (andunless-profile="production"content disappears); - code cells and render scripts see
QUARTO_PROFILE=production, so Python/R code can branch on it.
Activating profiles
Activate one or more profiles with the --profile option or the
QUARTO_PROFILE environment variable:
quarto render --profile production
quarto render --profile advanced,production
export QUARTO_PROFILE=advanced,production
quarto render--profile replaces any QUARTO_PROFILE from the environment —
the two never merge. Profile names are comma-separated, must start
with a letter or digit, and may contain only letters, digits, .,
_, and - (they name files like _quarto-<name>.yml; anything
else is an error).
quarto preview --static takes --profile like render. The live
quarto preview viewer takes it too, but only the native side honors it
(the PDF pane, downloads and project settings, as QUARTO_PROFILE does):
the page you edit is rendered in the browser from the synced project,
which has no profile files, so its html preview ignores the profile (a
startup notice says so). Restart the preview to change profiles.
Profile configuration
A profile’s configuration file _quarto-<name>.yml sits next to
_quarto.yml and may contain any project configuration. It is
merged over the main configuration:
_quarto.yml
project:
type: website
execute:
freeze: true_quarto-production.yml
execute:
freeze: falseMaps merge key-by-key and scalars from the profile win. Arrays
concatenate; write key: !prefer [...] in the profile to replace
an array instead. When several profiles are active, the
first-listed profile wins conflicts. A local override file
_quarto.yml.local (git-ignore it) is merged over everything,
profiles included.
Selecting a profile that matches nothing in the project — no
_quarto-<name>.yml, no _environment-<name>, not declared under
profile: — is usually a typo and draws a warning.
Default profiles and groups
The profile key in _quarto.yml controls what is active when no
explicit selection is made:
_quarto.yml
profile:
default: advancedA profile group declares mutually exclusive profiles of which exactly one should always be active — the first member is the group’s default:
_quarto.yml
project:
type: book
book:
title: "My Book"
profile:
group:
- [basic, advanced]With _quarto-basic.yml and _quarto-advanced.yml each supplying
their own book: chapters: list, quarto render builds the basic
book and quarto render --profile advanced the advanced one — and
rendering with no profile still works, because the group activates
basic.
_quarto.yml.local may also set profile: default: (handy for a
personal default on one machine); groups are read from _quarto.yml
only. You can also set QUARTO_PROFILE=... in _environment or
_environment.local to give the project a default.
Profile content
Divs and spans with the .content-visible and .content-hidden
classes condition content on the active profiles:
::: {.content-visible when-profile="advanced"}
This content only appears in the advanced version.
:::
::: {.content-hidden when-profile="advanced"}
This content is hidden from the advanced version.
:::
An inline example: [only for advanced readers]{.content-visible
when-profile="advanced"}.
The same classes accept when-format / unless-format (for output
formats, with the usual aliases — when-format="html" also matches
revealjs and epub) and when-meta / unless-meta (true when
the metadata at a dotted path is present and not false). Multiple
conditions on one element must all hold; a comma-separated value
(when-profile="basic,advanced") matches when any listed name is
active. Because profiles can set metadata in their configuration
files, when-meta combined with a profile overlay is often the most
flexible way to control content.
A profile used only for conditional content matches no files, so
it draws the unknown-profile warning. Declare it under
profile.group (or profile.default) in _quarto.yml to tell
Quarto it is intentional.
Profiles in code
The active profile list (comma-separated, in activation order, including group defaults) is visible to everything the render runs:
import os
profiles = os.environ.get("QUARTO_PROFILE", "").split(",")The same value is available in documents via
{{< env QUARTO_PROFILE >}}.
Differences from Quarto 1
Quarto 2 keeps Quarto 1’s activation and merging rules, with these deliberate changes:
- Typos are diagnosed. Unknown active profiles, malformed
profile:configuration, invalid profile names, misspelledwhen-*/unless-*attributes, andprofile:keys in files where they have no effect all produce warnings or errors; Quarto 1 is silent on all of them. - Array merging concatenates (use
!preferto replace); Quarto 1 unioned arrays while removing duplicates. - Comma-separated condition values (
when-profile="a,b") mean any-of; Quarto 1 matched the value literally. --profilenever modifies your environment; code seesQUARTO_PROFILEbecause Quarto passes it to the processes it starts.