---
title: "ContentOps"
slug: contentops
category: business
term_status: established
evidence_status: partially_verified
summary: "ContentOps (content operations) is the people, process and technology that turn a content plan into accurate, findable content at scale: modelled once, reviewed by named owners, published to every channel, measured, and retired when it goes stale."
audience: [Beginners, Content strategists and editors, Editorial operations managers, Technical writers and CMS owners, Engineers building content platforms, Leaders]
last_verified: 2026-10-23
key_takeaways:
  - "ContentOps is the execution layer between content strategy (what and why) and content management technology (the CMS): workflow, roles, standards, measurement and the lifecycle of every item."
  - "Every live item needs an owner and a review date; content without either decays silently, and the cost lands on readers, support teams and legal."
  - "Structured content (a content model with typed fields, no presentation markup) is what makes reuse, localisation and multi-channel publishing cheap; it is a modelling decision before it is a CMS purchase."
  - "Risk-tier your reviews: legal, safety and pricing statements need named approvers; most other content needs one editor and automated checks, not a committee."
  - "Measure flow (cycle time, review SLA, first-pass approval), health (freshness, ownerless rate, ROT) and outcomes (task success), never volume alone."
  - "Retirement is a production step, not an afterthought: decide between update, withdraw and unpublish, keep redirects, and record the decision."
related: [knowledgeops, mediaops, seo-operations, marketingops, designops, legalops, eduops, webops]
---

## What ContentOps is

### In 30 seconds

**ContentOps (content operations) is the system that turns a content plan into content people can rely on:** the workflow,
roles, standards, tools and measures that take each piece from request to publication, keep it accurate while it is live, and
retire it when it is no longer true or useful. Deane Barker put the boundary memorably in 2016: "Content Operations (CO) is
concerned with everything between Content Strategy (CS) and Content Management (CM)."[^barker]

Strategy decides what an organisation should say, to whom and why. A content management system (CMS) stores and delivers it.
ContentOps is everything that has to happen in between, every day: briefs, drafting, reviews, approvals, translation, publishing
to several channels, audits, corrections and retirement. When it works, a price change reaches every channel and language on the
same day, every item has a named owner and a review date, and nobody copies text between systems.

Written for beginners, content practitioners, platform engineers and the leaders who fund them. Sources were last verified on **2026-10-23**.

