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.mode | render.target | Build command | Deployed artifact |
|---|---|---|---|
static (default) | any | nuxt generate | .output/public/ |
hybrid | node | nuxt build | .output/ (node-server preset) |
hybrid | cloudflare-pages | nuxt build | .output/public/ (CF Worker embedded) |
hybrid | cloudflare-workers | nuxt build | .output/ + wrangler.toml |
ssr | node | nuxt build | .output/ (node-server preset) |
ssr | cloudflare-pages | nuxt build | .output/public/ (CF Worker embedded) |
ssr | cloudflare-workers | nuxt 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.*
| Option | Type | Default | Description |
|---|---|---|---|
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.routeRules | attrs | {} | 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.*
| Option | Type | Default | Description |
|---|---|---|---|
deploy.provider | "none" | "cloudflare-pages" | "cloudflare-workers" | "none" | Enables nix run .#docs-deploy and the generated workflow |
deploy.projectName | string | "" | Cloudflare Pages/Workers project name (required when provider is not "none") |
deploy.branch | string | null | null | Deploy branch (Pages only); uses the wrangler default when null |
deploy.emitWorkflow | bool | true | Write .github/workflows/docyard-cloudflare.yml during managed prep |
deploy.d1DatabaseId | string | null | null | Cloudflare 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/:
| Host | Command / action |
|---|---|
| Netlify | netlify deploy --dir docs/dist --prod |
| Vercel | vercel --cwd docs/dist --prod |
| AWS S3 | aws s3 sync docs/dist s3://your-bucket --delete |
| Firebase | firebase 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.