Skip to content
duxt

Cache remote sources and OG images

Reuse downloaded public repositories and rendered social cards safely between CI builds.

Two expensive build inputs can outlive an ephemeral CI runner without becoming part of the deployed site: Content's downloaded public repositories and the rendered OG-image cache. They have different invalidation rules, so duxt exposes one command for each instead of sharing a key.

Cache downloaded public sources

duxt-cache-key loads the resolved source list, after latest and release selection have become concrete refs, and emits the exact cache path and key.

- name: Resolve the remote-source cache key
  id: sources
  run: duxt-cache-key --root . --github >> "$GITHUB_OUTPUT"

- name: Restore the downloaded sources
  if: steps.sources.outputs.cacheable == 'true'
  uses: actions/cache@v6
  with:
    path: ${{ steps.sources.outputs.paths }}
    key: ${{ steps.sources.outputs.key }}

Use the directory containing the consuming Nuxt app as --root; use . when the app is the repository root. Run the command after installing dependencies and before the Nuxt build.

The emitted paths include Content's downloaded checkouts and exclude contents.sqlite*. That database is a parse result, not a download: restoring it could hide an authored content change behind stale parsed rows.

The cache is public sources only. A cache produced on a protected branch can be restored by a pull request, so one private, SSH or credential-bearing remote sets cacheable=false for the whole list. The workflow then skips the cache; duxt never mixes an unsafe remote with an otherwise public cache.

Run the command without --github to see the redacted inputs and the reason a site is or is not cacheable:

duxt-cache-key --root .

Cache rendered OG images

duxt-og-cache emits a rolling Actions key. The renderer dependency versions form its namespace, while the source revision lets a successful build save the new images it added instead of freezing the first exact hit forever.

- name: Resolve the OG image cache key
  id: og
  run: duxt-og-cache --root . --run "$GITHUB_SHA" --github >> "$GITHUB_OUTPUT"

- name: Restore the rendered OG images
  uses: actions/cache@v6
  with:
    path: ${{ steps.og.outputs.path }}
    key: ${{ steps.og.outputs.key }}
    restore-keys: ${{ steps.og.outputs['restore-keys'] }}

The consuming site's Nuxt config must also register the OG cache integration exported by @kirchdev/duxt/og-image-cache. That build-side fingerprint covers the site-owned inputs the pre-build CLI cannot safely load, such as template options and fonts. When they move, the integration empties the restored directory before any stale image can be served.

After the build, report what the cache actually reused:

duxt-og-cache --root . --report --since "$STARTED_MS" --log build.log

Add --github when the report is written to $GITHUB_OUTPUT; its plain form is suited to a terminal or $GITHUB_STEP_SUMMARY.

Checklist

  • Dependencies are installed before either key command runs.
  • --root names the consuming Nuxt application.
  • The source cache step is conditional on cacheable == 'true'.
  • The source cache uses no broad restore key.
  • contents.sqlite* remains excluded from the source cache.
  • No private or authenticated source is forced into an Actions cache.
  • The OG cache uses the emitted rolling restore keys.
  • The consuming Nuxt config fingerprints site-owned rendering inputs.
  • The post-build report uses the same cache directory as the build.
Was this page helpful?