{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreicu5r5vl4ciqicuqcj73ulaonzxc72v43mrcd4uzybezvr6ghhkrm",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mp5fy7huimj2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreid4pijpmwpcqj4egvcygc4ldk3fqvipblygihmsmkryocprrzrpim"
    },
    "mimeType": "image/webp",
    "size": 61894
  },
  "path": "/paperquire_e3fdb510bbe49c/docs-as-code-build-a-cicd-pipeline-for-your-documentation-3278",
  "publishedAt": "2026-06-25T21:37:07.000Z",
  "site": "https://dev.to",
  "tags": [
    "cicd",
    "automation",
    "tutorial",
    "CLI Reference",
    "GitHub Action docs",
    "Templates",
    "Download PaperQuire"
  ],
  "textContent": "##  Your code has CI/CD. Your docs don't.\n\nEvery modern engineering team has automated builds, tests, and deployments for their code. But documentation? That's still someone manually exporting a PDF, uploading it to Confluence, and hoping it's the latest version.\n\nThis post shows you how to treat documentation like code: version-controlled Markdown in a Git repo, automatically rendered to branded PDFs on every push. No manual steps, no stale documents.\n\n##  The stack\n\nPaperQuire gives you three tools that work together:\n\n  1. **`.paperquire.yml`** — project config that locks in your template, branding, and document options\n  2. **CLI** — `paperquire render` and `paperquire batch` for scripting and local builds\n  3. **GitHub Action** — `paperquire/render-action` for automated builds in CI\n\n\n\nEach one builds on the previous. The config file means no one has to remember flags. The CLI means you can test locally. The action means it happens automatically.\n\n##  Step 1: Add a project config\n\nDrop a `.paperquire.yml` in your repo root. Every render — GUI, CLI, and CI — picks up these settings automatically:\n\n\n\n    template: corporate\n    toc: true\n    toc-depth: 3\n    h1-page-break: true\n    cover:\n      title: \"Project Documentation\"\n      author: \"Engineering Team\"\n    branding:\n      primary-color: \"#2563eb\"\n\n\nThis is your single source of truth for how documents look. Change it once, and every PDF across every environment updates.\n\n##  Step 2: Test locally with the CLI\n\nBefore committing, verify your docs render correctly:\n\n\n\n    # Render a single file\n    paperquire docs/architecture.md -o out/architecture.pdf\n\n    # Batch render the entire docs directory\n    paperquire batch ./docs -o ./out\n\n    # Dry run — validate without producing output\n    paperquire batch ./docs --dry-run\n\n\nThe CLI reads `.paperquire.yml` automatically. The output is identical to what CI will produce.\n\n##  Step 3: Automate with the GitHub Action\n\nAdd one workflow file and your docs build themselves:\n\n\n\n    # .github/workflows/docs.yml\n    name: Build Documentation\n\n    on:\n      push:\n        paths:\n          - 'docs/**/*.md'\n          - '.paperquire.yml'\n\n    jobs:\n      render:\n        runs-on: ubuntu-latest\n        steps:\n          - uses: actions/checkout@v4\n\n          - uses: paperquire/render-action@v1\n            with:\n              files: 'docs/*.md'\n              output: build/pdfs\n\n          - uses: actions/upload-artifact@v4\n            with:\n              name: documentation\n              path: build/pdfs/\n\n\nEvery push that touches a Markdown file or the config triggers a fresh build. PDFs are available as downloadable artifacts from the Actions tab.\n\n##  Real-world patterns\n\n###  Gate docs in pull requests\n\nCatch formatting issues before they hit main. Reviewers can download the rendered PDFs directly from the PR:\n\n\n\n    on:\n      pull_request:\n        paths: ['docs/**', '.paperquire.yml']\n\n    jobs:\n      preview:\n        runs-on: ubuntu-latest\n        steps:\n          - uses: actions/checkout@v4\n\n          - uses: paperquire/render-action@v1\n            with:\n              files: 'docs/*.md'\n              output: preview/\n\n          - uses: actions/upload-artifact@v4\n            with:\n              name: pdf-preview\n              path: preview/\n\n\n###  Ship docs with releases\n\nAttach the latest PDFs to every GitHub release automatically:\n\n\n\n    on:\n      release:\n        types: [published]\n\n    jobs:\n      docs:\n        runs-on: ubuntu-latest\n        steps:\n          - uses: actions/checkout@v4\n\n          - uses: paperquire/render-action@v1\n            with:\n              files: 'docs/*.md'\n              output: dist/\n\n          - name: Attach to release\n            env:\n              GH_TOKEN: ${{ github.token }}\n            run: gh release upload ${{ github.event.release.tag_name }} dist/*.pdf\n\n\nCustomers downloading your release get up-to-date documentation bundled right in.\n\n###  Nightly builds for large doc sets\n\nFor repos with dozens of documents where you don't want to rebuild on every push:\n\n\n\n    on:\n      schedule:\n        - cron: '0 6 * * 1-5'  # Weekdays at 6 AM UTC\n      workflow_dispatch:        # Plus manual trigger\n\n    jobs:\n      render:\n        runs-on: ubuntu-latest\n        steps:\n          - uses: actions/checkout@v4\n\n          - uses: paperquire/render-action@v1\n            with:\n              files: 'docs/**/*.md'\n              output: build/docs\n\n          - uses: actions/upload-artifact@v4\n            with:\n              name: nightly-docs\n              path: build/docs/\n              retention-days: 14\n\n\n###  Non-GitHub CI\n\nThe CLI works in any CI system. GitLab CI, Jenkins, CircleCI, Azure Pipelines — anywhere you can run a shell command:\n\n\n\n    # GitLab CI example\n    build-docs:\n      image: node:20\n      script:\n        - npm install -g paperquire\n        - paperquire batch ./docs -o ./out --continue-on-error\n      artifacts:\n        paths:\n          - out/*.pdf\n\n\n##  Project structure\n\nHere's what a well-organized docs-as-code repo looks like:\n\n\n\n    my-project/\n    ├── .paperquire.yml          # Shared doc config\n    ├── .github/\n    │   └── workflows/\n    │       └── docs.yml         # CI pipeline\n    ├── docs/\n    │   ├── architecture.md\n    │   ├── api-reference.md\n    │   ├── onboarding.md\n    │   └── runbook.md\n    └── src/\n        └── ...\n\n\nMarkdown lives alongside code. The config file and workflow are checked in. Anyone cloning the repo can render docs locally with `paperquire batch ./docs`, and CI handles the rest.\n\n##  Why this matters\n\n  * **No stale docs.** Every merge to main produces fresh PDFs.\n  * **No manual steps.** No one has to remember to export and upload.\n  * **Consistent branding.** The config file enforces the same template and style everywhere.\n  * **Auditable.** Git history shows exactly when a document changed and who changed it.\n  * **Reviewable.** PR previews let reviewers see the final PDF before merging.\n\n\n\nYour documentation pipeline should be as reliable as your deployment pipeline. With PaperQuire, it takes one config file and one workflow to get there.\n\n##  Get started\n\n  * CLI Reference — full command and flag documentation\n  * GitHub Action docs — inputs, outputs, and examples\n  * Templates — browse built-in templates\n  * Download PaperQuire\n\n",
  "title": "Docs as Code: Build a CI/CD Pipeline for Your Documentation"
}