Quartz is meant to be extremely configurable, even if you don’t know any coding. Most of the configuration you should need can be done by just editing quartz.config.yaml.
Tip
If you edit quartz.config.yaml using a text-editor with YAML language support like VSCode, it will warn you when you’ve made an error in your configuration, helping you avoid configuration mistakes!
The configuration of Quartz can be broken down into three parts:
quartz.config.yaml
configuration: pageTitle: "My Site" # ... general configurationplugins: - source: "@quartz-community/explorer" enabled: true # ... plugin entrieslayout: # ... groups and per-page-type layout overrides
configuration and plugins are described below; the layout section (component groups, byPageType overrides, sidebar modes) is described in layout.
General Configuration
This part of the configuration concerns anything that can affect the whole site. The following is a list breaking down all the things you can configure:
pageTitle: title of the site. This is also used when generating the RSS Feed for your site.
pageTitleSuffix: a string added to the end of the page title. This only applies to the browser tab title, not the title shown at the top of the page.
enableSPA: whether to enable SPA Routing on your site.
enablePopovers: whether to enable popover previews on your site.
prefetch: fetch pages before their links are followed, so they open at once (prefetching): viewport (default, links on screen and links pointed at), hover (only links pointed at) or "off". Works with and without SPA routing.
analytics: what to use for analytics on your site. Values can be
null: don’t use analytics;
{ provider: 'google', tagId: '<your-google-tag>' }: use Google Analytics;
{ provider: 'plausible' } (managed) or { provider: 'plausible', host: 'https://<your-plausible-host>' } (self-hosted, make sure to include the https:// protocol prefix): use Plausible;
{ provider: 'posthog', apiKey: '<your-posthog-project-apiKey>' } (managed) or { provider: 'posthog', apiKey: '<your-posthog-project-apiKey>', apiHost: '<your-posthog-api-host>', uiHost: '<your-posthog-ui-host>', personProfiles: 'identified_only' } (self-hosted/reverse proxy): use PostHog. uiHost is required when apiHost is a reverse proxy. The legacy host option is an alias for apiHost;
{ provider: 'tinylytics', siteId: '<your-site-id>' }: use Tinylytics;
{ provider: 'cabin' } or { provider: 'cabin', host: 'https://cabin.example.com' } (custom domain): use Cabin;
{provider: 'clarity', projectId: '<your-clarity-id-code' }: use Microsoft clarity. The project id can be found on top of the overview page.
{ provider: 'matomo', siteId: '<your-matomo-id-code', host: 'matomo.example.com' }: use Matomo, without protocol.
baseUrl: this is used for sitemaps and RSS feeds that require an absolute URL to know where the canonical ‘home’ of your site lives. This is normally the deployed URL of your site (e.g. quartz.jzhao.xyz for this site). Do not include the protocol (i.e. https://) or any leading or trailing slashes.
You will be prompted to set this during `npx quartz create`. The CLI automatically strips any https:// or http:// protocol prefixes and trailing slashes for you.
This should also include the subpath if you are hosting on GitHub pages without a custom domain. For example, if my repository is jackyzha0/quartz, GitHub pages would deploy to https://jackyzha0.github.io/quartz and the baseUrl would be jackyzha0.github.io/quartz.
Note that Quartz 5 will avoid using this as much as possible and use relative URLs whenever it can to make sure your site works no matter where you end up actually deploying it.
publishAssets: which non-Markdown files (images, PDFs, …) from content are copied to the site.
"all" (default): every file that isn’t ignored.
"referenced": only files a published page links to or embeds. Use this with ExplicitPublish or drafts, so that files only unpublished notes use stay private.
Files that Quartz renders as pages themselves (e.g. .base and .canvas files) are never copied as raw assets.
ignorePatterns: a list of glob patterns that Quartz should ignore and not search through when looking for files inside the content folder. See private pages for more details.
theme: configure how the site looks.
fontOrigin: where to load fonts from.
"googleFonts" (default): loads fonts from Google Fonts API. Fastest option, especially with CDN caching enabled.
"local": Quartz loads no fonts at all; you provide them. The typography names are still used as the font families, so declare matching @font-face rules in quartz/styles/custom.scss and put the font files in quartz/static/fonts/ (served at static/fonts/):
Use a path relative to the site root like above (no leading /) so it also works when the site is served from a subpath. To have Quartz download Google Fonts at build time and serve them from your site instead, use the Fonts plugin with fontOrigin: selfHosted.
cdnCaching: if true (default), use Google CDN to cache the fonts. This will generally be faster. Disable (false) this if you want Quartz to download the fonts to be self-contained.
typography: what fonts to use. Any font available on Google Fonts works here.
title: font for the title of the site (optional, same as header by default)
header: font to use for headers
code: font for inline and block quotes
body: font for everything
colors: controls the theming of the site. It has two color schemes, lightMode and darkMode, each with the same keys:
textHighlight: markdown highlighted text background
frontmatter, links, drafts, contentIndex: options for Quartz’s built-in processing — frontmatter parsing (Frontmatter), link resolution (CrawlLinks), draft handling (RemoveDrafts) and the content index, sitemap and RSS feed (ContentIndex). They are on by default. Each takes an object of options (plus enabled and order) or a boolean shorthand: set e.g. links: { markdownLinkResolution: relative } to change an option or contentIndex: false to turn one off.
links.markdownLinkResolution defaults to shortest (Obsidian’s default). An old crawl-links plugin entry that Quartz migrates keeps that plugin’s default, absolute, unless it sets another value.
quartz.config.yaml
configuration: theme: colors: lightMode: light: "#faf8f8" secondary: "#284b63" # ... the other keys darkMode: light: "#161618" secondary: "#7b97aa" # ... the other keys
Colors with an Obsidian theme
A theme from quartz-themes (the @quartz-themes/core plugin; the Obsidian and TTRPG templates enable one) brings its own color scheme and colors the page through Obsidian’s CSS variables (--text-normal for most text, --text-muted for paragraphs, --background-primary, --interactive-accent, …). The colors above then have little or no effect. To change a theme’s colors, override its variables in quartz/styles/custom.scss:
quartz/styles/custom.scss
html[saved-theme="dark"] body { --text-normal: #e0e0e0; --text-muted: #a0a0a0;}
(use html[saved-theme="light"] body for light mode), or disable the theme to use the colors above.
Plugins
You can think of Quartz plugins as a series of transformations over content.
Plugins are categorized by their type (transformer, filter, emitter, pageType) based on their manifest. The order field controls execution order within each category.
Note
For advanced TS override of plugin configuration, you can modify quartz.ts:
quartz.ts
import { loadQuartzConfig, loadQuartzLayout } from "./quartz/plugins/loader/config-loader"const config = await loadQuartzConfig({ // override any configuration field here})export default configexport const layout = await loadQuartzLayout()
Transformersmap over content (e.g. parsing frontmatter, generating a description)
Emittersreduce over content (e.g. creating an RSS feed or pages that list all files with a specific tag)
Page Types define how different types of pages are rendered (content pages, folder listings, tag listings). Each page type can use a different page frame to control its overall HTML structure.
The layout.byPageType section in quartz.config.yaml can also set a template field to override the page frame for a specific page type:
quartz.config.yaml
layout: byPageType: canvas: template: minimal # Override the page frame for canvas pages
See layout > Page Frames for details on available frames and how frame resolution works.
Internal vs External Plugins
Quartz distinguishes between processing that is built into Quartz and plugins that are installed separately.
In quartz.config.yaml, the official plugins are referenced by their npm package name (this is what the default config uses); other plugins can also be referenced by a Git source such as github:org/repo:
Frontmatter parsing, link resolution, drafts and the content index are not plugins: they are built into Quartz and configured under configuration.frontmatter, .links, .drafts and .contentIndex. Everything else is a plugin, referenced by its source: npm plugins (all the default ones) are installed in node_modules, Git and local plugins in .quartz/plugins/.
Community Plugins
To install a community plugin, you can use the following command:
npx quartz plugin add @quartz-community/explorer # an npm packagenpx quartz plugin add github:username/repo # a Git repository
This adds the plugin to quartz.config.yaml and installs it to .quartz/plugins/.
To install all plugins referenced in your config that aren’t yet installed (useful when cloning a project or setting up CI):
npx quartz plugin install --from-config
To remove installed plugins that are no longer in your config:
npx quartz plugin prune
Both commands support --dry-run to preview changes. See the plugin CLI reference for full details.
Advanced Source Options
The source field for a plugin can be either a simple string or an object with additional options. The string form is the most common:
Themes from quartz-themes don’t need this: they are published to npm as @quartz-themes/core and the default config already has a (disabled) entry for it:
The string form github:user/repo#branch and the object form { repo, ref } are equivalent ways to specify a branch. Use the object form when you also need subdir or name, or when you prefer a more readable configuration.
Usage
You can customize the behaviour of Quartz by adding, removing and reordering plugins in quartz.config.yaml. Each plugin entry specifies its source, whether it’s enabled, execution order, and any options:
Some plugin options require JavaScript callback functions (e.g. custom sort, filter, or map functions) that can’t be expressed in YAML. For these, use the TS override in quartz.ts:
Options set in quartz.ts are merged with YAML options and take precedence. Plugin overrides must be placed beforeloadQuartzConfig() so they are applied when components are instantiated during config loading. See the plugin-specific documentation for available callback options.
You can see a list of all plugins and their configuration options here.
Fonts can be specified as a simple string or with advanced options in quartz.config.yaml:
quartz.config.yaml
configuration: theme: typography: title: Schibsted Grotesk # optional, defaults to header font header: Schibsted Grotesk body: Source Sans Pro code: IBM Plex Mono
Note
Quartz uses title, but the config’s JSON schema doesn’t list it yet, so an editor with YAML validation may flag it. The warning can be ignored.
For more control over font weights and italics, use the TS override in quartz.ts:
For per-heading font control, self-hosted fonts, or Obsidian theme font bridging, see the Fonts plugin. It can download Google Fonts at build time and serve them locally with fontOrigin: selfHosted, making your site fully self-contained.