Content Workflows for Documentation Teams
A static site is a joy for engineers and, without deliberate work, an obstacle course for everyone else. The generator that makes builds fast and hosting cheap also puts the content behind a toolchain: a repository, a branch, a pull request, a local build. Documentation teams include technical writers, support engineers, product managers and occasional contributors, and most of them should not have to install anything to fix a sentence.
This guide covers the workflow around the build: how content moves from an idea to production, what a review actually needs, where a CMS earns its place, how to schedule publication without runtime logic, and which checks belong in the build so reviewers can focus on meaning. It sits under Production-Ready Deployment & CI/CD Workflows.
Decide the Entry Points
Three interfaces cover a documentation team, and a healthy setup offers at least two.
Local checkout. Full-time writers with a technical background usually prefer this: a fast dev server, their own editor, and the ability to run the build gates before pushing. Its cost is onboarding — a toolchain install, a Node version, a first successful build.
Web editor. The repository host's own editor handles a typo, a broken link or a version number without anyone leaving the browser. It produces a normal branch and pull request, so the rest of the process is unchanged. This is the cheapest possible fix path and it costs nothing to enable.
Git-backed CMS. Decap, Sveltia, Tina, Keystatic and similar tools present a normal editing UI — fields, previews, media uploads — and commit Markdown behind the scenes. They earn their place when the front matter is structured enough that hand-editing YAML is error-prone, or when contributors genuinely will not use a code host. The setup is covered in Wiring a Headless CMS to a Static Build.
| Interface | Best for | Onboarding cost | Weakness |
|---|---|---|---|
| Local checkout | Daily writers, engineers | Hours | Toolchain problems block writing |
| Web editor | Occasional fixes | Minutes | No preview until CI runs |
| Git-backed CMS | Structured content, non-technical authors | Days to set up | Another system to maintain |
| Headless CMS + API | Content reused across products | Weeks | Build must fetch; loses Git history for content |
Make the Preview the Review
A documentation diff tells you what changed; a preview tells you whether it is right. Since previews are cheap on static hosting, make the rendered page the primary review artifact and the diff secondary.
That means the preview URL must appear on the pull request automatically, within a couple of minutes, on every push — the mechanics are in Preview Environments for Pull Requests and, host-specifically, Setting Up Deploy Previews on Netlify for Every Pull Request. A preview that takes ten minutes is a preview nobody waits for.
Keep the review checklist short enough that reviewers use it every time:
- Does the page answer the question its title asks?
- Are the code samples runnable, and do they match the version in use?
- Does every new claim carry a number or a source?
- Do the links resolve, and do they point at the most specific page available?
- Would a reader landing here from search understand it without the surrounding section?
Everything mechanical — link resolution, front matter validity, spelling, word counts — belongs in the build, not on this list.
Who reviews matters as much as what they check. Documentation benefits from two different reviewers doing two different jobs, and conflating them slows both: a subject-matter reviewer confirms the content is true, and an editorial reviewer confirms it is clear and consistent with the rest of the site. On a small team one person does both, and it helps to do them as two passes rather than one — read for accuracy, then read for clarity — because the two kinds of attention do not mix well.
Set an explicit expectation for review latency, and make it short. A day is workable; a week means authors context-switch away and return to a stale branch. If reviews routinely take longer, the problem is usually queueing rather than effort: nobody owns the queue, so every pull request waits for a volunteer. Assigning a rotating reviewer of the week fixes more review latency than any tooling change.
Gate the Build So Reviewers Read Meaning
Every check you automate is a class of comment reviewers never have to write again. For documentation, five gates cover most of it:
# .github/workflows/content.yml
name: Content checks
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npm run build
- name: Front matter schema
run: node scripts/check-frontmatter.mjs
- name: Internal links + anchors
run: npx linkinator ./dist --recurse --silent
- name: Spelling (project dictionary)
run: npx cspell "content/**/*.md" --no-progress
- name: Terminology
run: node scripts/check-terms.mjs
- name: Reading level and length
run: node scripts/check-readability.mjs
The terminology check is the one most teams underrate. A short list of "say this, not that" — product names, capitalisation, deprecated feature names — catches the inconsistencies that otherwise consume review attention:
// scripts/check-terms.mjs
const RULES = [
[/\bwebsite generator\b/gi, 'static site generator'],
[/\bJamstack\b/g, 'Jamstack'], // capitalisation
[/\bnode\.js\b/g, 'Node.js'],
[/\bcloudflare workers\b/gi, 'Cloudflare Workers'],
];
Publish on a Schedule Without Runtime Logic
Documentation teams frequently need a page to appear at a particular moment: a release announcement, an embargoed feature, a deprecation notice. On a static site there is no runtime to check a date, so the pattern is to filter at build time and rebuild on a schedule.
// Astro content collection filter — future-dated pages never build
const posts = await getCollection('blog', ({ data }) =>
!data.draft && data.date <= new Date());
# .github/workflows/scheduled-publish.yml
on:
schedule:
- cron: '5 * * * *' # hourly, five past
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- run: npx wrangler deploy
An hourly rebuild gives publication accurate to the hour with no infrastructure; a cron every fifteen minutes gets you closer at four times the build minutes. The trade-offs, including how to avoid a wasted deploy when nothing changed, are in Scheduling Content Publication With Cron-Triggered Builds.
Structure the Content So the Build Can Help
A workflow is only as good as the shape of the content it moves. Two structural decisions do most of the work.
Put required metadata in a schema. Every page needs a title, a description, a date and whatever your templates depend on. Declaring that as a schema means an author gets a build error naming the file and the field, rather than a reviewer noticing three days later that a search snippet is empty. In Astro this is a content collection schema; in Eleventy it is a computed-data validation step; in Hugo it is a template that fails loudly on a missing field.
// scripts/check-frontmatter.mjs — generator-agnostic guard
import { readFile } from 'node:fs/promises';
import { globSync } from 'node:fs';
import matter from 'gray-matter';
const REQUIRED = ['title', 'description', 'date'];
let bad = 0;
for (const file of globSync('content/**/*.md')) {
const { data } = matter(await readFile(file, 'utf8'));
for (const key of REQUIRED) {
if (!data[key]) { console.error(`${file}: missing ${key}`); bad++; }
}
if (data.description && (data.description.length < 80 || data.description.length > 158)) {
console.error(`${file}: description is ${data.description.length} chars (want 80–158)`);
bad++;
}
}
process.exit(bad ? 1 : 0);
Keep one page per file and one file per URL. Documentation teams sometimes reach for a single large file per section because it is easier to write. It is much harder to review, to link to, and to move. One file per URL means a pull request touching one page has a one-file diff, which is the single biggest factor in how quickly a review happens.
The corollary is that reorganising sections must be cheap. If moving a page changes its URL, the workflow needs a redirect step, and a workflow with a manual redirect step will eventually skip it. Either derive URLs from a permalink field that survives file moves, or make the redirect generation automatic — the approaches are covered in Keeping Redirects Working After an SSG Migration.
Handle Images and Assets Without Blocking Writers
The most common practical complaint from documentation authors is not Git — it is images. Where does a screenshot go, what size should it be, and why did the build fail because it was 4 MB?
Give the answer a shape that requires no decisions. Put images in a page bundle next to the Markdown, reference them relatively, and let the build resize and convert. Every major generator supports this, and it removes the two failure modes: an image in the wrong directory, and a 4 MB PNG in the repository.
content/guides/deploying/
index.md
deploy-dashboard.png ← referenced as 
rollback-panel.png
Add a size guard so an oversized source is caught at the pull request rather than in a performance audit three months later, and let the pipeline generate the responsive variants automatically — the build-time work in Image Optimization Pipelines in Astro and its Hugo equivalent is what makes this safe to leave to non-engineers.
The same principle applies to diagrams. If a diagram requires a design tool, only the person with the tool can update it. If it is text — an inline SVG, a diagram-as-code block rendered at build time — anyone who can edit the page can fix the label that is now wrong.
Keep Content and Code Together — Usually
For a documentation site, one repository is normally right. A single pull request can change a page and the component it renders with, the preview covers both, and the content's history sits alongside the code that presents it.
Split them when one of two things is true: the content is consumed by more than one site, or the contributor set is genuinely different and the code repository's permissions cannot accommodate them. In both cases the cost is real — two review processes, two histories, and a build that must fetch content from somewhere — so make the split deliberately rather than by default.
If you do split, keep the build reproducible: pin the content version the build uses rather than always fetching the tip, so a build can be repeated exactly. That single decision is the difference between a content repository and a moving target.
There is a middle path worth knowing about: keep content in the site repository but let a second team contribute through a fork or a limited-permission branch. This gives you a single build, a single history and one review process, while still allowing contributors who should not have write access to the code. Most repository hosts support this with no configuration beyond a branch protection rule, and it avoids the split entirely for the case that usually motivates it.
Measure the Workflow, Not Just the Site
Content workflows fail quietly: nobody announces that they have stopped writing because the toolchain is annoying. Three numbers make the health visible.
Time from first commit to publish. Measured per pull request, this is the workflow's latency. A documentation team that publishes in hours behaves differently from one that publishes in weeks — the second batches changes, and batching is what makes review hard.
Share of contributions from outside the core team. If support engineers and product managers never contribute, the entry points are too narrow, no matter how elegant the pipeline is.
Rework rate. How often a page is corrected within a week of publishing. A high rate points at review happening too late or previews arriving too slowly, not at careless writers.
None of these needs a dashboard to start. A monthly query against the repository host's API, written down in the same place as the review checklist, is enough to notice a trend — and noticing is the whole point, since a workflow that has quietly stopped working looks identical to one nobody needed this month.
Common Pitfalls
- One interface only. Requiring a local toolchain for a typo fix filters out exactly the contributors closest to the reader.
- Reviewing diffs instead of previews. Structure and rendering problems are invisible in a diff and obvious on the page.
- Mechanical review comments. Anything a reviewer says twice should become a build gate.
- Slow previews. A preview that arrives after the reviewer has moved on is not part of the workflow.
- CMS as the source of truth. A Git-backed CMS should commit Markdown you can read and edit by hand; if the repository is not authoritative, you have coupled publishing to a vendor.
- Scheduling with client-side logic. Hiding future content with JavaScript ships it to anyone who reads the source. Filter at build time.
Key Takeaways
- Offer at least two entry points: a local checkout for daily writers and a browser path for everyone else.
- Make the preview URL the review artifact, and keep the human checklist to meaning and accuracy.
- Move every mechanical check into the build — links, schema, spelling, terminology — so reviews get faster without getting shallower.
- Publish future-dated content by filtering at build time and rebuilding on a cron.
- Keep content in the site repository unless it is genuinely shared, and pin the version if you split.
FAQ
Do writers need to learn Git to work on a static site?
Not necessarily. A Git-backed CMS gives them a normal editing interface that commits behind the scenes, and a web-based editor covers small corrections. Teams that publish daily usually end up learning a handful of Git operations anyway, because the review flow is where the value is — but it should be a choice, not a barrier to the first contribution.
What is the right review process for documentation?
One reviewer, a preview URL, and a checklist short enough to actually use. Documentation review is mostly about accuracy and structure, both of which are easier to judge on a rendered preview than in a diff, so the preview link matters more than the review ceremony.
How do I schedule a post for a future date?
Filter future-dated content out of the build and trigger a rebuild on a schedule. A nightly or hourly cron that rebuilds and redeploys publishes anything whose date has arrived, with no runtime logic and no CMS involvement.
Should content live in the same repository as the site code?
For a documentation site, usually yes: one repository means one pull request can change a page and the component it uses, and previews cover both. Split them only when the content is shared across several sites or the contributor set is genuinely different.
How do we stop broken content reaching production?
Gate the build. A link check, a front-matter schema and a spell check catch most content defects before review, and they give the author the feedback instead of the reviewer. The rule of thumb is that anything a reviewer says twice should become a check.
What about non-technical contributors who only edit occasionally?
Give them the CMS or the web editor and a one-page guide. Occasional contributors should never have to install anything; the cost of onboarding them to a local toolchain exceeds the value of the change they came to make.
Related
- Parent: Production-Ready Deployment & CI/CD Workflows — the pipeline this workflow rides on.
- Wiring a Headless CMS to a Static Build — the editing layer, Git-backed or API-backed.
- Scheduling Content Publication With Cron-Triggered Builds — publishing at a time without a runtime.
- Docs-as-Code Review Workflow for Writers — branches, reviews and checklists in practice.
- Preview Environments for Pull Requests — the preview that makes review work.
- Rollbacks and Deploy Safety for Static Sites — what happens when something gets through anyway.