::: note Scope of this page
This page treats ContentOps as **the operating model for editorially planned content**: web and app copy, product and help
content, documentation, marketing and editorial articles, policy pages. Its boundaries with neighbouring Ops are **editorial
distinctions** of this Atlas, set out in [What ContentOps is not](#what-contentops-is-not).
:::

### At a glance

| Aspect | Summary |
|---|---|
| Goal | Accurate, findable, accessible content produced predictably and retired when stale, at a cost the organisation can sustain |
| Users | Content strategists, editors and writers, editorial ops managers, subject-matter experts, legal and brand reviewers, translators, CMS and platform engineers |
| In scope | Intake and briefs; editorial calendar and capacity; content models and structured content; style, terminology and taxonomy; review and approval; localisation workflow; multi-channel publishing; audits, freshness and retirement; content metrics |
| Handed off | Media pipelines, search optimisation, support-born knowledge, campaigns, hosting, learning design: see [What ContentOps is not](#what-contentops-is-not) and [SEOps](../seops/), [EduOps](../eduops/) |
| Prerequisites | None. A content strategy (even a one-page one) helps; spreadsheet skills help for audits |
| Key outputs | Content model, style guide and term list, workflow with states and service levels, content register with owners and review dates, governance charter, audit and retirement records, scorecard |
| Term status | **Established** as a practice with literature, consultancies, conferences and job roles; no standards body defines it, and definitions vary in breadth (see [Origins and evolution](#origins-and-evolution)) |

### The problem it solves

Content is cheap to publish and expensive to keep true. Organisations notice the problem late, through symptoms rather than causes:

- **Contradiction.** Two help articles describe the same task differently; the pricing page and the sales PDF disagree. Paul Boag's
  well-known description of "ROT" (redundant, out-of-date and trivial content) lists the usual suspects: "products or services
  that no longer exist; campaigns that have long since ended", phone numbers that no longer work, staff who have left.[^boag]
- **Nobody owns it.** The person who wrote a page has moved on, and the web team that could delete it lacks the authority: in
  Boag's words, digital teams "often do not own the content and so do not have the authority to remove it".[^boag]
- **Copy and paste.** The same paragraph lives in the website, the app, the PDF and the partner portal, so every change is four
  changes, and translation multiplies that by each language. Rahel Bailie's summary of what has to change: "This copy and paste
  stuff has got to go."[^bailie]
- **Bottlenecks.** Reviews wait days in someone's inbox; launches slip because legal sees the copy on the last afternoon.
- **The CMS is blamed.** Barker described two recurring situations: organisations not ready to launch a new CMS because their
  content is a mess, and organisations not using the CMS they already have.[^barker] Neither is fixed by buying another CMS.

Before ContentOps, content is a series of one-off projects. After it, content is a managed inventory whose changes flow
through a known path with service levels, and the organisation can answer "how much of our content is current?" with a number.

### What ContentOps is not

- **Not content strategy.** Strategy decides goals, audiences, messages and priorities. Barker is explicit that content operations
  "is *not* digital marketing or content strategy": it assumes the plan exists.[^barker] In practice the two loop: operations data
  (what decays, what nobody reads) should change the strategy.
- **Not the CMS.** Barker again: it "is *not* technical content management".[^barker] Choosing and running the platform is
  engineering work that ContentOps depends on and specifies requirements for.
- **Not "more content, faster".** Efficiency matters (Bailie calls it the point of the whole thing[^bailie]), but a system that
  publishes more while retiring nothing increases the maintenance load every month.
- **Not KnowledgeOps.** Both manage text with owners and expiry. This Atlas splits them by **origin** (an editorial
  distinction, made once here and linked from elsewhere): content that is planned and produced through an editorial workflow is
  ContentOps; knowledge captured while solving support cases or operations work (KCS articles, runbooks), even when published
  for customers, is [KnowledgeOps](../knowledgeops/). Shared rules such as owners and review dates should be identical on both
  sides, so readers do not notice the boundary.
- **Not the neighbouring pipelines.** Video and audio pipelines belong to [MediaOps](../mediaops/), search optimisation to
  [SEO Operations](../seo-operations/), campaign process to [MarketingOps](../marketingops/), and hosting to
  [WebOps](../webops/); the [relations table](#how-contentops-relates-to-other-ops) gives the handoff for each.
- **Not DevOps for words.** Docs-as-code borrows version control, review and automated tests from software,[^wtd] and ContentOps
  practitioners cite DevOps as a cousin, but content has different failure modes: a wrong sentence does not crash, it misleads
  quietly for years.

::: caution Naming confusion
In job titles, "content operations" sometimes means content moderation ("trust and safety"), in this Atlas's reading of job
listings (October 2026). Moderation is out of scope for the Atlas; broadcast media pipelines are in [MediaOps](../mediaops/).
:::

## Where it comes from and where it sits

### Origins and evolution

ContentOps has no founding manifesto. Its history is a convergence of three older threads, then a label.

1. **Governance in content strategy (2008 onwards).** Kristina Halvorson's 2008 article in *A List Apart* described content
   strategy as planning "for the creation, publication, and governance of useful, usable content", and asked who is responsible for
   content once it is published.[^halvorson] Governance was already in the definition; operations is what governance looks like
   on a Tuesday.
2. **Structured, portable content (2009).** NPR's digital team described "Create Once, Publish Everywhere (COPE)" as "one of the
   primary philosophies driving our systems", with three principles: build content management tools rather than web publishing
   tools, separate content from display, and eliminate markup from content.[^npr] This is the technical foundation of reuse.
3. **Technical communication's single-sourcing tradition.** Standards such as DITA[^dita13] and XLIFF[^xliff] made reuse,
   conditional publishing and translation workflows routine in documentation teams long before marketing sites went headless.
4. **The label (mid-2010s onwards).** Barker's 2016 post described a practice "we're calling 'content operations'" and listed
   its services, from content inventory and migration to QA, URL integrity and localisation support; he added that "in no way do
   we think we're breaking any new ground".[^barker] Content Science defined content operations as
   "the behind-the-scenes work of managing content activities as effectively and efficiently as possible" and published a five-level
   maturity model.[^cs-build][^cs-fact] Rahel Bailie described ContentOps as "a set of principles" used "to optimize content
   production".[^bailie] An abstract for one of Bailie's tekom talks says the descriptor was in use "as far back as the early
   2000s" but gained traction only after labels like DevOps spread;[^tekom] treat that as a practitioner's recollection, not a
   history. An open-access collection, *Content Operations from Start to Scale*, edited by Carlos Evia, aims to explain
   content operations to both industry and academia; it grew out of Scriptorium's *Technical Writing 101*.[^evia]

The result has **no standards body and no single definition**. Definitions differ mainly in breadth; this page uses Barker's
broad one (everything between strategy and the CMS).

### Glossary and mental model

| Term | Meaning | Example |
|---|---|---|
| Content item | One managed unit with an identity, type, owner and lifecycle state | The help article "Reset your password" |
| Content type | A template that defines which fields an item has and their rules | `product_notice`: headline ≤ 70 characters, summary, body, audience, locale, owner, review date |
| Content model | The set of content types and the relationships between them; Sanity's docs describe modelling as defining "the types of content you need, the attributes of each one, and the relationships between them"[^sanity] | Article → author, Article → product, Product → price |
| Structured content | Content stored as typed fields, without presentation markup, so any channel can render it[^npr] | A price stored as amount + currency, not as bold text inside a paragraph |
| Component (fragment) | A reusable piece referenced, not copied, by many items | The legal disclaimer used on 40 pages |
| Headless CMS | A CMS that stores and serves content through APIs and leaves presentation to each channel | Website, app and in-product tips all reading the same entry |
| Component content management system (CCMS) | A repository that manages content as small reusable topics or components, often in DITA XML, with conditional publishing | One safety warning topic reused in 30 manuals, filtered by product model |
| Digital asset management (DAM) | The system of record for images, files and media, with rights, renditions and expiry dates | A product photo whose licence expires in June |
| Translation management system (TMS) | The system that runs translation jobs and holds translation memory, the term base and vendor workflow | A German job containing only the 12 changed sentences |
| COPE | Create Once, Publish Everywhere: one source, many outputs[^npr] | One release note rendered to web, email and in-app panel |
| Workflow state | Where an item is in its [lifecycle](#the-content-lifecycle) | "Live, review due 2027-03-01" |
| Content register (inventory) | The list of every live item with its metadata; the basis of audits | A spreadsheet or CMS export |
| Content audit | A qualitative assessment of the inventory against criteria | Keep / update / merge / retire decisions |
| ROT | Redundant, out-of-date, trivial content[^boag] | A 2019 office-party post still in site search |
| Taxonomy, controlled vocabulary | Agreed terms used for tagging and navigation; ANSI/NISO Z39.19 covers their construction and maintenance[^z3919] | Product names, audiences, topics |
| Style guide, term base | Rules for voice, grammar and terminology, ideally enforced by tools | "sign in", never "log in" |
| Localisation (l10n), internationalisation (i18n) | Adapting content to a locale; designing content so adapting it is easy[^w3c-i18n] | German pricing page with local tax wording |
| Translation memory | Stored source–target segment pairs reused in later translations | An unchanged sentence is not re-translated |
| Withdraw / unpublish | Keep at its URL with a "no longer current" notice, or remove (with a redirect)[^govuk-retire] | Old press release withdrawn; duplicate page unpublished and redirected |

#### A mental model: an inventory, an assembly line and a garden

Hold three pictures. **An inventory**: content is a stock of items with owners, types and expiry dates, and you should be
able to count it. **An assembly line**: each new or changed item flows through stations (brief, draft, review, approve,
localise, publish) with queues, service levels and quality gates, and most delays are waiting, not working. **A garden**: once
published, content grows stale and tangled unless someone prunes it; the pruning (audits, updates, retirement) is scheduled work,
not a crisis response. Teams that see only the assembly line publish ever faster into an untended garden.

### How ContentOps relates to other Ops

ContentOps sits in a cluster of business and product Ops. The table gives the shared scope and the editorial distinction for each.

| Neighbouring Ops | Shared scope | Unique focus of the neighbour | Choose the neighbour when… |
|---|---|---|---|
| [KnowledgeOps](../knowledgeops/) | Owners, freshness, findability of text | Knowledge captured from support and operations work (KCS, runbooks) | The content is born from solving a case or an incident |
| [MarketingOps](../marketingops/) | Campaign content, calendars | Campaign and lead process, marketing automation, attribution | The question is about running a campaign, not producing its assets |
| [SEO Operations](../seo-operations/), [SEOps](../seops/) | Briefs, metadata, internal links | Search demand, ranking and crawl engineering | The success measure is organic search |
| [MediaOps](../mediaops/) | Assets, metadata, rights | Video and audio pipelines, transcoding, live delivery | The asset is time-based media |
| [DesignOps](../designops/) | Design systems, UX writing | Design tooling, design system governance, design team health | The work is about components' look and behaviour, not their words |
| [LegalOps](../legalops/) | Approvals for regulated statements | Legal intake, contracts, legal spend | The question is how legal work is run, not how content gets approved |
| [EduOps](../eduops/) | Course content production | Learning design, assessment validity, LMS operations | The content is a course with learners and assessments |
| [WebOps](../webops/) | Publishing to the web | Hosting, CDN, performance, certificates | The question is how the site runs, not what it says |

::: figure ContentOps between strategy, platforms and neighbouring Ops
```mermaid
flowchart TB
  CS["Content strategy"] --> IN["Intake and briefs"]
  IN --> PR["Produce and review"]
  PR --> PUB["Localise and publish"]
  PUB --> MT["Maintain, audit, retire"]
  MT -.->|"evidence"| CS
  MK["MarketingOps: campaigns"] --- IN
  SEO["SEO Operations: search"] --- PR
  PR <--> CMS["Platforms: CMS, DAM, TMS"]
  CMS --- WEB["WebOps: hosting"]
  MED["MediaOps: video, audio"] --- PUB
  KO["KnowledgeOps: support-born"] --- MT
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class IN,PR,PUB,MT core
  class CS,CMS,KO,MK,SEO,MED,WEB neutral
```
Text equivalent: Content strategy feeds the four ContentOps stages in order: intake and briefs, produce and review,
localise and publish, and maintain, audit and retire; the last stage returns evidence (what decays, what nobody uses) to strategy.
Each stage touches a neighbour across an editorial boundary: intake receives campaign requests from MarketingOps; production uses
search briefs from SEO Operations; publishing uses video and audio from MediaOps; maintenance borders KnowledgeOps, which owns
knowledge born from support work. Production works in both directions with the content platforms (CMS, DAM, translation
management), which share a boundary with WebOps (hosting).
:::

## Principles and operating model

### Charter and principles

No official ContentOps manifesto exists. The charter below is **this Atlas's proposal**; adapt the wording, keep the
commitments measurable.

> **Mission.** Every piece of content we publish is accurate, findable, accessible and owned, and reaches every channel and
> language it needs without being copied by hand. We produce it predictably and retire it deliberately.
>
> **Measurable goals.** At least 95 % of live items in scope have an active owner and a review date that has not passed; median
> cycle time for standard items within the agreed service level; zero high-risk statements published without the named
> approver's prior consent (emergency removals of wrong statements excepted, because they add no new claim);
> every retirement recorded with a redirect or notice.
>
> **Non-goals.** Deciding brand strategy or campaign goals; running the CMS infrastructure; moderating user-generated content.

Principles, each with the trade-off it implies:

1. **Model before you write.** Decide content types and fields before producing at scale. Trade-off: slower first project, much
   cheaper fifth channel.
2. **Separate content from presentation.** Store meaning, not layout, as NPR put it: "Separate Content from Display" and
   "Eliminate markup from content".[^npr] Trade-off: authors lose some visual control; designers gain consistency.
3. **One source of truth per fact.** A price, a legal statement or a product name lives in one place and is referenced. Trade-off:
   references need a dependency view so editors see where a change lands.
4. **Every item has an owner and an expiry.** Ownership is a named role, not a team alias; a review date is set at publication.
   Trade-off: owners must be given time; unowned content must be reassigned or retired.
5. **Review effort proportional to risk.** Tier content by the harm a mistake can do; automate the checks a machine can do.
   Trade-off: someone must define and maintain the tiers.
6. **Flow over heroics.** Limit work in progress, make queues visible, and set service levels for reviews. Trade-off: saying
   "not this sprint" to requesters.
7. **Retire as deliberately as you publish.** In NN/g's words, "Content won't govern itself."[^nng] Trade-off: retirement needs
   authority, granted explicitly.

### Fundamentals and building blocks

A working ContentOps has seven building blocks. Missing any one shows up as a predictable failure.

| Building block | What it is | Failure if missing |
|---|---|---|
| Content model | Types, fields, rules and relationships, documented and enforced by the CMS or a schema | Free-form pages that cannot be reused or validated |
| Standards | Style guide, term base, accessibility rules, plain-language guidance, taxonomy | Inconsistent voice, wrong product names, inaccessible pages |
| Workflow | States, transitions, roles allowed to move items, service levels | Invisible queues, approvals by email, launches blocked late |
| Content register | Inventory of live items with type, owner, review date, channel, locale | No answer to "what do we have and who owns it?" |
| Governance | Charter, decision rights, council or owner, escalation, exception process | Endless debates; nobody can retire anything |
| Tooling | CMS, DAM, translation management, linting and checks, analytics | Copy and paste between systems |
| Measurement | Flow, health and outcome metrics reviewed on a cadence | Opinions instead of evidence; volume as the only number |

### Roles, ownership and RACI

Small organisations combine these roles; large ones split them further. What matters is that each decision has exactly one
accountable person.

| Role | Responsibilities | Typical background |
|---|---|---|
| Content strategist | Goals, audiences, priorities, content types needed | Editorial, UX, marketing |
| Editorial operations manager (ContentOps lead) | Workflow, calendar, capacity, service levels, metrics, tooling requirements | Managing editor, project management |
| Content designer / writer | Drafting and updating items to the model and standards | Writing, UX writing, technical writing |
| Editor | Quality, style, structure; first-line approval | Editorial |
| Subject-matter expert (SME) | Factual accuracy for their domain | Product, engineering, policy |
| Risk approver | Legal, regulatory, safety, pricing or brand sign-off for high-tier items | Legal, compliance, brand |
| Content owner | Accountable for an item or collection while live; responds to review reminders | Product or service owner |
| Localisation manager | Translation workflow, vendors, term base, locale quality | Localisation |
| Content architect / CMS owner | Content model, taxonomy, CMS configuration, integrations | Information architecture, engineering |
| Content analyst | Audits, dashboards, outcome analysis | Analytics |

RACI for the main decisions (R = responsible, A = accountable, C = consulted, I = informed):

| Decision or activity | Strategist | ContentOps lead | Writer / editor | SME | Risk approver | Owner | Architect |
|---|---|---|---|---|---|---|---|
| Accept or decline a request | A | R | I | C | – | C | – |
| Add or change a content type | C | C | C | – | – | I | A/R |
| Draft and edit | – | I | R | C | – | A | – |
| Approve a high-risk statement | – | I | C | C | A/R | I | – |
| Set service levels and WIP limits | C | A/R | C | – | C | I | – |
| Review date reached: update or retire | C | R | R | C | C | A | – |
| Retire (withdraw or unpublish) | C | R | I | – | C | A | I |
| Translation release | – | A | C | – | C | I | – |

### The content lifecycle

The NN/g description of content strategy names four conceptual phases (planning, creation, maintenance and unpublishing) through
which content cycles until it is removed.[^nng] For operations, those phases need explicit **states**, because states are what a
CMS can enforce and what a dashboard can count. The state machine below is this Atlas's proposal.

::: figure Content item lifecycle as a state machine
```mermaid
stateDiagram-v2
  direction TB
  [*] --> Requested
  Requested --> Declined: not aligned or no capacity
  Requested --> Draft: brief accepted
  Draft --> InReview: submitted
  InReview --> Draft: changes requested
  InReview --> Approved: all required approvals
  Approved --> Scheduled
  Scheduled --> Live: published
  Scheduled --> Draft: launch changed
  Live --> ReviewDue: review date reached
  ReviewDue --> Live: confirmed accurate, new date
  ReviewDue --> Draft: needs update
  ReviewDue --> Withdrawn: no longer current
  Withdrawn --> Unpublished: redirect or remove
  Live --> Unpublished: duplicate or published in error
  Declined --> [*]
  Unpublished --> [*]
```
Text equivalent: A request is either declined or accepted as a draft. A draft goes into review, returns to draft if changes are
requested, and becomes approved when all required approvals are recorded. Approved items are scheduled and then published as live;
a scheduled item returns to draft if the launch changes.
When the review date arrives, a live item is confirmed (and given a new date), sent back to draft for an update, or withdrawn.
Withdrawn items can later be unpublished with a redirect. A live item can also be unpublished directly if it is a duplicate or was
published in error. Declined and unpublished items leave the lifecycle.
:::

Two details matter more than they look. First, **"review due" is a state, not a calendar reminder**: if the owner does nothing,
the item stays visibly overdue, which a dashboard can count and an escalation can act on. GOV.UK's publishing tool works this way:
search shows whether content is overdue for review, based on the date set at the last update.[^govuk-manage] Second, **withdraw and
unpublish are different outcomes**. GOV.UK withdraws content by keeping it at its URL with a "no longer current" banner and hiding
it from site search; it unpublishes (removes, optionally with a redirect) only in limited cases such as content published in error,
needs met elsewhere, personal details or copyright problems.[^govuk-retire]

### Operating model and governance

Governance answers four questions: who decides, by which rules, how often, and what happens when someone disagrees.

- **Decision rights.** Write down who can create a content type, who can publish in each risk tier, who can retire, and who can
  grant exceptions to the style guide. This Atlas treats the authority to retire as the first gap to close, because without it
  the problem Boag describes (teams that cannot remove content they do not own) persists.[^boag]
- **Cadences.** A weekly intake and prioritisation meeting (30 minutes, ContentOps lead chairs); a daily or asynchronous review
  queue check; a monthly health review of freshness, ownerless items and backlog; a quarterly audit of one collection; an annual
  model and standards review.
- **Service levels.** Set them per tier: for example, editorial review in two working days, legal review for high-risk items in
  three, translation in five per locale. Publish them, measure them, and renegotiate rather than silently miss them.
- **Exceptions: contain first, correct with consent.** When wrong content is live, the emergency path separates two acts.
  *Containment* (removing the wrong statement, or replacing it with a link to an approved source) may be done at once by the
  on-duty editor without approval, because it adds no new claim. *Correction* (publishing a new tier-3 statement) always needs
  the risk approver's consent **before** publication; in an emergency that consent may be given by phone or message, provided it
  is logged with the time and confirmed in the workflow afterwards. Both acts are recorded in the exception log.
- **Escalation.** Overdue reviews escalate to the owner's manager after a set period; disputed retirement decisions go to a
  governance council (strategist, ContentOps lead, a legal representative, a product representative).

The council's monthly decisions follow the [measurement loop](#metrics-and-kpis): evidence from the register and the workflow
leads to a change of standards, capacity or ownership.

## Architecture and workflow

### Reference architecture: the structured content platform

This is a logical architecture, not a product recommendation. Small teams can run all of it inside one traditional CMS; large
ones split it across specialised systems. The components and their responsibilities:

| Component | Responsibility |
|---|---|
| Intake | Requests, briefs, prioritisation; links each item to a goal |
| Authoring and repository | Typed entries, versions, workflow states, permissions (a CMS or a Git repository) |
| Content model and schema | Types, fields, validation rules, references; enforced at save time and in CI |
| Quality checks | Style and terminology linting, link, accessibility and schema checks before review |
| DAM | Images, files, rights and expiry of assets (media pipelines: [MediaOps](../mediaops/)) |
| TMS | Jobs, translation memory, term base, vendors; exchanges XLIFF files[^xliff] |
| Delivery | APIs and renderers for each channel |
| Analytics and register | Usage, search, feedback, inventory with owners and dates |

::: figure Logical architecture of a structured content platform
```mermaid
flowchart TB
  REQ["Intake and briefs"] --> REPO["CMS or Git repository"]
  MODEL["Content model and schema"] --> REPO
  REPO <--> DAM["DAM: assets, rights"]
  REPO <-->|"XLIFF"| TMS["TMS: memory, terms"]
  REPO --> QC["Checks: schema, style, links, a11y"]
  QC --> API["Content API"]
  API --> WEB["Website"]
  API --> APP["Mobile app"]
  API --> OTH["Email, PDF, help"]
  WEB --> AN["Analytics and register"]
  APP --> AN
  OTH --> AN
  AN -.->|"audits, review dates"| REQ
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class REQ,REPO,MODEL,QC core
  class DAM,TMS,API,WEB,APP,OTH,AN neutral
```
Text equivalent: Intake and briefs feed a CMS or Git repository that holds typed entries and workflow states. The
content model and schema constrain the repository; it exchanges assets and rights with a DAM, and translation files (for example
XLIFF) with a translation management system that holds memory and terms. Content passes automated checks (schema, style, links,
accessibility) before a content API delivers it to the website, the mobile app, and email, PDF or in-product help. Usage from all
three channels flows into analytics and the content register, which feeds audits and review dates back to intake.
:::

**Trust boundaries and alternatives.** Three boundaries deserve explicit controls. Authoring permissions: who can publish in
each tier (enforced in the CMS role model, not by convention). The translation boundary: content leaves the organisation for
vendors, so send only what needs translating and never unpublished financial or personal data without a contract that covers it.
The delivery API: preview and draft endpoints must not be publicly reachable, or embargoed content leaks. The alternatives (a coupled CMS, docs-as-code)
are compared in the [Decision framework](#decision-framework).

### End-to-end workflow: one change from request to retirement

The sequence below follows a typical medium-risk item (a help article for a new feature) through the happy path, with the two most
common exception paths described after it.

::: figure Handoffs for one help article, from request to publication
```mermaid
sequenceDiagram
  autonumber
  participant OPS as Ops lead
  participant W as Writer
  participant SME as SME
  participant ED as Editor
  participant L as L10n
  Note over OPS: Request and brief from product
  OPS->>W: Assign, set tier
  Note over W: Checks: schema, style, links
  W->>SME: Accuracy review
  SME-->>W: Corrections
  W->>SME: Revised draft
  SME->>ED: Accuracy confirmed
  ED->>L: Approved source
  L-->>ED: Translations
  Note over ED,L: Published, review date set
```
Text equivalent: The ContentOps lead receives a request and brief from product, assigns a writer and sets the review
tier. The writer's draft passes automated checks (schema, style, links) and goes to a subject-matter expert for an accuracy review;
the SME returns corrections, the writer sends a revised draft, and the SME confirms accuracy to the editor. The editor sends the
approved source text to localisation and receives translations; the item is then published in all locales with a review date.
:::

**Exception path 1: the launch moves.** If the feature changes before launch, the scheduled item returns to draft and translation
jobs already sent are cancelled or updated; translation memory limits the cost. The trigger is a change notice from product, so the
request form should capture the launch dependency.

**Exception path 2: a reviewer is the bottleneck.** If the SME review breaches its service level, the ContentOps lead escalates
once to the SME's manager and, for medium-risk items, may publish with editorial approval and an "accuracy check pending" task on
the owner. High-risk items never take this shortcut. The metric that exposes this path is review service-level attainment
(see [Metrics and KPIs](#metrics-and-kpis)).

## Practices, standards and tools

### Core practices and playbooks

| Practice | Goal | Trigger | Owner | Output | Verification |
|---|---|---|---|---|---|
| Intake and brief | Only planned, purposeful work enters production | Any request | ContentOps lead | Accepted brief with goal, audience, type, tier, owner, dates | Every item in production links to a brief |
| Calendar and capacity | Predictable delivery | Weekly | ContentOps lead | Calendar with WIP limits | Cycle time and on-time rate |
| Content modelling | Reusable, valid, multi-channel content | New content type or channel | Content architect | Type definitions, schema, examples | Schema validation in CI |
| Style and terminology | Consistent, plain, accessible language | Every save | Editor | Style guide, term base, linter rules | Lint error rate trends down |
| Risk-tiered review | Right approvals, no more | Submit for approval | ContentOps lead | Approvals recorded per tier | No high-tier item without its approver |
| Localisation | Every locale current and correct | Source approved | Localisation manager | Translated items, updated memory | Localisation lag, locale coverage |
| Audit and ROT triage | Know and shrink the inventory | Quarterly per collection | Content analyst | Keep, update, merge, retire decisions | ROT ratio, freshness compliance |
| Retirement | Remove harm and clutter safely | Audit decision or review due | Content owner | Withdrawal or unpublish with redirect, record | No 404s for retired URLs with traffic |

#### Playbook: intake that protects capacity

1. Every request arrives through one form (see [Templates](#templates)); requests by chat or email are redirected to it.
2. The ContentOps lead checks the brief against the strategy's priorities and the calendar, then accepts, defers or declines
   within two working days. A decline names the reason (no audience need, duplicate of existing item, no capacity).
3. Accepted briefs get a content type, a risk tier, an owner and a target date before any writing starts.
4. **Acceptance criteria:** goal and audience stated; existing content searched (a duplicate becomes an update request); owner
   named; risk tier set. **Contingency:** if a date-critical request arrives with no capacity, something else is explicitly moved,
   and the requester of the moved item is told.

#### Playbook: risk-tiered review

Tiers are this Atlas's proposal; the point is that review effort follows the harm a mistake could cause.

| Tier | Examples | Required approvals | Automated gates |
|---|---|---|---|
| 1 Low | Blog posts, event recaps, internal news | Editor | Schema, style lint, links |
| 2 Medium | Help articles, product descriptions, documentation | Editor + SME | As tier 1 + accessibility checks |
| 3 High | Prices, contractual terms, health and safety statements, regulated claims, privacy notices | Editor + SME + named risk approver (legal, compliance or safety) | As tier 2 + term base for regulated phrases |

Rules that keep tiering honest: the requester cannot lower a tier; a tier-3 statement used as a component inherits tier 3 wherever
it is reused; in an emergency the on-duty editor may remove a wrong tier-3 statement at once, but any new tier-3 statement
needs the risk approver's consent before it is published (see the Exceptions rule under
[Operating model and governance](#operating-model-and-governance)).

#### Playbook: audit and ROT triage

1. **Inventory.** Export every live item with URL, title, type, owner, last reviewed, review date, traffic for the last 90 days,
   and a regulatory flag. GOV.UK suggests exports from its publishing tool to find content that has not been updated
   recently.[^govuk-manage]
2. **Automated flags.** Mark ownerless (owner missing or no longer active), outdated (review date passed or missing), likely
   redundant (several items on one topic, this one weaker) and likely trivial (very low use and no regulatory reason to exist).
   [Lab 1](#lab-1-beginner-content-inventory-and-rot-triage) does this with a script.
3. **Human judgement.** Flags are proposals. Boag warns against automatic deletion: low-traffic content can serve a small but
   important audience or a regulatory need.[^boag]
4. **Decide and record.** Keep, update, merge (and redirect), withdraw, or unpublish. GOV.UK's guidance is a useful default:
   update guidance rather than withdraw it; withdraw other content when it is no longer current (GOV.UK gives news and press
   releases over a year old as an example); unpublish rarely.[^govuk-retire]
5. **Schedule the work** in the normal calendar; an audit that produces a spreadsheet nobody acts on is an expensive inventory.

A real example of scale: a 2016 GOV.UK audit of early-years and childcare content, run by editors from several organisations,
reviewed 723 items and marked 79 of them (10.9 %) for retirement.[^govuk-audit] Your ratio will differ; the point is that even
well-governed estates carry retirable content.

#### Playbook: localisation without chaos

1. **Internationalise the source.** W3C defines internationalisation as design "that enables easy localization";[^w3c-i18n] in
   content terms: no text in images, no sentences assembled from fragments, dates and prices as structured fields, room for
   longer translations.
2. **Release source in batches** once approved, not while drafting; every source change after hand-off costs a re-translation.
3. **Exchange standard files.** XLIFF exists "to store localizable data and carry it from one step of the localization process to
   the other, while allowing interoperability between and among tools".[^xliff]
4. **Maintain the term base and memory** as owned assets; product names and regulated phrases go into the term base first.
5. **Review in-market** for tier 2 and 3 content: a native reviewer checks meaning, not only grammar.
6. **Track localisation lag and locale coverage** (see [Metrics and KPIs](#metrics-and-kpis)) so that locales do not silently
   fall behind.

#### Playbook: platform migration

Barker's list of content-operations services starts with inventory, extraction, migration, content QA, URL integrity and launch
management;[^barker] a CMS migration is where all of them meet. Owner: the ContentOps lead, with the CMS owner for steps 4–7.

1. **Audit before you move.** Run ROT triage ([Lab 1](#lab-1-beginner-content-inventory-and-rot-triage)) and retire or merge
   first. *Acceptance:* every item in scope has a keep, update, merge or retire decision and a named owner.
2. **Map the model.** Define the target content types and map each source type and field to a target field in a mapping sheet.
   *Acceptance:* every kept item maps to a type; each unmappable field has a recorded decision (drop, merge, new field).
3. **Freeze and log.** Announce a freeze window on the old system; urgent changes during it go into a change log that is
   re-applied after cut-over. *Acceptance:* the log has one owner and is empty after re-application.
4. **Extract, transform, validate.** Move content with scripts and validate it against the target model
   ([Lab 2](#lab-2-intermediate-validate-entries-against-a-content-model)). *Acceptance:* zero schema errors on tier-2 and tier-3
   items; remaining tier-1 errors listed with owners.
5. **Map every URL.** Each old URL with traffic or inbound links gets a new URL or a retirement target. *Acceptance:* a crawl of
   the old URL list returns no 404s.
6. **Check content by tier.** Compare rendering, links, images and locales: every tier-3 item, a sample of the rest.
   *Acceptance:* all tier-3 items checked and signed off.
7. **Cut over with a way back.** Keep the old system read-only until verification ends, with a stated rollback trigger (for
   example, redirect failures above an agreed level). *Acceptance:* freshness and ownerless baselines re-measured on the new
   platform; the decision is recorded with Template 5.

### Methods, standards and frameworks

No standard governs ContentOps as a whole. These standards govern parts of it; separate the mandatory (law, contract) from the
optional (industry practice).

| Standard or method | What it covers | Status (as of October 2026) | Mandatory? |
|---|---|---|---|
| WCAG 2.2 | Accessibility of web content | Current W3C Recommendation, dated 12 December 2024; content that conforms to 2.2 also conforms to 2.1 and 2.0[^wcag] | Mandatory only through law or contract, and the main legal baselines still cite **WCAG 2.1 AA** (see [Quality, accessibility and legal duties](#quality-accessibility-and-legal-duties)); targeting 2.2 AA covers both, though 2.0/2.1 audits may still test 4.1.1 Parsing, which 2.2 removed |
| ISO 24495-1:2023 | Governing principles and guidelines for plain-language documents | International standard, published June 2023[^iso-plain] | Optional unless a regulator or contract requires plain language |
| DITA | Topic-based XML document types and reuse mechanisms for technical content | DITA 1.3 is an OASIS Standard (errata 2018);[^dita13] the public DITA 2.0 specification page still cited a working draft[^dita20] | Optional; common in documentation teams |
| XLIFF | Exchange of localisable content between tools | XLIFF 2.1 (2018) is the latest OASIS Standard;[^xliff] XLIFF 2.2 reached Committee Specification on 13 March 2025[^xliff22] | Optional; widely supported by TMS tools |
| ANSI/NISO Z39.19 | Construction and maintenance of controlled vocabularies and taxonomies | 2005, reaffirmed 2010[^z3919] | Optional |

### Tooling landscape

Vendor-neutral categories first; named tools are examples, not recommendations, and capabilities change (as of October 2026).

| Tool category | Job it does | Representative options | Selection criteria | Lock-in and risks |
|---|---|---|---|---|
| Traditional (coupled) CMS | Authoring and website in one | WordPress, Drupal | Single site, editor-friendly previews, plugin ecosystem | Content mixed with layout; harder multi-channel reuse |
| Headless CMS | Typed content served by API to any channel | Contentful, Sanity, Strapi | Modelling power, references, workflow, roles, API limits, localisation support | Proprietary models and APIs; plan export; usage-based pricing |
| Component content management (CCMS) | Topic-based reuse, conditional publishing, translation at scale | DITA-based CCMS products | Reuse depth, DITA support, publishing pipelines | High learning curve; specialised skills |
| Docs-as-code | Markdown or AsciiDoc in Git, static site generators | Git hosting, Hugo, Sphinx, MkDocs | Contributors' Git skills, CI available | Hard for non-technical reviewers |
| Workflow and planning | Briefs, calendars, approvals | Work-management tools; editorial workflow tools | Integrates with CMS; audit trail of approvals | Approvals outside the CMS lose traceability |
| Translation management (TMS) | Jobs, memory, term base, vendors | Commercial TMS platforms | XLIFF support, connectors to your CMS, memory ownership | Memory held in a vendor's format |
| Prose linting | Style and terminology checks as code | Vale (latest release v3.25.1, 22 October 2026)[^vale-release] | Rule language, CI integration, editor plugins | Rules need owners or they drift |
| DAM | Images, files, rights, expiry | DAM platforms | Rights metadata, renditions, CMS integration | Asset sprawl if DAM and CMS both store files |
| Analytics and audit | Usage, search, inventory | Web analytics, site crawlers, CMS exports | Can join usage to the register | Page views mistaken for value |

Selection advice: write the content model and the workflow on paper first, then test two or three candidates against them with
real content. A tool that cannot express your model or enforce your tiers will push the process back into spreadsheets.

### Automation and AI

Automation has an obvious, low-risk core in ContentOps: schema validation, style and terminology linting, link checking,
accessibility checks, review-date reminders, routing to the right reviewer, and publishing to several channels from one source.
Do these first; they remove waiting and copying without changing who is accountable.

Generative AI is useful for drafting variants, summarising, suggesting metadata and first-pass translation, and risky for the
same reason: it produces fluent text that can be wrong. The NIST Generative AI Profile names this risk "confabulation", "the
production of confidently stated but erroneous or false content", alongside information-integrity and intellectual-property
risks.[^nist-genai] Operational rules that follow:

- **Keep a named human accountable for every published item**, whatever drafted it, and record which items had AI assistance.
- **Never let generated text bypass the tier rules.** A tier-3 statement drafted by a model still needs its risk approver.
- **Ground generation in approved sources** (the term base, approved components) rather than a model's general knowledge.
- **Check the law where you publish.** In the EU, Article 50(4) of the AI Act requires deployers who publish AI-generated or
  manipulated text "published with the purpose of informing the public on matters of public interest" to disclose it. The
  exceptions are uses authorised by law for criminal investigations, and content that "has undergone a process of human review
  or editorial control" where "a natural or legal person holds editorial responsibility for the publication of the
  content".[^ai-act-50] The responsible party may therefore be the organisation, not a named individual; naming one is this
  Atlas's operational advice, not the law's requirement. These deployer duties have applied since 2 August 2026; the Digital
  Omnibus on AI, published in the Official Journal on 24 July 2026 and in force from 27 July, left them on that date and added a
  transitional period only for the labelling of synthetic content.[^garrigues-omnibus][^csa-omnibus] This is not legal advice;
  check with counsel for your case.
- **Search engines judge quality, not origin.** Google's 2023 guidance rewards high-quality content "however it is produced";
  generating content primarily to manipulate rankings breaks its spam policies.[^google-ai] Depth: [SEO Operations](../seo-operations/).

## ContentOps in practice

### Reference implementation: operating artefacts

The design below fits a mid-sized organisation (one website, one app, help centre, four locales, about 3,000 live items, a team of
six to ten content people). Assumptions: a headless or hybrid CMS with workflow states and roles, a TMS that accepts XLIFF, CI
available for checks. The artefacts are illustrative, not tied to one product; adapt field names to your CMS.

**Artefact 1: a content type definition.** The model states meaning, limits and ownership fields. The same structure drives the
CMS configuration and the validation in [Lab 2](#lab-2-intermediate-validate-entries-against-a-content-model).

_Example status: syntax-checked (JSON), not executed against a CMS._

```json
{
  "type": "help_article",
  "description": "Task-based help for one user goal",
  "fields": {
    "title": {"kind": "text", "required": true, "max": 70},
    "summary": {"kind": "text", "required": true, "max": 160},
    "steps": {"kind": "list", "of": "step", "required": true},
    "applies_to": {"kind": "refs", "to": "product", "required": true},
    "disclaimer": {"kind": "ref", "to": "legal_component", "required": false},
    "audience": {"kind": "enum", "values": ["customer", "admin", "partner"]},
    "risk_tier": {"kind": "enum", "values": [1, 2, 3], "required": true},
    "owner": {"kind": "person", "required": true},
    "review_by": {"kind": "date", "required": true},
    "locales": {"kind": "list", "of": "locale", "required": true}
  }
}
```

**Artefact 2: workflow states and rules.** Encode who may move an item between states, per tier. The states and transitions
are the same as in the [lifecycle state machine](#the-content-lifecycle): every arrow in the diagram has one rule here.

_Example status: syntax-checked (YAML), illustrative; real CMSs express this in their own configuration._

```yaml
workflow: editorial-v2
states: [requested, declined, draft, in_review, approved, scheduled,
         live, review_due, withdrawn, unpublished]
transitions:
  - {from: requested, to: draft, by: [contentops_lead],
     requires: [owner, risk_tier, brief]}
  - {from: requested, to: declined, by: [contentops_lead],
     requires: [reason]}
  - {from: draft, to: in_review, by: [writer]}
  - {from: in_review, to: draft, by: [editor, sme, risk_approver]}
  - {from: in_review, to: approved, by: [editor], when: "tier == 1"}
  - {from: in_review, to: approved, by: [editor], when: "tier == 2 and sme_ok"}
  - {from: in_review, to: approved, by: [risk_approver],
     when: "tier == 3 and editor_ok and sme_ok"}
  - {from: approved, to: scheduled, by: [editor], requires: [publish_at]}
  - {from: scheduled, to: live, by: [system], when: "now >= publish_at"}
  - {from: scheduled, to: draft, by: [contentops_lead],
     when: "launch changed"}
  - {from: live, to: review_due, by: [system], when: "today >= review_by"}
  - {from: review_due, to: live, by: [owner], sets: "review_by += 6 months"}
  - {from: review_due, to: draft, by: [owner], when: "needs update"}
  - {from: review_due, to: withdrawn, by: [owner]}
  - {from: withdrawn, to: unpublished, by: [contentops_lead],
     requires: [redirect_or_reason]}
  - {from: live, to: unpublished, by: [contentops_lead],
     requires: [redirect_or_reason], when: "duplicate or published in error"}
emergency:            # live content that is wrong; see Exceptions
  contain: {by: [on_duty_editor], allowed: [remove_statement, replace_with_link]}
  correct_tier3: {requires: risk_approver_consent_before_publish, log: true}
service_levels_working_days:
  editor_review: 2
  sme_review: 3
  risk_review: 3
  translation_per_locale: 5
escalation:
  review_due_overdue_days: 20
  escalate_to: owner_manager
  sme_sla_breach_tier2:   # exception path 2; never for tier 3
    by: [contentops_lead]
    allows: approve_without_sme
    creates: accuracy_check_task
```

**Artefact 3: the content register columns.** One row per live item, exported monthly from the CMS:
`id, url, title, type, collection, owner, owner_active, risk_tier, last_reviewed, review_by, locales, views_90d, regulatory,
topic, status`. [Lab 1](#lab-1-beginner-content-inventory-and-rot-triage) runs on a subset of these columns.

**Artefact 4: style rules as code.** Terminology and house-style rules for Vale, shown in [Lab 3](#lab-3-intermediate-lint-style-and-terminology-in-ci).

**Artefact 5: governance charter and templates.** See [Templates](#templates): request form, brief, review form, retirement
record, decision record.

### Hands-on labs

Labs 1, 2 and 4 use **synthetic data**, Python 3.8 or later and the standard library only; no accounts, no cost. They were run on
2026-10-23 exactly as printed (Python 3.8.10, Ubuntu Linux) and the expected outputs are copied from those runs. Lab 3 needs the
Vale command-line tool and was **not executed** for this page.

::: warning Practise on copies
Run audits on an export, not on the live CMS, and never bulk-unpublish from a script. Retirement decisions need an owner's
approval and redirects.
:::

#### Lab 1 (beginner): content inventory and ROT triage

**Objective.** Flag ownerless, outdated, likely redundant and likely trivial items in an inventory and compute three health
metrics. **Prerequisites.** Python 3.8+, a bash shell. **Time.** 20 minutes. **Risk.** None (synthetic data).

1. Create the folder, the inventory and the list of active owners.

_Example status: verified by execution on 2026-10-23 (bash, Linux)._

```bash
mkdir -p ~/contentops-labs/lab1 && cd ~/contentops-labs/lab1
cat > inventory.csv <<'CSV'
id,url,title,type,owner,last_reviewed,review_by,views_90d,regulatory,topic
C01,/pricing,Pricing plans,landing,ana,2026-09-01,2027-03-01,18200,no,pricing
C02,/pricing-2023,Pricing plans 2023,landing,ana,2023-02-10,2023-08-10,140,no,pricing
C03,/help/reset-password,Reset your password,help,raj,2026-05-20,2026-11-20,9400,no,login
C04,/help/password-reset,How to reset a password,help,,2024-01-15,2024-07-15,310,no,login
C05,/legal/privacy,Privacy notice,legal,lee,2026-02-01,2027-02-01,2100,yes,privacy
C06,/blog/office-party-2019,Our office party 2019,blog,tom,2019-12-20,,12,no,culture
C07,/help/export-data,Export your data,help,raj,2025-06-01,2025-12-01,4300,no,data
C08,/guides/api-quickstart,API quickstart,guide,mia,2026-08-15,2027-02-15,7600,no,api
C09,/guides/api-v1,API v1 guide,guide,mia,2022-03-01,2022-09-01,95,no,api
C10,/legal/terms-2021,Terms of service 2021,legal,lee,2021-05-01,,40,yes,terms
C11,/events/webinar-q3,Q3 webinar recording,event,tom,2026-07-30,2026-10-30,800,no,events
C12,/help/billing-faq,Billing FAQ,help,sam,2026-03-10,2026-09-10,5200,no,billing
CSV
printf 'ana\nraj\nlee\nmia\nsam\n' > active_owners.txt
```

2. Save the script as `triage.py`.

_Example status: verified by execution on 2026-10-23 (Python 3.8.10)._

```python
"""ROT triage of a content inventory (synthetic data, stdlib only)."""
import csv
from collections import defaultdict
from datetime import date

TODAY = date(2026, 10, 23)        # fixed so the output is reproducible
LOW_TRAFFIC = 100                 # views in 90 days; tune per site
owners = {l.strip() for l in open("active_owners.txt") if l.strip()}
rows = list(csv.DictReader(open("inventory.csv", newline="")))

by_topic = defaultdict(list)
for r in rows:
    by_topic[r["topic"]].append(r)

def flags(r):
    f = []
    if not r["owner"] or r["owner"] not in owners:
        f.append("ownerless")
    due = r["review_by"]
    if not due or date.fromisoformat(due) < TODAY:
        f.append("outdated")
    peers = [p for p in by_topic[r["topic"]] if p is not r]
    if peers and int(r["views_90d"]) < min(int(p["views_90d"]) for p in peers):
        f.append("redundant?")
    if int(r["views_90d"]) < LOW_TRAFFIC and r["regulatory"] == "no":
        f.append("trivial?")
    return f

def proposal(r, f):
    if r["regulatory"] == "yes":
        return "KEEP-ARCHIVE (legal owner decides)" if f else "KEEP"
    if "redundant?" in f:
        return "MERGE/REDIRECT"
    if "trivial?" in f:
        return "RETIRE"
    if "outdated" in f or "ownerless" in f:
        return "REVIEW"
    return "KEEP"

print(f"{'id':<4} {'flags':<34} proposal")
counts = defaultdict(int)
for r in rows:
    f = flags(r)
    p = proposal(r, f)
    counts[p.split(" ")[0]] += 1
    print(f"{r['id']:<4} {','.join(f) or '-':<34} {p}")

n = len(rows)
fresh = sum(1 for r in rows
            if r["review_by"] and date.fromisoformat(r["review_by"]) >= TODAY)
ownerless = sum(1 for r in rows if "ownerless" in flags(r))
rot = sum(1 for r in rows if proposal(r, flags(r)) in ("RETIRE", "MERGE/REDIRECT"))
print(f"\nItems: {n}")
print(f"Freshness compliance: {fresh}/{n} = {fresh / n:.0%}")
print(f"Ownerless rate:       {ownerless}/{n} = {ownerless / n:.0%}")
print(f"ROT candidates:       {rot}/{n} = {rot / n:.0%}")
print("Proposals:", dict(sorted(counts.items())))
```

3. Run it with `python3 triage.py`.

**Expected output.**

```text
id   flags                              proposal
C01  -                                  KEEP
C02  outdated,redundant?                MERGE/REDIRECT
C03  -                                  KEEP
C04  ownerless,outdated,redundant?      MERGE/REDIRECT
C05  -                                  KEEP
C06  ownerless,outdated,trivial?        RETIRE
C07  outdated                           REVIEW
C08  -                                  KEEP
C09  outdated,redundant?,trivial?       MERGE/REDIRECT
C10  outdated                           KEEP-ARCHIVE (legal owner decides)
C11  ownerless                          REVIEW
C12  outdated                           REVIEW

Items: 12
Freshness compliance: 5/12 = 42%
Ownerless rate:       3/12 = 25%
ROT candidates:       4/12 = 33%
Proposals: {'KEEP': 4, 'KEEP-ARCHIVE': 1, 'MERGE/REDIRECT': 3, 'RETIRE': 1, 'REVIEW': 3}
```

**Validation.** Check three rows by hand. C06 is owned by "tom", who is not in the active list, has no review date and 12 views:
ownerless, outdated, trivial, so retire. C11 is also Tom's, current and used, so it needs a new owner, not retirement. C10 is old
but regulatory: the script refuses to propose retirement and hands the decision to legal. Freshness: only C01, C03, C05, C08 and
C11 have review dates on or after 2026-10-23, so 5 of 12.

**Troubleshooting.** `ValueError: invalid isoformat string`: a date is not `YYYY-MM-DD`; fix the export. All items flagged
"redundant?": your `topic` column is too coarse; use a finer topic or a canonical-URL field.

**Teardown.** `rm -rf ~/contentops-labs/lab1`

#### Lab 2 (intermediate): validate entries against a content model

**Objective.** Enforce a content model in a script that could run in CI: required fields, length limits, allowed values, valid
dates, no markup in plain-text fields (NPR's "eliminate markup from content"[^npr]) and resolvable references.
**Prerequisites.** Python 3.8+. **Time.** 25 minutes. **Risk.** None.

1. Create the folder and the model.

_Example status: verified by execution on 2026-10-23 (bash, Linux)._

```bash
mkdir -p ~/contentops-labs/lab2 && cd ~/contentops-labs/lab2
cat > model.json <<'JSON'
{
  "type": "product_notice",
  "fields": {
    "id": {"kind": "id", "required": true},
    "headline": {"kind": "text", "required": true, "max": 70},
    "summary": {"kind": "text", "required": true, "max": 160},
    "body": {"kind": "rich", "required": true},
    "audience": {"kind": "enum", "required": true,
                 "values": ["customer", "partner", "internal"]},
    "locale": {"kind": "enum", "required": true,
               "values": ["en-GB", "de-DE", "fr-FR", "ja-JP"]},
    "owner": {"kind": "text", "required": true, "max": 40},
    "review_by": {"kind": "date", "required": true},
    "related": {"kind": "refs", "required": false}
  }
}
JSON
```

2. Create `entries.json` with three entries (one valid, two with deliberate defects).

_Example status: verified by execution on 2026-10-23 (JSON loaded by the script below)._

```json
[
  {"id": "N-100", "headline": "Scheduled maintenance on 2 November",
   "summary": "The billing portal is read-only from 01:00 to 03:00 UTC.",
   "body": [{"p": "Payments made in that window are queued."}],
   "audience": "customer", "locale": "en-GB", "owner": "ana",
   "review_by": "2026-11-03", "related": ["N-090"]},
  {"id": "N-101", "headline": "<b>New</b> export formats",
   "summary": "CSV and Parquet exports are now available to all plans.",
   "body": [{"p": "Choose a format in Settings."}],
   "audience": "everyone", "locale": "en-GB", "owner": "",
   "review_by": "2026-02-30", "related": ["N-999"]},
  {"id": "N-102",
   "headline": "Our biggest, boldest and most ambitious update to reports and dashboards",
   "summary": "Dashboards load faster.", "body": [],
   "audience": "customer", "locale": "en-US", "owner": "raj",
   "review_by": "2027-01-15"}
]
```

3. Save the validator as `validate_content.py` and run `python3 validate_content.py; echo "exit=$?"`.

_Example status: verified by execution on 2026-10-23 (Python 3.8.10)._

```python
"""Validate entries against a content model (stdlib only)."""
import json
import re
import sys
from datetime import date

model = json.load(open("model.json"))
entries = json.load(open("entries.json"))
known_ids = {"N-090", "N-100", "N-101", "N-102"}   # stand-in for the CMS index
MARKUP = re.compile(r"<[^>]+>|&[a-z]+;")

def check(e):
    errs = []
    for name, rule in model["fields"].items():
        v = e.get(name)
        if v in (None, "", []):
            if rule["required"]:
                errs.append(f"{name}: required")
            continue
        kind = rule["kind"]
        if kind == "text":
            if MARKUP.search(v):
                errs.append(f"{name}: markup in a plain-text field")
            if "max" in rule and len(v) > rule["max"]:
                errs.append(f"{name}: {len(v)} chars > {rule['max']}")
        elif kind == "enum" and v not in rule["values"]:
            errs.append(f"{name}: '{v}' not in {rule['values']}")
        elif kind == "date":
            try:
                date.fromisoformat(v)
            except ValueError:
                errs.append(f"{name}: '{v}' is not a valid date")
        elif kind == "refs":
            missing = [r for r in v if r not in known_ids]
            if missing:
                errs.append(f"{name}: unknown references {missing}")
    return errs

failed = 0
for e in entries:
    errs = check(e)
    print(f"{e.get('id', '?')}: {'OK' if not errs else 'FAIL'}")
    for msg in errs:
        print(f"  - {msg}")
    failed += bool(errs)
print(f"{len(entries) - failed} of {len(entries)} entries valid")
sys.exit(1 if failed else 0)
```

**Expected output.**

```text
N-100: OK
N-101: FAIL
  - headline: markup in a plain-text field
  - audience: 'everyone' not in ['customer', 'partner', 'internal']
  - owner: required
  - review_by: '2026-02-30' is not a valid date
  - related: unknown references ['N-999']
N-102: FAIL
  - headline: 72 chars > 70
  - body: required
  - locale: 'en-US' not in ['en-GB', 'de-DE', 'fr-FR', 'ja-JP']
1 of 3 entries valid
exit=1
```

**Validation.** The non-zero exit code is the point: in CI it blocks a merge or a publish. Note what the model caught that a
human reviewer might miss: an impossible date (30 February), a locale the organisation does not support, and a reference to an
item that does not exist.

**Troubleshooting.** `json.decoder.JSONDecodeError`: a trailing comma or a smart quote in `entries.json`. If real CMS exports
use other field names, map them before validation rather than loosening the model.

**Teardown.** `rm -rf ~/contentops-labs/lab2`

#### Lab 3 (intermediate): lint style and terminology in CI

**Objective.** Turn two style-guide rules into automated checks with Vale, a tool that "brings code-like linting to
prose",[^vale] and see which alerts fail a build. **Prerequisites.** Vale installed from its official distribution (latest release
v3.25.1 as of 22 October 2026;[^vale-release] rule inheritance needs v3.20.0 or later, not used here), a Git repository with
Markdown files. **Time.** 30 minutes. **Risk.** Low; installing a binary may need approval on managed machines.

_Example status: not executed (Vale not installed in the research environment); configuration follows the Vale documentation as
read on 2026-10-23; YAML syntax-checked._

1. Create the configuration and a house style.

```bash
mkdir -p ~/contentops-labs/lab3/styles/House ~/contentops-labs/lab3/docs
cd ~/contentops-labs/lab3
cat > .vale.ini <<'INI'
StylesPath = styles
MinAlertLevel = suggestion

[*.md]
BasedOnStyles = House
INI
printf 'To log in, click here.\nThe app is very fast.\n' > docs/sample.md
```

2. Save `styles/House/Terms.yml` (a substitution rule at error level).

```yaml
extends: substitution
message: "Use '%s' instead of '%s'."
level: error
ignorecase: true
swap:
  log in: sign in
  click here: select the link text
```

3. Save `styles/House/Hedging.yml` (an existence rule at warning level).

```yaml
extends: existence
message: "Remove '%s'; say what is measurably true."
level: warning
ignorecase: true
tokens:
  - very
  - really
  - simply
```

4. Run `vale docs/` (shows warnings and errors), then `vale --minAlertLevel=error docs/` as the CI gate.

**Expected output (not executed; described from the documentation).** Two error-level alerts from `House.Terms` for "log in"
and "click here", and one warning from `House.Hedging` for "very". Vale documents that only error-level alerts produce a non-zero
exit code, so the second command fails the build because of the two errors, not the warning.[^vale-min] Both commands fail
only on errors, whatever the alert level shown; `--minAlertLevel=error` simply keeps CI logs to the alerts that block.

**Validation.** Fix the sentence to "To sign in, select Sign in." and re-run: the error count should drop to zero and the exit
code to 0.

**Troubleshooting.** An error naming `StylesPath`: the directory must exist relative to `.vale.ini`.[^vale-ini] No alerts at all:
check that the section glob (`[*.md]`) matches your files and that `BasedOnStyles` names the directory `House`.[^vale-styles]

**Teardown.** `rm -rf ~/contentops-labs/lab3`

#### Lab 4 (advanced): editorial flow metrics from an event log

**Objective.** Compute cycle time (median and 85th percentile), review service-level attainment, first-pass approval and
localisation lag from workflow events, the numbers used in [Metrics and KPIs](#metrics-and-kpis). **Prerequisites.** Python
3.8+. **Time.** 30 minutes. **Risk.** None.

1. Create the event log (five English items, some German and Japanese releases).

_Example status: verified by execution on 2026-10-23 (bash, Linux)._

```bash
mkdir -p ~/contentops-labs/lab4 && cd ~/contentops-labs/lab4
cat > events.csv <<'CSV'
item,locale,event,date
A1,en,brief_accepted,2026-09-01
A1,en,review_requested,2026-09-04
A1,en,review_done,2026-09-05
A1,en,approved,2026-09-05
A1,en,published,2026-09-08
A1,de,published,2026-09-15
A1,ja,published,2026-09-29
A2,en,brief_accepted,2026-09-02
A2,en,review_requested,2026-09-10
A2,en,changes_requested,2026-09-15
A2,en,review_requested,2026-09-17
A2,en,review_done,2026-09-18
A2,en,approved,2026-09-18
A2,en,published,2026-09-22
A2,de,published,2026-09-24
A3,en,brief_accepted,2026-09-03
A3,en,review_requested,2026-09-07
A3,en,review_done,2026-09-08
A3,en,approved,2026-09-08
A3,en,published,2026-09-09
A3,de,published,2026-09-11
A3,ja,published,2026-09-16
A4,en,brief_accepted,2026-09-07
A4,en,review_requested,2026-09-09
A4,en,review_done,2026-09-16
A4,en,approved,2026-09-16
A4,en,published,2026-09-17
A5,en,brief_accepted,2026-09-14
A5,en,review_requested,2026-09-21
A5,en,review_done,2026-09-22
A5,en,approved,2026-09-22
A5,en,published,2026-09-30
A5,de,published,2026-10-09
CSV
```

2. Save `flow_metrics.py` and run `python3 flow_metrics.py`.

_Example status: verified by execution on 2026-10-23 (Python 3.8.10)._

```python
"""Editorial flow metrics from an event log (synthetic data, stdlib only)."""
import csv
import math
from collections import defaultdict
from datetime import date
from statistics import median

REVIEW_SLA_DAYS = 3
ev = defaultdict(lambda: defaultdict(list))
for r in csv.DictReader(open("events.csv", newline="")):
    ev[(r["item"], r["locale"])][r["event"]].append(date.fromisoformat(r["date"]))

def days(a, b):
    return (b - a).days

cycle, reviews_ok, reviews, first_pass, lags = [], 0, 0, 0, []
items = sorted({i for i, loc in ev if loc == "en"})
for i in items:
    e = ev[(i, "en")]
    cycle.append(days(e["brief_accepted"][0], e["published"][0]))
    # Pair each review request with the next response (done or changes).
    answers = sorted(e["review_done"] + e["changes_requested"])
    for req, ans in zip(sorted(e["review_requested"]), answers):
        reviews += 1
        reviews_ok += days(req, ans) <= REVIEW_SLA_DAYS
    first_pass += not e["changes_requested"]
    for (j, loc), le in ev.items():
        if j == i and loc != "en":
            lags.append((loc, days(e["published"][0], le["published"][0])))

cycle.sort()
p85 = cycle[math.ceil(0.85 * len(cycle)) - 1]  # nearest rank
print("Cycle time (days, brief to publish):", cycle)
print(f"  median = {median(cycle)}  p85 = {p85}")
print(f"Review SLA ({REVIEW_SLA_DAYS} days): {reviews_ok}/{reviews} = "
      f"{reviews_ok / reviews:.0%}")
print(f"First-pass approval: {first_pass}/{len(items)} = "
      f"{first_pass / len(items):.0%}")
for loc in sorted({l for l, _ in lags}):
    v = sorted(d for l, d in lags if l == loc)
    print(f"Localisation lag {loc}: {v} median = {median(v)}")
covered = len(lags)
target = len(items) * 2          # every item should reach de and ja
print(f"Locale coverage: {covered}/{target} = {covered / target:.0%}")
```

**Expected output.**

```text
Cycle time (days, brief to publish): [6, 7, 10, 16, 20]
  median = 10  p85 = 20
Review SLA (3 days): 4/6 = 67%
First-pass approval: 4/5 = 80%
Localisation lag de: [2, 2, 7, 9] median = 4.5
Localisation lag ja: [7, 21] median = 14.0
Locale coverage: 6/10 = 60%
```

**Validation.** By hand for item A2: brief accepted 2 September, published 22 September, so 20 days. Its first review took five
days (10 → 15 September, changes requested) and missed the three-day level; the second took one day. A4's single review took seven
days. Those are the two misses in 4 of 6. Calendar days are used for simplicity; production metrics usually count working days.

**Troubleshooting.** `IndexError` on `published`: an item has no publish event yet; filter to published items or report it as
work in progress. Percentiles on five items are fragile; report them only with the count.

**Teardown.** `rm -rf ~/contentops-labs/lab4`

### Use cases and scenarios

Scenarios 1–3 are documented by the organisations themselves; their outcomes are as those organisations describe them, not
independently measured. Scenario 4 is illustrative. The last column is this Atlas's suggested measure for anyone copying the
approach, not a measure the organisations published.

| Scenario | Context | Method | Trade-off | Success measure (Atlas suggestion) |
|---|---|---|---|---|
| 1 Multi-channel news (NPR, documented) | Content needed on browsers, RSS readers, iPods, radio displays, mobile devices and TVs | COPE: content tools not web tools, content separated from display, markup removed | Up-front modelling and API work | New outputs launched without re-architecting |
| 2 Lifecycle governance (GOV.UK, documented) | Many publishing organisations on one domain | Review dates, overdue status, audits, withdraw versus unpublish rules | Editors' time for reviews | Share of content current; retirements recorded |
| 3 Docs-as-code (Microsoft Learn, documented) | Large technical documentation set with outside contributors | Markdown in public GitHub repositories, pull requests, review and sign-off | Contributors need Git; non-technical reviewers struggle | Contributions reviewed and merged within service levels |
| 4 Localised launch (illustrative) | One release, eight locales, legal statements | Components, tiered review, XLIFF hand-off, locale coverage metric | Source freeze earlier than marketing wants | All locales live on launch day |

#### Scenario 1: create once, publish everywhere at NPR (documented)

**Problem.** NPR wanted its content where its users were, not only on its website. **Method.** The three COPE principles
described under [Origins and evolution](#origins-and-evolution), with content in a central database independent of any
presentation layer, so the same story can go to browsers, RSS readers, iPods, radio displays, mobile devices and TVs.[^npr]
**Outcome as described.** Because content was separate from display, NPR says it launched its NPR Music site "without refactoring
the system architecture or our presentation layer code".[^npr] **Pitfall for imitators.** The principle is cheap to state and
expensive to retrofit: rich-text fields full of layout markup must be remodelled before any API can reuse them, which is why
[Lab 2](#lab-2-intermediate-validate-entries-against-a-content-model) rejects markup in plain-text fields.

#### Scenario 2: review dates and retirement rules at GOV.UK (documented)

**Problem.** Hundreds of departments, agencies and public bodies share one domain;[^govuk-orgs] stale content misleads citizens. **Method.** Review dates
with a visible overdue status,[^govuk-manage] explicit withdraw and unpublish rules (see [The content lifecycle](#the-content-lifecycle)),[^govuk-retire]
and editor-run audits such as the 2016 early-years audit.[^govuk-audit] **Trade-off.** Reviews consume editor
time and depend on owners responding. **What to copy.** The vocabulary (overdue, withdraw, unpublish) and the default to update
rather than delete.

#### Scenario 3: documentation as code at Microsoft Learn (documented)

**Problem.** A very large documentation set needs corrections from many people, including outside contributors. **Method.**
Public GitHub repositories: minor fixes through an "Edit" link that opens a pull request, major changes through a fork and a
pull request that is reviewed and signed off;[^mslearn-edit] reviewing pull requests is itself a listed contribution.[^mslearn]
**Trade-off.** Training modules are
not open to public edits,[^mslearn-edit] and Git is a barrier for many subject experts. **What to copy.** The review workflow,
history and automated checks come with the repository, which is the docs-as-code argument in short.[^wtd]

#### Scenario 4: an eight-locale product launch (illustrative)

::: example Illustrative scenario: launch content for a pricing change
A software company changes its plans and prices on 1 March in eight locales. **Method.** Prices live in one structured
component (amount, currency, plan, effective date) referenced by the pricing page, the in-app upgrade screen, three help articles
and the order confirmation email. The legal text is a tier-3 component approved once by legal. English source is frozen 15
working days before launch, sent as XLIFF, and translations are reviewed in-market. **Measures.** Locale coverage on launch day
(target 100 %), zero price mismatches found by a scripted cross-channel check, localisation lag. **Trade-off.** Marketing wanted
to keep editing copy until a week before launch; the freeze was negotiated down to ten days for tier-1 copy only. **Pitfall.** A
screenshot in two help articles still showed old prices: images escape structured content, so the checklist now includes
"screenshots that show prices or plan names".
:::

## Measure, govern, pay

### Metrics and KPIs

No standard set of ContentOps metrics exists. The set below is this Atlas's proposal, grouped into **flow** (is production
predictable?), **health** (is the live estate trustworthy?) and **outcome** (does content do its job?). Flow and health metrics are
leading indicators; outcomes lag and are noisy.

| KPI | Definition / formula | Data source | Pitfall | Cadence |
|---|---|---|---|---|
| Cycle time | Days from brief accepted to first publication; report median and 85th percentile per tier | Workflow events | Averages hide the slow tail; count working days consistently | Weekly |
| Review SLA attainment | Reviews answered within the service level ÷ reviews requested | Workflow events | Count every review round, not only the last | Weekly |
| First-pass approval rate | Items approved with no "changes requested" ÷ items approved | Workflow events | Can be gamed by soft reviews; pair with defect escape rate | Monthly |
| Defect escape rate | Corrections to published items for factual or policy errors ÷ items published | Corrections log | Typos and facts mixed; classify severity | Monthly |
| Freshness compliance | Live items whose review date has not passed ÷ live items in scope | Register | Items with no review date count as non-compliant | Monthly |
| Ownerless rate | Live items with no active owner ÷ live items | Register + HR or directory | Team aliases hide departed owners | Monthly |
| ROT ratio | Items marked retire or merge in an audit ÷ items audited | Audit | Not comparable across collections of different age | Per audit |
| Localisation lag | Days from source publication to locale publication; median per locale | Workflow events | Missing locales do not appear in a lag; pair with coverage | Monthly |
| Locale coverage | Locale versions published ÷ locale versions required | Register | Define "required" per collection, not globally | Monthly |
| Reuse rate | (Component placements − distinct components) ÷ component placements | CMS reference index | Reuse of wrong content spreads errors; tie to tiering | Quarterly |
| Volatile-fact component coverage | Occurrences of volatile facts (prices, limits, legal text) that are component references ÷ all occurrences of those facts | Reference index + scripted search for copies | Needs a list of volatile facts and a search for copied values | Quarterly |
| Task success | Share of users who complete the task the content supports (survey, usability test, or a behavioural proxy) | Research, analytics | Page views and time on page are not success | Quarterly |
| Content-attributable contacts | Support contacts tagged "content was wrong or missing" ÷ contacts | Support tagging | Needs consistent tagging with [SupportOps](../supportops/) | Monthly |

#### Worked calculation

Use the Lab 4 data and an illustrative register for a help-centre collection of 1,200 live items.

- **Cycle time.** Five items took 6, 7, 10, 16 and 20 days. Median = 10 days; 85th percentile by nearest rank: rank =
  ceil(0.85 × 5) = 5, so 20 days. Report "median 10, p85 20, n = 5", because two slow items dominate.
- **Review SLA attainment.** Six review rounds, four answered within three days: 4 ÷ 6 = 67 %. The event log does not record
  who reviewed, so it cannot say where the delay sits. Suppose the review forms (Template 2) show both misses were SME rounds:
  that would point at SME capacity, not editors. In production, add a reviewer-role column to the events.
- **First-pass approval.** Four of five items needed no changes: 80 %.
- **Freshness compliance.** Suppose 1,020 of the 1,200 items have a review date on or after today: 1,020 ÷ 1,200 = 85 %. Items
  with no date at all count as non-compliant.
- **Locale coverage.** Lab 4 required German and Japanese for every item and found 6 of 10 locale versions: 60 %, while median
  German lag (4.5 days) looked healthy. Coverage reveals what lag hides.

**Targets.** Set targets from your own baseline, per tier, after two months of measurement; the charter's 95 % freshness goal is a
destination, not a starting point. **Vanity traps.** Pages published per month (rewards adding, never pruning); total page views
(rewards popular content, not correct content); "AI-generated items" as a productivity figure without a defect escape rate beside
it.

::: figure Measurement and governance loop for a content collection
```mermaid
flowchart TB
  EV["Workflow events and register"] --> FLOW["Flow: cycle time, review SLA, first pass"]
  EV --> HEALTH["Health: freshness, ownerless, ROT, coverage"]
  USE["Research, analytics, support tags"] --> OUT["Outcomes: task success, contact reasons"]
  FLOW --> REV["Monthly health review"]
  HEALTH --> REV
  OUT --> REV
  REV --> ACT{"Council decision"}
  ACT -->|"queue too long"| WIP["Change WIP limits or reviewer capacity"]
  ACT -->|"stale or ownerless"| AUD["Audit; reassign or retire collection"]
  ACT -->|"rule or tier wrong"| STD["Change standards, model or tiers"]
  ACT -->|"content fails users"| STR["Revise brief or strategy"]
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class FLOW,HEALTH,OUT,REV core
  class ACT decision
  class EV,USE,WIP,AUD,STD,STR neutral
```
Text equivalent: Workflow events and the content register produce flow metrics (cycle time, review service level, first-pass
approval) and health metrics (freshness, ownerless rate, ROT, locale coverage). Research, analytics and support tags produce outcome
metrics (task success, contact reasons). All three feed a monthly health review, where the governance council chooses an action:
change work-in-progress limits or reviewer capacity when queues are long; audit, then reassign or retire a collection when content
is stale or ownerless; change the standards, content model or risk tiers when a rule is wrong; revise the brief or strategy when
content fails users.
:::

### Quality, accessibility and legal duties

Content creates legal exposure in ways that are easy to underestimate. What applies depends on jurisdiction and sector; this
section names the common categories and dates time-sensitive points (as of October 2026). It is not legal advice.

| Risk | Example | Control | Owner |
|---|---|---|---|
| Inaccessible content | Images without text alternatives, unclear link text, PDFs that screen readers cannot read | WCAG 2.2 AA[^wcag] criteria in the model (required alt-text field), automated checks, manual testing of templates | Editor, CMS owner |
| Regulated accessibility duty (US public sector) | Web content and apps of US state and local governments | ADA Title II rule: WCAG 2.1 Level AA is the technical standard; compliance from 26 April 2027 for entities with a total population of 50,000 or more, 26 April 2028 for smaller entities and special district governments, dates set by an interim final rule of 20 April 2026[^ada-title2] | Legal, CMS owner |
| Regulated accessibility duty (EU) | Content of in-scope services such as e-commerce, e-books and banking | The European Accessibility Act covers these services[^eaa] and came into effect on 28 June 2025;[^eaa-date] the Commission-funded AccessibleEU guidance says small businesses providing services are generally exempt (Article 4);[^eaa-guide] check national transposition | Legal, product |
| Which WCAG version the EU cites | Conformity evidence for EU duties | EN 301 549 V3.2.1 (WCAG 2.1) stays the legally cited version until V4.1.1 (WCAG 2.2 AA), published 2 September 2026, is cited in the Official Journal, expected 16 December 2026[^en301549] | Legal, CMS owner |
| Wrong regulated statement | Price, contractual term, health or financial claim | Tier-3 review, components with single ownership, emergency correction path | Risk approver |
| Undisclosed AI-generated public-interest text (EU) | AI-drafted public information published without human editorial control | Human review with editorial responsibility held by a natural or legal person, or disclosure (AI Act Art. 50(4))[^ai-act-50] | Editor-in-chief, legal |
| Copyright and licences | Stock images past licence expiry; quoted text without permission | Rights metadata and expiry dates in the DAM; retirement on expiry | Owner, DAM manager |
| Personal data in content | Customer names in case studies, staff photos after they leave | Consent records, review dates on people content; GOV.UK treats personal details as a reason to unpublish[^govuk-retire] | Owner, privacy ([PrivacyOps](../privacyops/)) |
| Plain language | Notices that readers cannot act on | Plain-language standard (ISO 24495-1)[^iso-plain] where required; readability checks as warnings, not gates | Editor |

**Least privilege in the CMS.** Separate roles for drafting, approving and publishing; restrict who can edit tier-3 components;
keep an audit trail of approvals for as long as your records policy requires (legal decides the period). **Evidence retention.**
For regulated statements keep the approved version, the approver and the publication date; a CMS revision history is evidence only
if it cannot be edited by the people it records.

### Cost, capacity and sustainability

The main cost of content is people's time over the item's whole life, not the CMS licence. Useful unit economics:

- **Cost per published item** = (hours × loaded hourly rate for writing, review and publishing + translation + tool cost share) ÷
  items published. Illustrative: 6 hours × 60 per hour + 4 locales × 80 per locale + 15 tool share = 695 per help article.
- **Cost of keeping an item** = review hours per year × rate. At 0.5 hours a year, a 3,000-item estate costs 1,500 hours a year
  just to stay current, before any change. This is why retirement is a cost control, not housekeeping.
- **Translation cost** scales with new and changed words times locales; reuse and translation memory reduce it because unchanged
  segments are not re-translated. Freezing source text before hand-off is the cheapest saving.
- **Capacity.** Plan in item-equivalents per tier (for example, one tier-3 item consumes three tier-1 slots of review capacity) and
  set work-in-progress limits per stage; the binding constraint is usually SME or legal review, not writing.

**Sustainability.** Fewer pages mean less to crawl, store, translate and serve; page weight and delivery belong to
[WebOps](../webops/) and [GreenOps](../greenops/). The stronger argument is human: an estate that only grows eventually consumes all
capacity in maintenance.

### Assurance of the operating model

How do you know the system works, not just that this month's numbers look good?

- **Quarterly audit of one collection**, rotating, against stated criteria (current, owned, accurate, accessible, findable),
  with a sample checked by someone outside the team.
- **Control tests.** Pick five tier-3 items each quarter and verify that the recorded approver is the named risk approver and
  approved the version that went live.
- **Exception log review.** Emergency containments, emergency corrections and skipped reviews are counted; a rising count means
  the normal path is too slow.
- **Risk indicators.** Ownerless rate rising after reorganisations; overdue reviews concentrated in one owner; a collection whose
  traffic falls while support contacts about it rise.
- **Feedback to strategy.** Each quarter, report the collections that cost most to maintain and deliver least.

## When things go wrong

### Common failures and troubleshooting

| Symptom | Likely cause | Diagnosis | Remediation | Prevention |
|---|---|---|---|---|
| The same fact differs across pages | Copied text instead of a referenced component | Search for the fact's distinctive phrase across channels | Replace copies with one component; correct all | Model facts that change (prices, limits) as components |
| Reviews take weeks | One reviewer for everything; no service levels | Review SLA attainment by reviewer | Add reviewers, tier the reviews, set and publish levels | WIP limits and escalation rules |
| Launch-day content in only some languages | Source changed after hand-off; no coverage metric | Compare source publish dates with locale dates | Freeze and resend; publish with clear "English only" note where allowed | Source freeze; locale coverage on the launch checklist |
| Help centre full of outdated articles | No review dates, or reminders ignored | Freshness and ownerless rates by collection | Audit; reassign or retire | Review-due state with escalation |
| Retired pages produce 404s | Unpublished without redirects | Crawl or server logs for retired URLs | Add redirects to the closest current content | Retirement record requires a redirect decision |
| New CMS, same mess | Migrated everything without audit or modelling | Count items migrated vs items with owners | Audit and retire post-migration | Audit and model before migrating (Barker's first scenario)[^barker] |
| Linting ignored | Too many warnings; rules without owners | Alert counts by rule | Cut to the rules that matter; errors only for hard rules | Each rule has an owner and a reason link |

### Worked incident: a wrong price in eight locales

::: example Illustrative scenario: runbook in action
**Trigger.** At 09:10 on a Tuesday, support reports three contacts quoting a monthly price of 19 for a plan that costs 29. The
pricing page is right; the comparison table on the help article "Choose a plan" and its seven translations show 19.

**Severity.** Tier-3 content (price), customer-facing, eight locales: severity 1 under the team's policy (wrong price or legal
statement live).
:::

In this illustrative scenario, the team followed this runbook, in order:

1. **Contain (owner: on-duty editor, target 30 minutes, no approval needed).** Remove the comparison table from the article in
   all locales, or replace it with a link to the pricing page. Do not wait for translations: removing a wrong statement is faster
   than correcting it in eight languages, and it adds no new claim, which is why the governance rules allow it without approval.
2. **Notify (ContentOps lead, 1 hour).** Inform the risk approver (legal or pricing), support (with a reply macro) and the
   product owner. Record the time of each notification.
3. **Diagnose (ContentOps lead and CMS owner, same day).** Why was the price typed into a table instead of referenced? Check the
   item's history: the table was pasted from a slide during a deadline, bypassing the price component, and tier-3 review did not
   trigger because the article was tier 2.
4. **Correct (writer, risk approver, translators).** Rebuild the table using the price component; the risk approver approves
   it **before** it is republished (by message if urgent, logged with the time); send only the changed segments for translation;
   publish all locales.
5. **Verify.** Script a search for the wrong value across all channels and locales; ask support to confirm no new contacts.
6. **Remediate customers (product and legal).** Whether customers are owed anything is a legal decision, not a content one.
7. **Learn (within five working days).** Blameless review: the control gap was that tier was set per item, not per statement.
   Actions: any item that contains a price must reference the price component (schema rule); tier is computed from the components
   an item contains; add "prices outside components" to the monthly scripted check.

::: figure Incident flow for wrong published content
```mermaid
flowchart TB
  A["Report: wrong statement live"] --> B{"Tier 3 or harmful?"}
  B -->|"yes"| C["Contain within 30 min, no approval: remove or link"]
  B -->|"no"| D["Normal correction through workflow"]
  C --> E["Notify risk approver, support, owner"]
  E --> F["Diagnose: history, copy or component, why review missed it"]
  F --> G["Correct source; approver consents before republish"]
  G --> H["Verify across channels and locales"]
  H --> I["Blameless review: control change, schema rule"]
  D --> H
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  class A,C risk
  class B decision
  class E,F,G,H,I,D core
```
Text equivalent: A report says a wrong statement is live. If it is tier 3 or harmful, the on-duty editor contains it within 30
minutes, without approval, by removing it or replacing it with a link; the team notifies the risk approver, support and the owner,
diagnoses from the item's history whether it was copied rather than referenced and why review missed it, corrects the source with
the risk approver's consent before it is republished and translates only changed segments, verifies across channels and locales, and holds a blameless review that produces a control change such as a schema rule.
If it is not tier 3, it goes through the normal correction workflow and is then verified.
:::

### Anti-patterns and myths

- **"The new CMS will fix it."** A migration without an audit moves the mess and adds a deadline; see the
  [migration playbook](#playbook-platform-migration).
- **Approval by committee.** Five reviewers on every blog post produce delay without safety. Tier the reviews; make one person
  accountable per tier.
- **Rich-text everything.** One big formatted body field is quick to build and blocks reuse, validation and localisation. Model
  the parts that change or repeat.
- **Owner = team alias.** "Owned by Marketing" means owned by nobody. Name a role holder and re-check after reorganisations.
- **Audit as a one-off project.** A spreadsheet of decisions with no scheduled work behind it decays within a quarter. Put audit
  actions in the calendar and track completion.
- **Myth: "Structured content is only for documentation teams."** Any content that appears in more than one place or language
  benefits; NPR's case is news, not manuals.[^npr]
- **Myth: "AI makes governance unnecessary."** Generation increases volume and the risk of confident errors;[^nist-genai] it makes
  ownership, review and retirement more important, not less.
- **Myth: "Deleting content hurts us."** Some retirements need care (inbound links, regulatory records), which is why the
  withdraw/unpublish distinction exists; but keeping wrong content has its own cost in support contacts and trust.

## Deciding and adopting

### When to use and when not to use

**Invest in a deliberate ContentOps when** several of these are true: content appears in more than one channel or language;
more than a handful of people create or approve content; content carries legal, safety or pricing risk; the estate is large
enough that nobody can name every item (this Atlas's heuristic: about 300 items, as in the tree below); support contacts are caused by wrong or
missing content; or a platform migration is coming.

**Do not build a formal ContentOps function when:**

- **One person writes one small site.** A style sheet, a review date in each page's metadata and a quarterly self-audit are
  enough. A workflow tool would cost more than it saves.
- **The strategy is missing.** Operations cannot rescue content nobody needs. Fix the "what and why" first, with a small
  strategy exercise; then operationalise.
- **The content is knowledge from support work.** Use [KnowledgeOps](../knowledgeops/) (see [What ContentOps is not](#what-contentops-is-not)).
- **The real problem is the platform.** If editors cannot publish because the site is down or slow, that is
  [WebOps](../webops/) work.
- **You are about to rename the content team "ContentOps" without changing anything else.** A label without decision rights,
  service levels and a register is a reorganisation, not an operating model.

Hidden responsibilities to budget for: owners' time for reviews (often the scarcest resource), modelling and CMS configuration
skills, translation vendor management, and the political cost of retiring other people's content.

### Decision framework

The most consequential architecture decision is how much structure to adopt. The tree below is this Atlas's proposal; its
assumptions are stated on each branch.

::: figure Decision tree: how much structure does your content need?
```mermaid
flowchart TB
  Q3{"Developer docs by Git users?"}
  Q3 -->|"yes"| A3["Docs-as-code, CI checks"]
  Q3 -->|"no"| Q1{"Reused across channels or locales?"}
  Q1 -->|"no"| A1["Coupled CMS; add workflow and audits at 300+ items or 5+ authors"]
  Q1 -->|"yes"| Q4{"Heavy reuse, 10+ locales?"}
  Q4 -->|"yes"| A4["Component CMS (DITA)"]
  Q4 -->|"no"| A5["Headless or hybrid CMS"]
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class Q1,Q3,Q4 decision
  class A3,A4,A5 core
  class A1 neutral
```
Text equivalent: First ask whether the content is mostly developer documentation written by Git users: if so, use docs-as-code
with schema validation and linting in CI, whether or not it is reused. Otherwise ask whether content is reused across channels or
locales, because reuse is what makes structure pay. If it is not, a coupled CMS is enough: below about 300 live items and five
authors, one named owner and review dates suffice and no ContentOps team is needed; above that, add workflow, a register and
audits to the coupled CMS. If content is reused, ask whether there is heavy conditional reuse and ten or more locales: if so,
consider a component CMS such as a DITA-based one; otherwise use a headless or hybrid CMS with a content model, whatever the
estate's size.
:::

The thresholds (300 items, five authors, ten locales) are heuristics, not research findings; move them to fit your
situation. Among the CMS options, reuse comes before size because a small estate published to a website, an app and six locales already pays the copy-and-paste
cost on every change; size alone only decides how much workflow a single-channel estate needs. For tool choice inside a branch, a
weighted comparison works better than feature lists:

| Criterion | Weight | Questions to score 1–5 |
|---|---|---|
| Expresses our content model | 25 | Typed fields, references, validation, components |
| Enforces our workflow and tiers | 20 | States, roles, approvals recorded, audit trail |
| Localisation fit | 15 | Locale fallback rules, XLIFF or connector to our TMS |
| Editor experience | 15 | Preview, ease of use for non-technical authors |
| Exit and lock-in | 15 | Full export of content and model, open formats |
| Cost over three years | 10 | Licences, usage, implementation, people |

### Maturity model

This is **this Atlas's maturity model**, built for self-assessment; it is not an industry standard. It can be read alongside
Content Science's five levels (Chaotic, Piloting, Scaling, Sustaining, Thriving),[^cs-fact] which run from ad hoc work through
spreading formal operations across functions to optimising them and seeing return on investment; the levels below describe observable controls instead.

| Level | Observable behaviour | Evidence (exit criteria) | Next step |
|---|---|---|---|
| 1 Ad hoc | Content made per request; approvals by email; nobody can count the estate | No register; owners unknown | Build an inventory; name owners for the top collections |
| 2 Repeatable | Intake form, calendar, basic style guide; reviews happen but without service levels | Register exists; ≥ 70 % items owned | Workflow states; risk tiers; review dates on new items |
| 3 Governed | Workflow states enforced in the CMS; tiered approvals; review dates; quarterly audits | Freshness ≥ 80 %; tier-3 control test passes | Content model for top types; components for volatile facts |
| 4 Structured and measured | Content model and components; automated checks in CI; flow and health metrics reviewed monthly | Volatile-fact component coverage ≥ 90 % (see [Metrics and KPIs](#metrics-and-kpis)); review SLA ≥ 85 %; locale coverage tracked | Outcome measures; capacity planning per tier |
| 5 Adaptive | Outcome data changes strategy; retirement is routine; AI assistance governed by the same tiers | Collections retired or merged each quarter on evidence; defect escape rate trending down | Keep pruning; revisit model yearly |

::: figure Maturity progression and the control added at each step
```mermaid
flowchart TB
  L1["1 Ad hoc: count nothing"] -->|"inventory and owners"| L2["2 Repeatable: intake and calendar"]
  L2 -->|"states, tiers, review dates"| L3["3 Governed: enforced workflow"]
  L3 -->|"content model, checks in CI"| L4["4 Structured and measured"]
  L4 -->|"outcomes drive strategy"| L5["5 Adaptive: routine pruning"]
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  class L1,L2 neutral
  class L3,L4,L5 core
```
Text equivalent: Level 1, ad hoc, counts nothing; adding an inventory and owners reaches level 2, repeatable, with intake and a
calendar. Adding workflow states, risk tiers and review dates reaches level 3, governed, with an enforced workflow. Adding a content
model and automated checks in CI reaches level 4, structured and measured. Letting outcome data drive strategy reaches level 5,
adaptive, where pruning is routine.
:::

Most organisations should aim for level 3 before buying new platforms: a headless CMS at level 1 produces structured chaos.

### Adoption roadmap: 30/60/90 days

The plan assumes one ContentOps lead with part-time help from an editor, a CMS owner and an analyst, and one pilot collection
(for example the help centre).

| Window | Actions | Quick wins | Milestone and metric |
|---|---|---|---|
| Days 1–30: see the estate | Export the inventory; add owner and review-date columns; run ROT triage ([Lab 1](#lab-1-beginner-content-inventory-and-rot-triage)); agree risk tiers with legal; publish an intake form | Retire obviously dead items with redirects; reassign ownerless top-traffic items | Register for the pilot; baseline freshness and ownerless rates |
| Days 31–60: control the flow | Define workflow states in the CMS; set review service levels; start the weekly intake meeting; write the style guide's top 20 rules and lint the five hardest ([Lab 3](#lab-3-intermediate-lint-style-and-terminology-in-ci)) | Review queue visible to everyone; first escalations resolved | Cycle time and review SLA measured weekly ([Lab 4](#lab-4-advanced-editorial-flow-metrics-from-an-event-log)) |
| Days 61–90: structure what changes | Model the two most reused content types; move prices and legal statements into components; add schema validation ([Lab 2](#lab-2-intermediate-validate-entries-against-a-content-model)); hold the first monthly health review; write the governance charter | One price change made once and published everywhere | Charter signed; freshness above baseline; plan for the next collection |

Dependencies: legal's agreement on tiers (start in week one), CMS configuration time, and access to support contact reasons for
outcome measures.

## Toolkit

### Checklists

**Quick start (first week)**

- [ ] Inventory exported with owner, review date and traffic columns
- [ ] Risk tiers drafted and sent to legal
- [ ] One intake channel announced
- [ ] Top 20 items by traffic have a named, active owner

**Pre-publication (every item)**

- [ ] Brief linked; content type correct; owner and review date set
- [ ] Automated checks pass (schema, style errors, links, accessibility)
- [ ] Required approvals for the tier recorded on this version
- [ ] Reused facts referenced, not copied
- [ ] Alt text, link text and headings meaningful
- [ ] Locales required for this collection scheduled

**Launch readiness (multi-locale release)**

- [ ] Source frozen and sent for translation by the agreed date
- [ ] Screenshots and images showing changed values updated
- [ ] Cross-channel check for changed facts scripted and run
- [ ] Support briefed; reply macros updated

**Monthly health review**

- [ ] Freshness, ownerless rate and overdue reviews by collection
- [ ] Review SLA attainment by reviewer group
- [ ] Exception log (emergency containments and corrections, skipped reviews)
- [ ] Actions from last month closed

**Governance audit (quarterly)**

- [ ] Five tier-3 items: approver and approved version verified
- [ ] CMS roles: who can publish tier-3 content, reviewed
- [ ] Retirement records: redirect present for retired URLs with traffic
- [ ] Rights expiry: assets past licence date removed

**Retirement**

- [ ] Owner approved; regulatory and legal hold checked
- [ ] Withdraw versus unpublish decided and recorded
- [ ] Redirect target chosen for URLs with traffic or inbound links
- [ ] Translations and reused components handled

### Templates

**Template 1: content request and brief**

```text
CONTENT REQUEST                                   ID: ____  Date: ____
Requester / team:
Goal (what should a reader be able to do or decide?):
Audience and channel(s):
Existing content checked? (links)   [ ] none found  [ ] update instead
Content type:                       Risk tier (1/2/3):
Owner after publication:            Review interval (months):
Locales required:                   Launch date / dependency:
Subject-matter expert:              Risk approver (tier 3):
Success measure (task, contact reason, other):
Decision: [ ] accepted  [ ] deferred to ____  [ ] declined, reason:
```

**Template 2: review form (one per review round)**

```text
REVIEW                      Item: ____  Version: ____  Tier: __
Reviewer role: [ ] editor  [ ] SME  [ ] risk approver
Requested: ____ (date)      Answered: ____ (date)   SLA met: [ ]
Accuracy: [ ] correct  [ ] corrections listed below
Policy or legal: [ ] n/a  [ ] approved  [ ] blocked, reason:
Accessibility: [ ] alt text  [ ] link text  [ ] headings  [ ] tables
Decision: [ ] approve  [ ] changes requested
Comments:
```

**Template 3: retirement record**

```text
RETIREMENT                  Item: ____  URL: ____  Locales: ____
Reason: [ ] outdated  [ ] duplicate  [ ] trivial  [ ] legal/rights
        [ ] personal data  [ ] published in error
Decision: [ ] update instead  [ ] withdraw (notice)  [ ] unpublish
Redirect to: ____               Inbound links checked: [ ]
Regulatory or legal hold checked by: ____
Reused components affected: ____
Approved by owner: ____  Date: ____   Done by: ____  Date: ____
```

**Template 4: one-page governance charter**

```text
CONTENTOPS CHARTER — <collection or organisation>      Version __
Scope: <channels, collections, locales>   Out of scope: <...>
Mission: <one sentence>
Decision rights:
  New content type ........ <content architect>
  Publish tier 1 / 2 / 3 .. <editor> / <editor + SME> / <risk approver>
  Retire .................. <owner>, disputes to <council>
  Style exceptions ........ <managing editor>
Service levels (working days): editor 2, SME 3, risk 3,
  translation 5 per locale
Cadences: intake weekly; health review monthly; audit quarterly
Metrics and targets: freshness >= __%, ownerless <= __%,
  review SLA >= __%, locale coverage >= __%
Escalation: overdue review > 20 days -> owner's manager
Signed: <sponsor>, <ContentOps lead>, <legal>         Date: ____
```

**Template 5: decision record for a platform or model change**

```text
DECISION RECORD  CR-___   Status: proposed | accepted | superseded
Context: <problem, constraints, volumes, channels, locales>
Options considered: <A>, <B>, <C>
Decision: <chosen option>
Consequences: <what gets easier, what gets harder, migration work>
Exit plan: <how content and model would be exported>
Review date: ____
```

### Deep comparisons

| Approach | Strengths | Weaknesses | Choose when |
|---|---|---|---|
| Coupled CMS | Fast to start, visual editing, many plugins | Content bound to page layouts; weak reuse | One site, one language, small team |
| Headless or hybrid CMS | Typed content, APIs for every channel, references | Modelling skills needed; previews harder; usage pricing | Several channels, reuse, a product team to build front ends |
| Component CMS (DITA-style) | Fine-grained reuse, conditional output, mature translation flow | Steep learning curve, specialist tooling | Large technical documentation, many variants and locales |
| Docs-as-code | Version control, review and CI for free[^wtd] | Hard for non-technical contributors | Developer documentation; engineering-heavy teams |
| Spreadsheet plus shared drive | Zero cost | No workflow, no history, copy and paste | Never as a target state; acceptable for a first inventory |

For the comparison with neighbouring operating models, see the
[relations table](#how-contentops-relates-to-other-ops).

### FAQ

**Is ContentOps a job title or a team?** It can be either, or one editor's responsibility. What makes it ContentOps is the operating model (states, owners,
service levels, metrics), not the name.

**Do we need a headless CMS to do ContentOps?** No. Workflow, ownership, review dates, audits and style rules work in any CMS.
Headless helps when content must be reused across channels; see the [Decision framework](#decision-framework).

**Who should own a page: the writer or the business?** The business role that knows whether it is still true (product, policy,
service owner). Writers create and edit; owners answer "is this still correct?" when the review date arrives.

**How often should content be reviewed?** By risk and volatility, not a single interval: prices and legal statements whenever
they change plus a fixed interval; help articles with each product release that touches them; evergreen guidance perhaps yearly;
news is time-bound and is usually withdrawn rather than reviewed (GOV.UK gives news over a year old as an example of content that
can be withdrawn).[^govuk-retire]

**Can we let AI write first drafts?** Yes, under the same tiers and ownership as human drafts, grounded in approved sources, with
records of which items used AI. In the EU, AI-generated public-interest text needs either human review or editorial control, with
a natural or legal person holding editorial responsibility, or a disclosure.[^ai-act-50] Watch the defect escape rate.

**What is a good first metric?** Freshness compliance for one important collection: it forces you to build the register, set
owners and review dates, and it shows progress within weeks.

## Going further

### Advanced topics and emerging direction

- **Content as data for AI assistants (emerging).** Structured, owned, dated content is what retrieval systems need; stale
  content becomes confidently wrong answers. Engineering of retrieval belongs to [LLMOps](../llmops/), corpus ownership for
  operational knowledge to [KnowledgeOps](../knowledgeops/); ContentOps contributes the model, the metadata and the retirement
  discipline.
- **Computed risk tiers (this Atlas's proposal).** Tiers derived from the components an item contains, as in the worked
  incident, instead of being set by hand. We found no published source describing this as common practice.
- **Content graphs and semantic metadata.** Rich relationships between types (product, task, audience, region) enable
  personalisation and better navigation; they need taxonomy governance in the spirit of Z39.19.[^z3919]
- **Machine translation with human post-editing.** It changes the cost and lag of localisation; this page makes no claim about
  quality by language pair, so measure it on your own content and keep in-market review for tier 2 and 3.
- **Provenance and labelling of AI output (regulatory, moving).** Machine-readable marking duties in the EU fall on AI system
  providers (Art. 50(2)), with a transitional period for systems already on the market reported to end on 2 December
  2026;[^csa-omnibus][^garrigues-omnibus] publishers should know what their tools emit and keep human responsibility clear. Media provenance in depth
  belongs to [MediaOps](../mediaops/).
- **Vendor marketing to discount.** Claims that a platform "automates content operations" usually mean workflow features; the
  operating model (owners, tiers, retirement) is still yours to design.

### Learning path

- **Prerequisites.** None. Comfort with spreadsheets helps; basic Git helps for docs-as-code.
- **One-day primer.** Read [What ContentOps is](#what-contentops-is) and [Principles and operating model](#principles-and-operating-model);
  read Barker's post,[^barker] Halvorson's 2008 article[^halvorson] and NPR's COPE post;[^npr] run
  [Lab 1](#lab-1-beginner-content-inventory-and-rot-triage).
- **One-week practice.** Inventory one real collection (export only), propose tiers and owners, run
  [Lab 2](#lab-2-intermediate-validate-entries-against-a-content-model) and [Lab 4](#lab-4-advanced-editorial-flow-metrics-from-an-event-log)
  on a copy of your data, and draft the charter.
- **30-day progression.** Run the first 30 days of the [roadmap](#adoption-roadmap-306090-days); set up Vale with five rules
  ([Lab 3](#lab-3-intermediate-lint-style-and-terminology-in-ci)); read GOV.UK's retirement guidance[^govuk-retire] and the
  plain-language standard's scope.[^iso-plain]
- **Specialisations.** Content modelling and information architecture; localisation operations (XLIFF,[^xliff] translation
  memory); structured authoring (DITA[^dita13]); content analytics; accessibility (WCAG 2.2[^wcag]).
- **Portfolio project.** Take a public website you know, build a 50-item inventory, run ROT triage, model one content type,
  write a one-page charter and a 90-day plan, and present the before-and-after metrics you would expect, labelled as estimates.
- **Further reading.** The open-access collection *Content Operations from Start to Scale*[^evia] and Content Science's maturity
  material.[^cs-maturity]

## Wrap-up

### Executive recap and cheat sheet

| Topic | Remember |
|---|---|
| Definition | The execution layer between content strategy and the CMS: workflow, roles, standards, measurement, lifecycle |
| First decision | Who owns each item, and when is it next reviewed? |
| Architecture choice | Coupled CMS for one site; headless or hybrid for reuse across channels; docs-as-code for developer docs; component CMS for heavy technical reuse |
| Essential practices | One intake; risk-tiered review; content model for what changes or repeats; style rules as code; source freeze before translation; quarterly audits; deliberate retirement |
| Metrics | Cycle time (median, p85), review SLA, first-pass approval, defect escape, freshness, ownerless, ROT, locale coverage, task success |
| Watch-outs | Migrating without auditing; approval committees; rich-text everything; team-alias owners; volume metrics; ungoverned AI drafting |
| Next actions | Export the inventory, name owners for the top collection, agree risk tiers with legal, measure freshness |

### A judgement call: rewrite 4,000 stale pages with AI, or prune first?

::: decision The dilemma
A company's support site has about 4,000 articles. A rebrand and a product rename take effect in ten weeks; most articles mention
the old names, and about a third have not been reviewed for two years. The team has four writers. One proposal: use a generative AI
tool to rewrite all 4,000 articles with the new names and voice in six weeks, with editors spot-checking 5 %. The alternative:
audit and retire first, then rewrite the remainder with AI assistance under normal review.
:::

**Assumptions (illustrative).** Each article takes a writer about 40 minutes to review properly, a sampled scripted edit about
10 minutes, and a retirement record with its redirect about 5 minutes; four writers have roughly 500
review hours in ten weeks; traffic is concentrated, with a few hundred articles receiving most visits; tier-3 statements (prices,
data-retention terms) appear in perhaps 10 % of articles.

**Why the attractive option is risky.** Rewriting everything treats the stale third as worth keeping. A 5 % spot check means
about 3,800 articles go live without a human reading them, including tier-3 statements, which breaks the tier rules. Generated
text can be fluent and wrong ("confabulation" in NIST's terms[^nist-genai]), and a rename touches product behaviour as well as
names, so errors would be specific and plausible. Every article kept also keeps its maintenance cost for years. If the site serves
EU users with public-interest information, publishing AI text without human editorial control would also raise a disclosure
question.[^ai-act-50]

**The decision process.**

1. Run ROT triage on the full inventory ([Lab 1](#lab-1-beginner-content-inventory-and-rot-triage)): suppose it proposes 1,500
   items to retire or merge.
2. Withdraw or unpublish those with redirects, with owners' approval; this alone removes 1,500 rename edits.
3. Split the remaining 2,500 by tier and traffic. Tier-3 and top-traffic articles (say 600) get AI-assisted drafts with full human
   review: 600 × 40 minutes = 400 hours, inside capacity.
4. The remaining 1,900 low-traffic tier-1 and tier-2 articles get a scripted name replacement (deterministic, reviewable as a diff),
   not free rewriting, plus a sampled review and a review date within six months.
5. Count the work that is easy to forget. A 10 % sample of the scripted edits (190 articles) at about 10 minutes each adds
   about 32 hours, so writers carry 432 of their 500 hours. Retirement records and redirects at about 5 minutes each add
   1,500 × 5 minutes = 125 hours; under the RACI this is the ContentOps lead's work (helped by the analyst), approved by owners. If the
   writers had to do it too, the total (about 557 hours) would exceed capacity, and the top-traffic set would have to shrink.

**Uncertainty.** The 1,500 retirement estimate could be wrong in either direction; if triage finds less ROT, the scripted
replacement covers more articles and the review backlog grows. The plan protects the riskiest statements first and accepts slower
voice changes elsewhere.

**Why this is a judgement, not a rule.** If the articles were mostly accurate and the change truly only cosmetic, a bulk AI rewrite
with a larger sample might be defensible. The decision turns on the share of tier-3 content and the share of content worth keeping,
both of which the audit measures before anyone commits.

### Learning objectives and mastery check

After this page you should be able to **explain** where ContentOps sits between strategy and platforms and how it differs from
KnowledgeOps; **design** a lifecycle with states, owners and review dates; **specify** a content type and validate entries against
it; **set** risk tiers and service levels; **calculate and interpret** flow and health metrics; **run** an audit and a retirement;
and **choose** an architecture and a maturity target for a given organisation.

::: answer 1. A team says its help centre is "95 % fresh" because 95 % of items with a review date are not overdue. What is wrong?
The denominator excludes items with no review date, which are the most likely to be stale. Freshness compliance counts every live
item in scope; items without a date are non-compliant.
:::

::: answer 2. Compute the reuse rate for 120 placements of 30 distinct components, and say what risk rises with it.
(120 − 30) ÷ 120 = 75 %. One error in a component now appears in many places, so components that carry facts or legal text need the
highest tier of the items they appear in.
:::

::: answer 3. Six review rounds were answered in 1, 2, 2, 4, 5 and 1 days with a three-day level. What is the attainment, and what do you check next?
Four of six, 67 %. Check which reviewer group the misses belong to; if they cluster on SMEs or legal, add capacity or tiering there
rather than pushing editors.
:::

::: answer 4. A page published in error contains a customer's name. Withdraw or unpublish?
Unpublish (remove), with a redirect if the URL had users, and record the decision. GOV.UK lists personal details as a reason to
unpublish, whereas withdrawing would leave the content visible at its URL.
:::

::: answer 5. A five-person start-up with a 40-page marketing site asks whether to buy a headless CMS and hire a content operations manager. What do you advise?
Probably neither. Following the decision framework: no reuse across channels and a small estate point to a coupled CMS, a style
guide, review dates and one named owner. Revisit when channels, locales or contributors grow.
:::

::: answer 6. German pages have a median localisation lag of four days, yet customers complain that German content is missing. How can both be true?
Lag is measured only on pages that were translated. Measure locale coverage: published locale versions divided by required ones.
Low coverage with low lag means many pages were never sent for translation.
:::

::: answer 7. Why should an item containing a price be tier 3 even if the article is otherwise routine?
Because tiering is about the harm of an error, and the price statement carries legal and financial risk wherever it appears.
Compute the tier from the most sensitive component the item contains (the lesson of the worked incident).
:::

::: answer 8. Your organisation plans a CMS migration in six months. What do you do first?
Inventory and audit, retire and merge, name owners, and model the main content types before migrating. Migrating everything first
moves the problem and spends migration effort on content that should be retired.
:::

### Conclusion

ContentOps is unglamorous by design. It does not decide what an organisation should say, and it does not choose the shiny
platform; it makes sure that what is said is true, owned, consistent across channels and languages, and removed when it stops
being true. The field has a real literature and real foundations (governance in content strategy, NPR's create-once principle,
structured-content and localisation standards), but no standards body and no single definition, so be wary of anyone selling it as
a product. The honest summary is a set of small, testable commitments: every item has an owner and a review date; facts that
change live in one place; reviews are as heavy as the risk and no heavier; flow and health are measured; and retirement is as
deliberate as publication. An organisation that keeps those commitments can adopt any CMS, any channel and any AI tool without
losing control of what it tells people. One that skips them will publish faster and faster into a garden nobody tends.

## Sources and further reading

All sources were opened on 2026-10-23 unless the ledger (`research/contentops-ledger.md`) says otherwise. Legal sources are for
orientation, not advice; check official texts (for EU law, EUR-Lex) before relying on them.

[^barker]: [The Need for Content Operations](https://deanebarker.net/tech/blog/need-for-content-operations) — Deane Barker, 2016-01-27. Checked 2026-10-23.
[^halvorson]: [The Discipline of Content Strategy](https://www.alistapart.com/article/thedisciplineofcontentstrategy) — Kristina Halvorson, A List Apart, 2008-12-16. Checked 2026-10-23.
[^nng]: [Content Strategy 101](https://www.nngroup.com/articles/content-strategy/) — Anna Kaley, Nielsen Norman Group, 2022-11-13. Checked 2026-10-23.
[^cs-build]: [How to Build a Content Operation](https://review.content-science.com/how-to-build-a-content-operation/) — Content Science Review, 2023-08-22. Checked 2026-10-23.
[^cs-fact]: [Content Operations Fact Sheet](https://review.content-science.com/content-operations-fact-sheet/) — Content Science Review, 2022-01-21. Checked 2026-10-23.
[^cs-maturity]: [What's Your Level of Content Operations Maturity?](https://review.content-science.com/whats-your-level-of-content-operations-maturity/) — Colleen Jones, Content Science Review, 2020-01-29 (modified 2021-03-24). Checked 2026-10-23.
[^bailie]: [The rise of content ops (podcast)](https://www.scriptorium.com/2022/02/the-rise-of-content-ops-podcast/) — Scriptorium, Sarah O'Keefe with Rahel Bailie, 2022-02-07. Checked 2026-10-23.
[^tekom]: [Content operations comes of age](https://www.tekom.de/events-online-offline/webinare/webithek/content-operations-comes-of-age) — tekom webinar listing (Rahel Bailie), event date not shown. Checked 2026-10-23.
[^evia]: [Content operations from start to scale](https://www.scriptorium.com/content-operations-from-start-to-scale/) — Scriptorium page on the open-access collection edited by Carlos Evia (Virginia Tech Publishing). Checked 2026-10-23.
[^npr]: [Clean Content = Portable Content](https://www.npr.org/sections/inside/2009/02/clean_content_portable_content.html) — Daniel Jacobson, Inside NPR.org, 2009-02-04. Checked 2026-10-23.
[^boag]: [How To Deal With Redundant, Out-Of-Date And Trivial Content (ROT)](https://www.smashingmagazine.com/2015/06/dealing-with-redundant-out-of-date-trivial-rot-content/) — Paul Boag, Smashing Magazine, 2015-06-11. Checked 2026-10-23.
[^govuk-retire]: [Retire content](https://guidance.publishing.service.gov.uk/writing-to-gov-uk-standards/plan-manage-content/retire-content) — GOV.UK publishing guidance, Government Digital Service, undated. Checked 2026-10-23.
[^govuk-manage]: [Manage existing GOV.UK content](https://guidance.publishing.service.gov.uk/writing-to-gov-uk-standards/plan-manage-content/manage-existing-govuk-content) — GOV.UK publishing guidance, undated. Checked 2026-10-23.
[^govuk-orgs]: [Departments, agencies and public bodies](https://www.gov.uk/government/organisations) — GOV.UK, live list (23 ministerial and 20 non-ministerial departments, 419 agencies and other public bodies on 2026-10-23). Checked 2026-10-23.
[^govuk-audit]: [Finding things audit (1/2): what, why, how](https://insidegovuk.blog.gov.uk/2016/02/19/finding-things-audit-12-what-why-how) — Alan Maddrell, Inside GOV.UK blog, 2016-02-19. Checked 2026-10-23.
[^mslearn-edit]: [Overview of editing documentation on Microsoft Learn](https://learn.microsoft.com/en-us/contribute/content/how-to-write-overview) — Microsoft Learn, updated 2024-05-08. Checked 2026-10-23.
[^mslearn]: [Contribute to Microsoft Learn — contributor guide](https://learn.microsoft.com/en-us/contribute/content/) — Microsoft Learn, 2023-08-30. Checked 2026-10-23.
[^wtd]: [Docs as Code](https://www.writethedocs.org/guide/docs-as-code/) — Write the Docs, undated. Checked 2026-10-23.
[^sanity]: [Content modeling: what it is and how to get started](https://www.sanity.io/docs/content-modelling) — Sanity, last edited 2023-06-26. Checked 2026-10-23.
[^dita13]: [DITA Version 1.3 Part 0: Overview, Plus Errata 02](https://docs.oasis-open.org/dita/dita/v1.3/dita-v1.3-part0-overview.html) — OASIS Standard, 2018-06-19. Checked 2026-10-23.
[^dita20]: [Darwin Information Typing Architecture (DITA) Version 2.0](https://dita-lang.org/dita/resources/oasis-cover) — OASIS DITA TC specification site (cites a working draft). Checked 2026-10-23.
[^xliff]: [XLIFF Version 2.1](https://docs.oasis-open.org/xliff/xliff-core/v2.1/xliff-core-v2.1.html) — OASIS Standard, 2018-02-13. Checked 2026-10-23.
[^xliff22]: [XLIFF Version 2.2. Part 1: Core](https://docs.oasis-open.org/xliff/xliff-core/v2.2/xliff-core-v2.2-part1.html) — OASIS Committee Specification 01, 2025-03-13. Checked 2026-10-23.
[^w3c-i18n]: [Localization vs. Internationalization](https://www.w3.org/International/questions/qa-i18n) — W3C Internationalization, undated. Checked 2026-10-23.
[^wcag]: [Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG22/) — W3C Recommendation, 2024-12-12. Checked 2026-10-23.
[^iso-plain]: [ISO 24495-1:2023 Plain language — Part 1: Governing principles and guidelines](https://accessible-eu-centre.ec.europa.eu/content-corner/digital-library/iso-24495-12023-plain-language-part-1-governing-principles-and-guidelines_en) — AccessibleEU catalogue entry (European Commission); standard text not read. Checked 2026-10-23.
[^z3919]: [ANSI/NISO Z39.19-2005 (R2010) Guidelines for the Construction, Format, and Management of Monolingual Controlled Vocabularies](https://www.niso.org/publications/ansiniso-z3919-2005-r2010) — NISO, 2005, reaffirmed 2010. Checked 2026-10-23.
[^vale]: [Vale documentation: introduction](https://docs.vale.sh/) — Vale project, live docs. Checked 2026-10-23.
[^vale-styles]: [Vale: Styles](https://docs.vale.sh/topics/styles.md) — Vale project, live docs. Checked 2026-10-23.
[^vale-ini]: [Vale: .vale.ini](https://docs.vale.sh/topics/.vale.ini.md) — Vale project, live docs. Checked 2026-10-23.
[^vale-min]: [Vale: MinAlertLevel](https://docs.vale.sh/keys/minalertlevel.md) — Vale project, live docs. Checked 2026-10-23.
[^vale-release]: [Vale releases](https://github.com/vale-cli/vale/releases) — GitHub, latest v3.25.1 published 2026-10-22. Checked 2026-10-23.
[^google-ai]: [Google Search's guidance about AI-generated content](https://developers.google.com/search/blog/2023/02/google-search-and-ai-content) — Google Search Central Blog, 2023-02-08. Checked 2026-10-23.
[^ai-act-50]: [Article 50: Transparency obligations for providers and deployers of certain AI systems](https://artificialintelligenceact.eu/article/50/) — reproduction of Regulation (EU) 2024/1689 by the Future of Life Institute (secondary; EUR-Lex holds the official text). Checked 2026-10-23.
[^csa-omnibus]: [EU AI Act Watermarking Grace Period Ends December 2026](https://labs.cloudsecurityalliance.org/research/csa-research-note-eu-ai-act-article50-watermarking-deadline/) — Cloud Security Alliance research note, 2026-09-21 (secondary analysis). Checked 2026-10-23.
[^garrigues-omnibus]: [The AI Digital Omnibus Regulation has been published, redefining deadlines and simplifying requirements for companies and developers](https://www.garrigues.com/en_GB/garrigues-digital/ai-digital-omnibus-regulation-has-been-published-redefining-deadlines-and) — Garrigues (law firm), 2026-07-24 (secondary; the Official Journal holds the official text). Checked 2026-10-23.
[^nist-genai]: [NIST AI 600-1: Artificial Intelligence Risk Management Framework — Generative Artificial Intelligence Profile](https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.600-1.pdf) — NIST, 2024-07-26. Checked 2026-10-23.
[^eaa]: [European Accessibility Act](https://commission.europa.eu/strategy-and-policy/policies/justice-and-fundamental-rights/disability/union-equality-strategy-rights-persons-disabilities-2021-2030/european-accessibility-act_en) — European Commission, undated. Checked 2026-10-23.
[^eaa-date]: [The EAA comes into effect in June 2025. Are you ready?](https://accessible-eu-centre.ec.europa.eu/content-corner/news/eaa-comes-effect-june-2025-are-you-ready-2025-01-31_en) — AccessibleEU, 2025-01-31. Checked 2026-10-23.
[^eaa-guide]: [Getting to know the European legislation on accessibility (guidance on legislation, PDF)](https://accessible-eu-centre.ec.europa.eu/document/download/7bf9cb97-8ccf-421f-9d2d-6d1283e602ef_en?filename=AccEU_Guidance+on+legislation_English_acc.pdf) — AccessibleEU final report (European Commission), undated; says small businesses providing services are generally exempted [Article 4]. Checked 2026-10-23.
[^en301549]: [EN 301 549 V4.1.1 published](https://nda.ie/news/en301549-published) — National Disability Authority (Ireland), 2026. Checked 2026-10-23.
[^ada-title2]: [Fact Sheet: New Rule on the Accessibility of Web Content and Mobile Apps Provided by State and Local Governments](https://www.ada.gov/resources/2024-03-08-web-rule/) — U.S. Department of Justice, ADA.gov, 2024, with compliance dates as amended by the interim final rule of 2026-04-20. Checked 2026-10-23.

Further reading is listed in the [Learning path](#learning-path).

**Changelog**

- 2026-10-23: first published draft (research, ledger, 13 parts, 9 diagrams, 4 labs of which 3 executed); not yet independently reviewed.
- 2026-10-23 (revision r1, after independent review `reviews/contentops-r1.md`): legal accessibility baseline corrected (WCAG 2.1 AA in US Title II and EN 301 549 V3.2.1; V4.1.1 status; EAA small-business exemption for services); emergency rule unified as contain-without-approval, correct-with-prior-consent; workflow YAML now matches the state machine; decision tree asks about reuse first; migration playbook, DAM/TMS/CCMS glossary rows and a volatile-fact KPI added; governance and measurement loops merged (8 diagrams); attributions tightened (Barker, Halvorson, Boag, Evia, GOV.UK, AI Act Art. 50(4)); XLIFF 2.2 status; p85 formula fixed; Labs 1, 2 and 4 re-run.
- 2026-10-23, post-score polish: decision tree asks the Git-docs question first (matches the recap); WCAG 4.1.1 caveat; GOV.UK organisation count sourced; size threshold and naming callout labelled; Content Science levels in full; EAA changelog wording.
