DOCS

Deployment

Deploy your docyard site to GitHub Pages, Cloudflare Pages, or any static host.

Deployment

nix run .#docs-build produces a static site in docs/dist/ (the default site.output). That directory can be uploaded to any static host with no server-side runtime required.

This page shows ready-to-use GitHub Actions workflows for the two most common targets. Workflow templates are also available in templates/workflows/ to copy into your own repository.

Render modes

Docyard supports three render modes and two Cloudflare deployment targets. The mode and target together determine what Nuxt builds and what artifact is deployed.

render.moderender.targetBuild commandDeployed artifact
static (default)anynuxt generate.output/public/
hybridnodenuxt build.output/ (node-server preset)
hybridcloudflare-pagesnuxt build.output/public/ (CF Worker embedded)
hybridcloudflare-workersnuxt build.output/ + wrangler.toml
ssrnodenuxt build.output/ (node-server preset)
ssrcloudflare-pagesnuxt build.output/public/ (CF Worker embedded)
ssrcloudflare-workersnuxt build.output/ + wrangler.toml

static (default) runs nuxt generate and produces a fully static bundle. No render.* options are needed; today's behavior is unchanged.

hybrid pre-renders all content pages by default (crawl + force-prerender) and supports opt-in SSR routes via render.routeRules. This keeps the Cloudflare Worker small — most weight stays in static CDN assets.

ssr renders on demand. Only routes listed in render.prerender are frozen at build time; everything else is rendered at the edge on each request.

llms.txt / llms-full.txt remain static build artifacts in every mode. OG images remain build-time only; they are generated on node and static targets, but not on Cloudflare targets in hybrid mode@nuxt/content uses the D1 adapter at compile time for the CF preset, and D1 bindings are not present in a local build. Use render.mode = "static" if social cards are required on Cloudflare Pages.

Options reference

site.render.*

OptionTypeDefaultDescription
render.mode"static" | "hybrid" | "ssr""static"Render mode
render.target"node" | "cloudflare-pages" | "cloudflare-workers""node"Deploy runtime (ignored when mode = "static")
render.prerender[string][]Extra routes to force-prerender on top of the crawler
render.routeRulesattrs{}Merged into Nitro routeRules (per-route SSR/ISR/headers escape hatch)
render.contentRuntime"build" | "d1""build""build" ships the SQLite dump; "d1" binds Cloudflare D1 at the edge (Cloudflare targets only)

site.deploy.*

OptionTypeDefaultDescription
deploy.provider"none" | "cloudflare-pages" | "cloudflare-workers""none"Enables nix run .#docs-deploy and the generated workflow
deploy.projectNamestring""Cloudflare Pages/Workers project name (required when provider is not "none")
deploy.branchstring | nullnullDeploy branch (Pages only); uses the wrangler default when null
deploy.emitWorkflowbooltrueWrite .github/workflows/docyard-cloudflare.yml during managed prep
deploy.d1DatabaseIdstring | nullnullCloudflare D1 database ID (required when render.contentRuntime = "d1"); obtain with wrangler d1 create <projectName>-content

GitHub Pages

GitHub Pages is the default target — render.mode = "static" (the default) and no render.* or deploy.* options are needed.

1. Enable GitHub Pages

In your repository go to Settings → Pages and set the Source to GitHub Actions.

2. Add the workflow

Create .github/workflows/docs.yml:

name: Docs

on:
  push:
    branches: [main, master]
  workflow_dispatch:

concurrency:
  group: pages-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Nix
        uses: DeterminateSystems/nix-installer-action@v14

      - name: Cache Nix store
        uses: DeterminateSystems/magic-nix-cache-action@v8

      - name: Build docs
        run: nix run .#docs-build

      - name: Upload Pages artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: docs/dist

  deploy:
    name: Deploy
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

DeterminateSystems/magic-nix-cache-action caches Nix store paths across runs, cutting subsequent build times significantly.

3. Set the canonical URL

Add url to your flake config so the site generates correct absolute links and a valid llms.txt:

docyard.site = {
  managed = true;
  url     = "https://your-org.github.io/your-repo";
  # ...
};

If your repository name differs from the Pages domain root (i.e. you're not at your-org.github.io), add a base in site.extraEnv:

docyard.site.extraEnv = {
  NUXT_APP_BASE_URL = "/your-repo/";
};

Cloudflare Pages

Cloudflare Pages runs Nuxt in hybrid or SSR mode via a Cloudflare Worker. In managed mode, Docyard sets the correct Nitro preset, switches to nuxt build, and optionally generates the GitHub Actions workflow.

1. Create a Pages project

In the Cloudflare dashboard go to Workers & Pages → Create → Pages → Connect to Git and follow the prompts, or create an empty project to deploy via the API.

2. Configure the flake

docyard.site = {
  managed    = true;
  url        = "https://myproject.pages.dev";
  render.mode    = "hybrid";
  render.target  = "cloudflare-pages";
  deploy.provider    = "cloudflare-pages";
  deploy.projectName = "myproject";
};

3. Add secrets and run the build once

Add CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID as repository secrets (Settings → Secrets and variables → Actions), then run:

nix run .#docs-build

With deploy.emitWorkflow = true (the default), this writes .github/workflows/docyard-cloudflare.yml into your repository. Commit and push it; subsequent pushes to main will build and deploy automatically.

Alternatively, deploy locally with credentials in your environment:

export CLOUDFLARE_API_TOKEN=...
export CLOUDFLARE_ACCOUNT_ID=...
nix run .#docs-deploy

Other static hosts

Any host that accepts a directory of static files works. After running nix run .#docs-build locally or in CI, upload docs/dist/:

HostCommand / action
Netlifynetlify deploy --dir docs/dist --prod
Vercelvercel --cwd docs/dist --prod
AWS S3aws s3 sync docs/dist s3://your-bucket --delete
Firebasefirebase deploy --only hosting (set public: docs/dist in firebase.json)

Custom output directory

If you prefer a different output path, set site.output in your flake config:

docyard.site = {
  managed = true;
  output  = "public";   # docs-build writes to public/ instead of docs/dist/
};

Update path: docs/dist in the workflow to match.

Caching build times

The magic-nix-cache-action caches the full Nix store. On a cold run the first build downloads all dependencies; subsequent pushes only rebuild what changed and typically complete in under two minutes.

For projects with Python or Rust API extraction, the extractor binaries are also cached through the Nix store, so repeated CI runs pay no re-download cost.