scope:

Before You Start: Save Your Content

risk:

  • Switching to v5 replaces working-directory files with the v5 codebase.
  • Your v4 content/ folder disappears until restored.
  • Back up content/ 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, v3, or Hugo branch. Restore access with git checkout v4.

Getting the v5 Branch

goal:

  • Fetch official v5.
  • Create local v5.
  • Install dependencies.
  • Push v5 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

interactive_setup:

npx quartz create

prompts:

  • template: choose default, obsidian, ttrpg, or blog; choose the closest match to your old setup.
  • obsidian: recommended for Obsidian vaults.
  • content strategy: choose Copy; select your backed-up content folder.

manual_restore:

# macOS / Linux
cp -r /tmp/quartz-content/* content/
 
# Windows (PowerShell)
Copy-Item -Recurse $env:TEMP\quartz-content\* content\

post_create:

  • Install plugins referenced in the generated config.
npx quartz plugin install --from-config

What Changed in v5

core_change:

  • Quartz 5 uses a community plugin system.
  • Most Quartz 4 built-in plugins now live as standalone repositories under quartz-community.

changes:

  • configuration_format: quartz.config.ts, quartz.layout.tsquartz.config.yaml
  • plugin_system: standalone Git repositories installed via npx quartz plugin add
  • import_pattern: ExternalPlugin.X() from .quartz/plugins replaces Plugin.X() from ./quartz/plugins
  • layout_structure: quartz.layout.ts removed; layout position moved to per-plugin properties in quartz.config.yaml
  • page_types: new plugin category for content, folder, and tag page rendering
  • url_casing: generated URLs now lowercase and hyphenated; My Notes/Hello World.md/my-notes/hello-world
  • v4_url_behavior: preserved original file/folder casing in URLs

URL Casing and SEO

impact:

  • v4 URLs containing uppercase letters return 404 after v5 migration unless redirected.
  • Search indexing changes because Google treats URLs as case-sensitive.

default_solution:

  • AliasRedirects is enabled by default.
  • Build detects source paths containing uppercase characters.
  • Redirect pages generate at old uppercase URLs.
  • SEO signals included:
    • <link rel="canonical">
    • <meta http-equiv="refresh">
    • <meta name="robots" content="noindex">
  • Search engines transfer ranking to new lowercase URLs.

configuration:

  • No manual configuration required.
  • Case redirects are on by default.
  • Disable with enableCaseRedirects: false.
quartz.config.yaml
plugins:
  - source: github:quartz-community/alias-redirects
    enabled: true
    options:
      enableCaseRedirects: false

Hosting on Netlify?

Netlify lowercases all URLs and issues server-side 301 redirects. Case redirect pages are optional but harmless.

Most users do not need these details

If you used the default Quartz 4 configuration, or only changed settings exposed by npx quartz create, the setup wizard handles migration. The details below apply to custom plugin configurations.

Plugin Reference Table

v4_to_v5_plugins:

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

requirements:

  • Install Quartz plugins before building.
  • Add dependency and plugin caching where supported.

github_actions_pattern:

- 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

cache_behavior:

  • Plugin cache key: quartz.lock.json
  • Plugins re-download only when lockfile changes.

non_github_ci:

  • Cloudflare, Vercel, Netlify, and similar providers should use:
npx quartz plugin install && npx quartz build

provider_setup:

Setting Your Default Branch to v5

prerequisite:

  • Verify build and deployment success.

steps:

  • Open the repository on GitHub.
  • Go to SettingsGeneral.
  • Under Default branch, click the switch icon beside the current default branch.
  • Select v5.
  • Click Update.
  • Confirm.

effects:

  • New clones target v5.
  • Pull requests target v5.
  • GitHub Pages deployments target v5.
  • Old v4 branch remains available.

Update your CI triggers

If your CI workflow targets a specific branch, such as branches: [v4], update it to v5. See hosting for examples.

Notes for Quartz 3 Users

path:

  • Use the same migration flow: get v5, run npx quartz create, import content.
  • Quartz 4 migration is unnecessary.

Key changes from Quartz 3

changes:

  • hugo_removed: Quartz now uses Node-based static-site generation; no Go templates or hugo-obsidian.
  • full_hot_reload: npx quartz build --serve re-processes all content on every change.
  • jsx_layouts: layout components use JSX instead of Go templates.
  • plugin_system: see Plugins.

Things to update

updates:

  • Deploy scripts: see hosting.
  • GitHub default branch: set to v5.
  • Folder and tag listings:
    • folder descriptions: content/<folder-name>/index.md
    • tag descriptions: content/tags/<tag-name>.md
  • Custom CSS: update selectors if they depended on Quartz 3 HTML hierarchy or class names.