Your code has CI/CD. Your docs don’t.
Every 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.
This 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.
The stack
PaperQuire gives you three tools that work together:
.paperquire.yml— project config that locks in your template, branding, and document options- CLI —
paperquire renderandpaperquire batchfor scripting and local builds - GitHub Action —
paperquire/render-actionfor automated builds in CI
Each 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.
Step 1: Add a project config
Drop a .paperquire.yml in your repo root. Every render — GUI, CLI, and CI — picks up these settings automatically:
template: corporate
toc: true
toc-depth: 3
h1-page-break: true
cover:
title: "Project Documentation"
author: "Engineering Team"
branding:
primary-color: "#2563eb"
This is your single source of truth for how documents look. Change it once, and every PDF across every environment updates.
Step 2: Test locally with the CLI
Before committing, verify your docs render correctly:
# Render a single file
paperquire docs/architecture.md -o out/architecture.pdf
# Batch render the entire docs directory
paperquire batch ./docs -o ./out
# Dry run — validate without producing output
paperquire batch ./docs --dry-run
The CLI reads .paperquire.yml automatically. The output is identical to what CI will produce.
Step 3: Automate with the GitHub Action
Add one workflow file and your docs build themselves:
# .github/workflows/docs.yml
name: Build Documentation
on:
push:
paths:
- 'docs/**/*.md'
- '.paperquire.yml'
jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: paperquire/render-action@v1
with:
files: 'docs/*.md'
output: build/pdfs
- uses: actions/upload-artifact@v4
with:
name: documentation
path: build/pdfs/
Every push that touches a Markdown file or the config triggers a fresh build. PDFs are available as downloadable artifacts from the Actions tab.
Real-world patterns
Gate docs in pull requests
Catch formatting issues before they hit main. Reviewers can download the rendered PDFs directly from the PR:
on:
pull_request:
paths: ['docs/**', '.paperquire.yml']
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: paperquire/render-action@v1
with:
files: 'docs/*.md'
output: preview/
- uses: actions/upload-artifact@v4
with:
name: pdf-preview
path: preview/
Ship docs with releases
Attach the latest PDFs to every GitHub release automatically:
on:
release:
types: [published]
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: paperquire/render-action@v1
with:
files: 'docs/*.md'
output: dist/
- name: Attach to release
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload ${{ github.event.release.tag_name }} dist/*.pdf
Customers downloading your release get up-to-date documentation bundled right in.
Nightly builds for large doc sets
For repos with dozens of documents where you don’t want to rebuild on every push:
on:
schedule:
- cron: '0 6 * * 1-5' # Weekdays at 6 AM UTC
workflow_dispatch: # Plus manual trigger
jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: paperquire/render-action@v1
with:
files: 'docs/**/*.md'
output: build/docs
- uses: actions/upload-artifact@v4
with:
name: nightly-docs
path: build/docs/
retention-days: 14
Non-GitHub CI
The CLI works in any CI system. GitLab CI, Jenkins, CircleCI, Azure Pipelines — anywhere you can run a shell command:
# GitLab CI example
build-docs:
image: node:20
script:
- npm install -g paperquire
- paperquire batch ./docs -o ./out --continue-on-error
artifacts:
paths:
- out/*.pdf
Project structure
Here’s what a well-organized docs-as-code repo looks like:
my-project/
├── .paperquire.yml # Shared doc config
├── .github/
│ └── workflows/
│ └── docs.yml # CI pipeline
├── docs/
│ ├── architecture.md
│ ├── api-reference.md
│ ├── onboarding.md
│ └── runbook.md
└── src/
└── ...
Markdown 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.
Why this matters
- No stale docs. Every merge to main produces fresh PDFs.
- No manual steps. No one has to remember to export and upload.
- Consistent branding. The config file enforces the same template and style everywhere.
- Auditable. Git history shows exactly when a document changed and who changed it.
- Reviewable. PR previews let reviewers see the final PDF before merging.
Your documentation pipeline should be as reliable as your deployment pipeline. With PaperQuire, it takes one config file and one workflow to get there.
Get started
- CLI Reference — full command and flag documentation
- GitHub Action docs — inputs, outputs, and examples
- Templates — browse built-in templates
- Download PaperQuire