Quarto websites are a great way for people familiar with code notebooks like Rmarkdown and Jupyter to share their work on the internet. If you use GitHub for version control of your site’s code, then GitHub Pages is a natural and convenient way to publish your site. But because Quarto is relatively new, the methods for publishing on various platforms including GitHub Pages are still evolving. I wasn’t satisfied with the existing methods for publishing Quarto sites on GitHub pages, so I created my own.
Prerequisites
- A Quarto site in a GitHub repository that can successfully be rendered and previewed on your local computer.
Existing methods for Quarto sites on GitHub Pages
The Quarto GitHub Pages documentation offers three methods of publishing your site on GitHub pages, but they each have disadvantages.
- Render to
docs/
folder
With this method, you change the Quarto output directory to docs/
, which is a directory GitHub Pages can serve content from. This is easy to set up, but it requires checking the rendered HTML pages into version control. Generally it’s frowned upon to have version control tracking content that can be regenerated from other source code in the repository, so I would like to avoid using this method.
- Use
quarto publish gh-pages
Quarto includes its own publish command for many platforms including GitHub Pages. This method works by creating a branch in the repository called gh-pages
which contains the rendered content. This method also has rendered content tracked in version control, although because it is in a separate branch, it can be committed only when you want. The gh-pages
branch method is based on an old GitHub Pages publishing option. This branch is somewhat separate from the rest of the version control tree. Because the gh-pages
branch is never intended to be merged back into the default branch, this feels too much like a hack to me and goes against the purpose of branches in version control.
- Use GitHub Actions
The Quarto documentation provides a GitHub Action (workflows which are run by GitHub upon certain conditions) to automatically publish the site when you push code to the GitHub reposiory. But this action just runs quarto publish gh-pages
behind the scenes and so has all the problems of that method.
Improved method: a better GitHub Actions workflow
A better method that I am using is based on GitHub Actions, but doesn’t use the workflow provided by Quarto. Instead it’s based on a GitHub template workflow for publishing static content.
How to use
First, enable GitHub Pages in your repository by selecting GitHub Actions as the Source.
Next, set up Quarto’s freeze feature by editing _quarto.yml
:
_quarto.yml
# ...
execute:
freeze: auto
# ...
Finally, copy this code into the file .github/workflows/publish.yml
in your repository (create it if it doesn’t exist):
.github/workflows/publish.yml
# Workflow for rendering and deploying quarto site to GitHub Pages
# Based on the GitHub example static content deploy action
name: Deploy Quarto site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
# Single deploy job since we're just deploying
render-deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Quarto
uses: quarto-dev/quarto-actions/setup@v2
- name: Render
uses: quarto-dev/quarto-actions/render@v2
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload quarto render output directory
path: '_site'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
Now when you push to the default branch of your repository, this action will render your site using the frozen computations, bundle the rendered static HTML content, and deploy it to GitHub Pages. After the workflow runs, you can access the site at https://<your-username>.github.io/
if this is your user pages repository, or https://<your-username>.github.io/<repo-name>
if this is any other repository.
Additional configuration
- If your default branch isn’t called “main”, change the
on:
options:
.github/workflows/publish.yml
# ...
on:
# Runs on pushes targeting the default branch
push:
branches: ["your-default-branch"] # <---- **CHANGE THIS LINE**
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# ...
- If your site renders to a folder other than
_site
, change the “Upload artifact” step accordingly:
.github/workflows/publish.yml
# ...
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload quarto render output directory
path: 'your-render-output-path' # <---- **CHANGE THIS LINE**
# ...
- If your Quarto site is not located in the root of your repository, for example if using quarto to create documentation for your code, add a path option to the “Render” step and also change the “Upload artifact” step option:
.github/workflows/publish.yml
# ...
- name: Render
uses: quarto-dev/quarto-actions/render@v2
with:
path: 'your-quarto-folder' # <---- **CHANGE THIS LINE**
# ...
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload quarto render output directory
path: 'your-quarto-folder/_site' # <---- **CHANGE THIS LINE**
# ...
These changes can be combined if necessary.
How it works
This GitHub action works by rendering your site on the GitHub server (the “runner”), then packaging the resulting static content and deploying it on the GitHub Pages server. It doesn’t require write access to your repository. Because of the Quarto freeze option, the runner doesn’t need to have R, Python or any computational packages installed. The rendered content is exactly what you would have seen in a preview on your local computer.