Deploying a Quartz site to Netlify
I replaced my previous Jekyll static website with
Quartz (you are looking at the end result!).
I didn’t want to give up my existing Netlify setup deploying the site, but Quartz is not just a static site (even though it’s based on Hugo), so Netlify can’t just automatically build it.
Quartz’s original deploy instructions build the Hugo site with GitHub Actions and deploy it to GitHub Pages. This guide is an extension of the upstream instructions, but deploy the final result on Netlify.
# Why it doesn’t work out of the box
Netlify recognizes popular static site generators (such as Hugo) to build the static site in its own CI system.
Quartz is a bit special, requiring one extra build step compared to a regular Hugo site. Quartz has a CLI tool that scans the notes and precomputes the graph representation. This extra build step is obviously not supported by Netlify, and there are no Netlify plugins doing this step as of today.
# The deploy workflow
Instead of creating a plugin, I decided to embrace the existing GitHub Actions workflow and just replace the last step (deploy to GitHub pages) with a Netlify equivalent. Netlify has a CLI tool that lets me skip its CI build system and directly deploy a pre-built folder on Netlify.
This means that the build happens in GitHub’s CI environment and Netlify just receives the final static site to deploy.
You can see my full workflow here, but the only difference is the last step of the Quartz deploy workflow:
the official Netlify GitHub Action and we tell it to create a prod deployment of the
public folder (Hugo’s build folder).
Don’t forget to define the two secret values as GitHub Actions secrets! Both values are available under your Netlify settings.
# Pull request deployments
We can also recreate Netlify’s PR deploy preview feature using a plain GitHub Actions workflow. This workflow is not much different from the above deploy workflow, the main difference is in handling Netlify’s special deploy preview URL (such as
Again, the whole workflow is available in my repo.
We need to tell Hugo to use this URL instead of the hard-coded base URL, which is a bit of a chicken-and-egg situation: the Hugo build happens before Netlify’s process starts and assigns a temporary URL. Fortunately, we can override the dynamic part of this URL (called alias), so let’s create a unique alias as an env var from the PR number and the commit SHA:
Next, we tell Hugo to override the base URL (normally defined in
Finally, we tell Netlify to use our custom alias:
As a cherry on top, we can also automatically comment the deploy URL on the pull request: