Use Freeze to Cache Expensive Notebooks

Avoid re-executing costly computations (MCMC, deep learning, simulations) on every docs build using Quarto’s freeze feature.

Great Docs enables freeze: auto by default, which means executable code cells are only re-executed when their source .qmd file changes. This recipe explains how freeze works in practice and how to manage the cache for expensive notebooks.

How It Works

Great Docs uses Quarto’s freeze mechanism to cache execution outputs in a _freeze/ directory:

  1. First build: all executable cells run and their outputs are cached
  2. Subsequent builds: only pages whose .qmd source has changed are re-executed
  3. Cache round-trip: Great Docs automatically restores _freeze/ into the build directory before rendering, and copies the updated cache back to the project root after rendering

No configuration is needed — this works out of the box.

Managing Expensive Pages

For pages with especially expensive computations (MCMC sampling, large simulations, GPU workloads), you may want finer control. Use freeze: true in the page’s frontmatter to lock it completely:

user_guide/benchmarks.qmd
---
title: "Benchmarks"
freeze: true
---

With freeze: true, the page is never re-executed during a project render, even if its source changes. The only way to update its outputs is an explicit great-docs freeze.

Updating the Freeze Cache

When you change a frozen page’s source code or input data, use the great-docs freeze command to re-execute it and update the cache:

Terminal
great-docs freeze user_guide/benchmarks.qmd

This command:

  1. Renders the specified page inside the build directory (always executing code)
  2. Copies the updated _freeze/ entries back to your project root
  3. Tells you exactly what to commit

You can freeze multiple pages at once:

Terminal
great-docs freeze user_guide/benchmarks.qmd user_guide/mcmc-demo.qmd

Or specify a custom persistence directory:

Terminal
great-docs freeze user_guide/benchmarks.qmd --freeze-dir docs/_freeze

The command prints a ready-to-use git add + git commit hint when it finishes.

CI Workflow

The great-docs setup-github-pages command generates a workflow with built-in freeze caching using actions/cache. The cache key includes both your dependency lockfile and .qmd content hashes:

.github/workflows/docs.yml
- name: Restore freeze cache
  uses: actions/cache@v4
  with:
    path: _freeze/
    key: freeze-${{ hashFiles('**/uv.lock', ...) }}-${{ hashFiles('**/*.qmd') }}
    restore-keys: |
      freeze-${{ hashFiles('**/uv.lock', ...) }}-
      freeze-

- name: Build docs
  run: great-docs build

This ensures that dependency updates (new package releases, bugfixes) automatically invalidate the cache, while documentation-only changes get fast partial cache hits. GitHub Actions caches are branch-scoped, so PR branches benefit from main’s cache but never pollute it.

Advanced: Additional Pre-render Scripts

If you need custom scripts to run before rendering (e.g., data generation), add them via pre_render. Great Docs automatically runs the freeze restore before your scripts so you don’t need to include it yourself:

great-docs.yml
freeze: auto
pre_render:
  - scripts/generate-data.py

Scripts run in order after the freeze restore, and each must exist at the specified path relative to your project root.

When to Re-execute

The freeze cache should be refreshed when:

  • Input data changes (not just source code)
  • Package API changes affect output
  • You want to update rendered figures or tables

To re-execute specific pages:

Terminal
great-docs freeze user_guide/benchmarks.qmd

To force a full re-execution of all frozen pages, use --clean:

Terminal
great-docs freeze --clean user_guide/benchmarks.qmd user_guide/sampling.qmd

Build Log

When freeze is configured, the build log reports it:

 Step 1  Prepare build directory ················· Ready
          Freeze mode: auto

This confirms that the freeze configuration is active and the cache restore will happen automatically.

Per-Page Overrides

Since freeze is enabled project-wide by default, all executable pages are cached. To force a specific page to always re-execute, add freeze: false to its frontmatter:

a-page-that-must-always-execute.qmd
---
title: "Live Status"
freeze: false
---

This is useful for pages that pull live data or display current status information.

Disabling Freeze

To disable freeze entirely and re-execute all pages on every build, set freeze: false in great-docs.yml:

great-docs.yml
freeze: false