This guide covers migrating to Quartz 5 from previous versions. If you’re already on Quartz 5 and want to update to the latest version, see Upgrading Quartz instead.
If you’re new to Quartz entirely, skip this guide and follow the Installation guide instead.
Before You Start: Save Your Content
Before switching branches, make sure your content is safe. Switching to v5 will replace the files in your working directory with the v5 codebase, so your v4 content folder won’t be visible until you restore it.
Copy your content folder somewhere outside the repo before switching:
# macOS / Linux
cp -r content /tmp/quartz-content
# Windows (PowerShell)
Copy-Item -Recurse content $env:TEMP\quartz-contentYour old branch is preserved
Switching branches does not delete your v4 (or v3/hugo) branch. You can always switch back with
git checkout v4to access your old content and configuration.
Getting the v5 Branch
Whether you’re coming from Quartz 4 or Quartz 3, the first step is the same: get the v5 branch onto your machine and push it to your repository.
# Add the official Quartz repository as a remote called "upstream" (skip if already set)
git remote add upstream https://github.com/jackyzha0/quartz.git
# Fetch the v5 branch from the official repository
git fetch upstream v5
# Create a local v5 branch from the official one
git checkout -b v5 upstream/v5
# Install dependencies
npm i
# Push v5 to your GitHub repository
git push -u origin v5Setting Up Your Site
Once you’re on v5, run the interactive setup to configure your site and import your content:
npx quartz createThis will prompt you for:
- A template (
default,obsidian,ttrpg,blog) — pick the one closest to your old setup.obsidianis recommended if you use an Obsidian vault. - A content strategy — choose “Copy” and point it to your backed-up content folder.
If you skipped the create wizard or need to restore your content manually:
# macOS / Linux
cp -r /tmp/quartz-content/* content/
# Windows (PowerShell)
Copy-Item -Recurse $env:TEMP\quartz-content\* content\After running create, install all plugins referenced in the generated config:
npx quartz plugin install --from-configWhat Changed in v5
Quartz 5 introduces a community plugin system that fundamentally changes how plugins and components are managed. Most plugins that were built into Quartz 4 are now standalone community plugins maintained under the quartz-community organization.
Key changes:
- Configuration format: TypeScript (
quartz.config.ts,quartz.layout.ts) → YAML (quartz.config.yaml) - Plugin system: Plugins are now standalone Git repositories, installed via
npx quartz plugin add - Import pattern: Community plugins use
ExternalPlugin.X()(from.quartz/plugins) instead ofPlugin.X()(from./quartz/plugins) - Layout structure:
quartz.layout.tsis gone — layout position is now a per-plugin property inquartz.config.yaml - Page types: A new plugin category for page rendering (content, folder, tag pages)
Most users don't need to worry about these details
If you used the default Quartz 4 configuration (or only changed settings that
npx quartz createprompts for), the setup wizard handles everything. The details below are for users who had custom plugin configurations.
Plugin Reference Table
Mapping v4 plugin names to v5 equivalents:
| v4 | v5 | Type |
|---|---|---|
Plugin.FrontMatter() | ExternalPlugin.NoteProperties() | Community |
Plugin.CreatedModifiedDate() | ExternalPlugin.CreatedModifiedDate() | Community |
Plugin.SyntaxHighlighting() | ExternalPlugin.SyntaxHighlighting() | Community |
Plugin.ObsidianFlavoredMarkdown() | ExternalPlugin.ObsidianFlavoredMarkdown() | Community |
Plugin.GitHubFlavoredMarkdown() | ExternalPlugin.GitHubFlavoredMarkdown() | Community |
Plugin.CrawlLinks() | ExternalPlugin.CrawlLinks() | Community |
Plugin.Description() | ExternalPlugin.Description() | Community |
Plugin.Latex() | ExternalPlugin.Latex() | Community |
Plugin.RemoveDrafts() | ExternalPlugin.RemoveDrafts() | Community |
Plugin.ContentPage() | ExternalPlugin.ContentPage() | Community (pageTypes) |
Plugin.FolderPage() | ExternalPlugin.FolderPage() | Community (pageTypes) |
Plugin.TagPage() | ExternalPlugin.TagPage() | Community (pageTypes) |
Plugin.NotFoundPage() | Plugin.PageTypes.NotFoundPageType() | Internal (pageTypes) |
Plugin.ComponentResources() | Plugin.ComponentResources() (unchanged) | Internal |
Plugin.Assets() | Plugin.Assets() (unchanged) | Internal |
Plugin.Static() | Plugin.Static() (unchanged) | Internal |
Plugin.AliasRedirects() | ExternalPlugin.AliasRedirects() | Community |
Plugin.ContentIndex() | ExternalPlugin.ContentIndex() | Community |
Component layout mapping:
| v4 Layout | v5 Layout |
|---|---|
Component.Explorer() | Plugin.Explorer() |
Component.Graph() | Plugin.Graph() |
Component.Search() | Plugin.Search() |
Component.Backlinks() | Plugin.Backlinks() |
Component.Darkmode() | Plugin.Darkmode() |
Component.Footer() | Plugin.Footer() |
Component.TableOfContents() | Plugin.TableOfContents() |
Component.Head() | Component.Head() (unchanged, internal) |
Component.Spacer() | Plugin.Spacer() |
Updating Your CI/CD
Quartz 5 requires plugins to be installed before building. Add a plugin install step and (optionally) caching to your CI pipeline.
Here’s the recommended pattern, based on the project’s own GitHub Actions:
- name: Cache dependencies
uses: actions/cache@v5
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Cache Quartz plugins
uses: actions/cache@v5
with:
path: .quartz/plugins
key: ${{ runner.os }}-plugins-${{ hashFiles('quartz.lock.json') }}
restore-keys: |
${{ runner.os }}-plugins-
- run: npm ci
- name: Install Quartz plugins
run: npx quartz plugin install
- name: Build Quartz
run: npx quartz buildThe plugin cache uses quartz.lock.json as the cache key, so plugins are only re-downloaded when the lockfile changes.
For non-GitHub CI providers (Cloudflare, Vercel, Netlify), the build command should be:
npx quartz plugin install && npx quartz buildSee hosting for provider-specific setup details.
Setting Your Default Branch to v5
After verifying your site builds and deploys correctly, update your repository’s default branch to v5:
- Go to your repository on GitHub
- Navigate to Settings → General
- Under Default branch, click the switch icon next to your current default branch
- Select
v5from the dropdown and click Update - Confirm the change
This ensures that new clones, pull requests, and GitHub Pages deployments all target v5 by default. Your old v4 branch remains available for reference.
Update your CI triggers
If your CI workflow triggers on a specific branch (e.g.
branches: [v4]), make sure to update it tov5. See the hosting guide for examples.
Notes for Quartz 3 Users
If you’re coming from Quartz 3 (the Hugo-based version), follow the same steps above — get the v5 branch, run npx quartz create, and import your content. There is no need to go through Quartz 4 first.
Key changes from Quartz 3
- Hugo is gone: Quartz now uses a Node-based static-site generation process. No more Go templates or
hugo-obsidian. - Full hot-reload: The development server (
npx quartz build --serve) re-processes all content on every change. - JSX instead of Go templates: Layout components are written in JSX (JavaScript XML), which is significantly easier to customize.
- New plugin system: See Plugins for details on the extensible plugin architecture.
Things to update
- Update your deploy scripts — see the hosting guide.
- Ensure your default branch on GitHub is updated to
v5. - Folder and tag listings have changed:
- Folder descriptions go under
content/<folder-name>/index.md - Tag descriptions go under
content/tags/<tag-name>.md
- Folder descriptions go under
- Custom CSS may need updates if you depended on specific HTML hierarchy or class names from Quartz 3.