Building the site and PDFs🔗

PolicyPress builds both the static site and all PDFs in a single pipeline run. See Installation for the full pipeline definition (GitHub Actions or Azure DevOps).

The outputs:

  • Static site → public/ (Zola output, ready to serve)
  • PDFs → public/pdfs/ (one per policy, named by title and version)

Deploying the site🔗

After the build, push public/ to your static host. For access-controlled deployments (restricting who can view the site), see Securing Your Repository first — that guide covers setting up Azure AD SSO, GitHub Pages org access, and Cloudflare Zero Trust.

Add the deploy step after the build in your pipeline:

- uses: Azure/static-web-apps-deploy@v1
  with:
    azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
    repo_token: ${{ secrets.GITHUB_TOKEN }}
    action: "upload"
    app_location: "public"

Store the SWA deployment token in Settings → Secrets and variables → Actions as AZURE_STATIC_WEB_APPS_API_TOKEN. Get the token from the SWA resource in the Azure Portal.

- task: AzureStaticWebApp@0
  inputs:
    azure_static_web_apps_api_token: $(AZURE_STATIC_WEB_APPS_API_TOKEN)
    action: upload
    app_location: public

Store the SWA deployment token as a pipeline variable (AZURE_STATIC_WEB_APPS_API_TOKEN) in Pipelines → [your pipeline] → Edit → Variables. Mark it as secret. Get the token from the SWA resource in the Azure Portal.

Add a deploy step after the build in your GitHub Actions workflow:

- uses: actions/deploy-pages@v4
  with:
    artifact_name: site

In Settings → Pages, set source to GitHub Actions.

The simplest option is the Cloudflare Pages GitHub Action:

- uses: cloudflare/pages-action@v1
  with:
    apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
    projectName: your-project-name
    directory: public

Or connect your repository directly in the Cloudflare dashboard (Pages → Create a project → Connect to Git). Set the build output directory to public and leave the build command blank — PolicyPress pre-builds everything.

Copy public/ to any web server that can serve static files:

- name: Deploy to server
  run: rsync -az --delete public/ user@your-server:/var/www/policies/

nginx, Caddy, S3 static hosting, and any CDN that can serve a directory all work. No server-side processing is required.

Distributing PDFs🔗

PDFs land in the pdfs artifact (GitHub Actions) or pipeline artifact (Azure DevOps). From there you can:

  • Attach them to a GitHub/ADO release for versioned archival
  • Copy them to an S3 bucket or SharePoint library for auditor access
  • Send them directly to auditors as email attachments

To generate a redacted build for external distribution while keeping the full build for internal use, run the pipeline a second time with redact_mode: true:

# GitHub Actions — manual trigger with redact_mode: true
- uses: sc2in/policypress@v1
  with:
    redact_mode: 'true'

# Azure DevOps — set parameter at queue time, or add a separate pipeline stage
- bash: policypress --redact -c config.toml -o dist-redacted
  displayName: Build redacted PDFs

Manual / local build🔗

If you need to build outside of CI, use the Nix app (no devshell required):

# Live preview with hot reload
nix run github:sc2in/policypress#serve

# One-shot build: static site + PDFs
nix run github:sc2in/policypress#preview

# PDFs only
nix run github:sc2in/policypress -- -c config.toml -o public

# Redacted PDFs only
nix run github:sc2in/policypress -- -c config.toml -o dist --redact