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-content

Your old branch is preserved

Switching branches does not delete your v4 (or v3/hugo) branch. You can always switch back with git checkout v4 to 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 v5

Setting Up Your Site

Once you’re on v5, run the interactive setup to configure your site and import your content:

npx quartz create

This will prompt you for:

  • A template (default, obsidian, ttrpg, blog) — pick the one closest to your old setup. obsidian is 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-config

What 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 of Plugin.X() (from ./quartz/plugins)
  • Layout structure: quartz.layout.ts is gone — layout position is now a per-plugin property in quartz.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 create prompts 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:

v4v5Type
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 Layoutv5 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 build

The 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 build

See 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:

  1. Go to your repository on GitHub
  2. Navigate to Settings → General
  3. Under Default branch, click the switch icon next to your current default branch
  4. Select v5 from the dropdown and click Update
  5. 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 to v5. 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

  1. Hugo is gone: Quartz now uses a Node-based static-site generation process. No more Go templates or hugo-obsidian.
  2. Full hot-reload: The development server (npx quartz build --serve) re-processes all content on every change.
  3. JSX instead of Go templates: Layout components are written in JSX (JavaScript XML), which is significantly easier to customize.
  4. 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
  • Custom CSS may need updates if you depended on specific HTML hierarchy or class names from Quartz 3.