What ContentOps is
Link to section “What ContentOps is”In 30 seconds
Link to section “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).”[1]
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.
At a glance
Link to section “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 and SEOps, 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) |
The problem it solves
Link to section “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.[2]
- 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”.[2]
- 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.”[3]
- 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.[1] 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
Link to section “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.[1] 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”.[1] 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[3]), 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. 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, search optimisation to SEO Operations, campaign process to MarketingOps, and hosting to WebOps; the relations table gives the handoff for each.
- Not DevOps for words. Docs-as-code borrows version control, review and automated tests from software,[4] 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.
Where it comes from and where it sits
Link to section “Where it comes from and where it sits”Origins and evolution
Link to section “Origins and evolution”ContentOps has no founding manifesto. Its history is a convergence of three older threads, then a label.
- 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.[5] Governance was already in the definition; operations is what governance looks like on a Tuesday.
- 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.[6] This is the technical foundation of reuse.
- Technical communication’s single-sourcing tradition. Standards such as DITA[7] and XLIFF[8] made reuse, conditional publishing and translation workflows routine in documentation teams long before marketing sites went headless.
- 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”.[1] 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.[9][10] Rahel Bailie described ContentOps as “a set of principles” used “to optimize content production”.[3] 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;[11] 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.[12]
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
Link to section “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”[13] | Article → author, Article → product, Product → price |
| Structured content | Content stored as typed fields, without presentation markup, so any channel can render it[6] | 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[6] | One release note rendered to web, email and in-app panel |
| Workflow state | Where an item is in its 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[2] | 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[14] | 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[15] | 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)[16] | Old press release withdrawn; duplicate page unpublished and redirected |
A mental model: an inventory, an assembly line and a garden
Link to section “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
Link to section “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 | 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 | Campaign content, calendars | Campaign and lead process, marketing automation, attribution | The question is about running a campaign, not producing its assets |
| SEO Operations, SEOps | Briefs, metadata, internal links | Search demand, ranking and crawl engineering | The success measure is organic search |
| MediaOps | Assets, metadata, rights | Video and audio pipelines, transcoding, live delivery | The asset is time-based media |
| 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 | Approvals for regulated statements | Legal intake, contracts, legal spend | The question is how legal work is run, not how content gets approved |
| EduOps | Course content production | Learning design, assessment validity, LMS operations | The content is a course with learners and assessments |
| WebOps | Publishing to the web | Hosting, CDN, performance, certificates | The question is how the site runs, not what it says |
Diagram source (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
Link to section “Principles and operating model”Charter and principles
Link to section “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:
- Model before you write. Decide content types and fields before producing at scale. Trade-off: slower first project, much cheaper fifth channel.
- Separate content from presentation. Store meaning, not layout, as NPR put it: “Separate Content from Display” and “Eliminate markup from content”.[6] Trade-off: authors lose some visual control; designers gain consistency.
- 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.
- 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.
- 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.
- Flow over heroics. Limit work in progress, make queues visible, and set service levels for reviews. Trade-off: saying “not this sprint” to requesters.
- Retire as deliberately as you publish. In NN/g’s words, “Content won’t govern itself.”[17] Trade-off: retirement needs authority, granted explicitly.
Fundamentals and building blocks
Link to section “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
Link to section “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
Link to section “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.[17] 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.
Diagram source (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.[18] 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.[16]
Operating model and governance
Link to section “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.[2]
- 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: evidence from the register and the workflow leads to a change of standards, capacity or ownership.
Architecture and workflow
Link to section “Architecture and workflow”Reference architecture: the structured content platform
Link to section “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) |
| TMS | Jobs, translation memory, term base, vendors; exchanges XLIFF files[8] |
| Delivery | APIs and renderers for each channel |
| Analytics and register | Usage, search, feedback, inventory with owners and dates |
Diagram source (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.
End-to-end workflow: one change from request to retirement
Link to section “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.
Diagram source (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).
Practices, standards and tools
Link to section “Practices, standards and tools”Core practices and playbooks
Link to section “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
Link to section “Playbook: intake that protects capacity”- Every request arrives through one form (see Templates); requests by chat or email are redirected to it.
- 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).
- Accepted briefs get a content type, a risk tier, an owner and a target date before any writing starts.
- 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
Link to section “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).
Playbook: audit and ROT triage
Link to section “Playbook: audit and ROT triage”- 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.[18]
- 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 does this with a script.
- Human judgement. Flags are proposals. Boag warns against automatic deletion: low-traffic content can serve a small but important audience or a regulatory need.[2]
- 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.[16]
- 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.[19] Your ratio will differ; the point is that even well-governed estates carry retirable content.
Playbook: localisation without chaos
Link to section “Playbook: localisation without chaos”- Internationalise the source. W3C defines internationalisation as design “that enables easy localization”;[15] in content terms: no text in images, no sentences assembled from fragments, dates and prices as structured fields, room for longer translations.
- Release source in batches once approved, not while drafting; every source change after hand-off costs a re-translation.
- 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”.[8]
- Maintain the term base and memory as owned assets; product names and regulated phrases go into the term base first.
- Review in-market for tier 2 and 3 content: a native reviewer checks meaning, not only grammar.
- Track localisation lag and locale coverage (see Metrics and KPIs) so that locales do not silently fall behind.
Playbook: platform migration
Link to section “Playbook: platform migration”Barker’s list of content-operations services starts with inventory, extraction, migration, content QA, URL integrity and launch management;[1] a CMS migration is where all of them meet. Owner: the ContentOps lead, with the CMS owner for steps 4–7.
- Audit before you move. Run ROT triage (Lab 1) and retire or merge first. Acceptance: every item in scope has a keep, update, merge or retire decision and a named owner.
- 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).
- 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.
- Extract, transform, validate. Move content with scripts and validate it against the target model (Lab 2). Acceptance: zero schema errors on tier-2 and tier-3 items; remaining tier-1 errors listed with owners.
- 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.
- 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.
- 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
Link to section “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[20] | Mandatory only through law or contract, and the main legal baselines still cite WCAG 2.1 AA (see 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[21] | 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);[7] the public DITA 2.0 specification page still cited a working draft[22] | Optional; common in documentation teams |
| XLIFF | Exchange of localisable content between tools | XLIFF 2.1 (2018) is the latest OASIS Standard;[8] XLIFF 2.2 reached Committee Specification on 13 March 2025[23] | Optional; widely supported by TMS tools |
| ANSI/NISO Z39.19 | Construction and maintenance of controlled vocabularies and taxonomies | 2005, reaffirmed 2010[14] | Optional |
Tooling landscape
Link to section “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)[24] | 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
Link to section “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.[25] 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”.[26] 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.[27][28] 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.[29] Depth: SEO Operations.
ContentOps in practice
Link to section “ContentOps in practice”Reference implementation: operating artefacts
Link to section “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.
Example status: syntax-checked (JSON), not executed against a CMS.
{
"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: every arrow in the diagram has one rule here.
Example status: syntax-checked (YAML), illustrative; real CMSs express this in their own configuration.
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 runs on a subset of these columns.
Artefact 4: style rules as code. Terminology and house-style rules for Vale, shown in Lab 3.
Artefact 5: governance charter and templates. See Templates: request form, brief, review form, retirement record, decision record.
Hands-on labs
Link to section “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.
Lab 1 (beginner): content inventory and ROT triage
Link to section “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).
- Create the folder, the inventory and the list of active owners.
Example status: verified by execution on 2026-10-23 (bash, Linux).
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
- Save the script as
triage.py.
Example status: verified by execution on 2026-10-23 (Python 3.8.10).
"""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())))
- Run it with
python3 triage.py.
Expected output.
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
Link to section “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”[6]) and resolvable references. Prerequisites. Python 3.8+. Time. 25 minutes. Risk. None.
- Create the folder and the model.
Example status: verified by execution on 2026-10-23 (bash, Linux).
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
- Create
entries.jsonwith three entries (one valid, two with deliberate defects).
Example status: verified by execution on 2026-10-23 (JSON loaded by the script below).
[
{"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"}
]
- Save the validator as
validate_content.pyand runpython3 validate_content.py; echo "exit=$?".
Example status: verified by execution on 2026-10-23 (Python 3.8.10).
"""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.
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
Link to section “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”,[30] and see which alerts fail a build. Prerequisites. Vale installed from its official distribution (latest release v3.25.1 as of 22 October 2026;[24] 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.
- Create the configuration and a house style.
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
- Save
styles/House/Terms.yml(a substitution rule at error level).
extends: substitution
message: "Use '%s' instead of '%s'."
level: error
ignorecase: true
swap:
log in: sign in
click here: select the link text
- Save
styles/House/Hedging.yml(an existence rule at warning level).
extends: existence
message: "Remove '%s'; say what is measurably true."
level: warning
ignorecase: true
tokens:
- very
- really
- simply
- Run
vale docs/(shows warnings and errors), thenvale --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.[31] 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.[32] No alerts at all:
check that the section glob ([*.md]) matches your files and that BasedOnStyles names the directory House.[33]
Teardown. rm -rf ~/contentops-labs/lab3
Lab 4 (advanced): editorial flow metrics from an event log
Link to section “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. Prerequisites. Python 3.8+. Time. 30 minutes. Risk. None.
- Create the event log (five English items, some German and Japanese releases).
Example status: verified by execution on 2026-10-23 (bash, Linux).
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
- Save
flow_metrics.pyand runpython3 flow_metrics.py.
Example status: verified by execution on 2026-10-23 (Python 3.8.10).
"""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.
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
Link to section “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)
Link to section “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, 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.[6] 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”.[6] 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 rejects markup in plain-text fields.
Scenario 2: review dates and retirement rules at GOV.UK (documented)
Link to section “Scenario 2: review dates and retirement rules at GOV.UK (documented)”Problem. Hundreds of departments, agencies and public bodies share one domain;[34] stale content misleads citizens. Method. Review dates with a visible overdue status,[18] explicit withdraw and unpublish rules (see The content lifecycle),[16] and editor-run audits such as the 2016 early-years audit.[19] 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)
Link to section “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;[35] reviewing pull requests is itself a listed contribution.[36] Trade-off. Training modules are not open to public edits,[35] 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.[4]
Scenario 4: an eight-locale product launch (illustrative)
Link to section “Scenario 4: an eight-locale product launch (illustrative)”Measure, govern, pay
Link to section “Measure, govern, pay”Metrics and KPIs
Link to section “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 | Monthly |
Worked calculation
Link to section “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.
Diagram source (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
Link to section “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[20] 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[37] | 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[38] and came into effect on 28 June 2025;[39] the Commission-funded AccessibleEU guidance says small businesses providing services are generally exempt (Article 4);[40] 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[41] | 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))[26] | 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[16] | Owner, privacy (PrivacyOps) |
| Plain language | Notices that readers cannot act on | Plain-language standard (ISO 24495-1)[21] 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
Link to section “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 and GreenOps. The stronger argument is human: an estate that only grows eventually consumes all capacity in maintenance.
Assurance of the operating model
Link to section “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
Link to section “When things go wrong”Common failures and troubleshooting
Link to section “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)[1] |
| 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
Link to section “Worked incident: a wrong price in eight locales”In this illustrative scenario, the team followed this runbook, in order:
- 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.
- 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.
- 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.
- 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.
- Verify. Script a search for the wrong value across all channels and locales; ask support to confirm no new contacts.
- Remediate customers (product and legal). Whether customers are owed anything is a legal decision, not a content one.
- 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.
Diagram source (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
Link to section “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.
- 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.[6]
- Myth: “AI makes governance unnecessary.” Generation increases volume and the risk of confident errors;[25] 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
Link to section “Deciding and adopting”When to use and when not to use
Link to section “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 (see What ContentOps is not).
- The real problem is the platform. If editors cannot publish because the site is down or slow, that is 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
Link to section “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.
Diagram source (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
Link to section “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),[10] 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); 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 |
Diagram source (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
Link to section “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); 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) | Review queue visible to everyone; first escalations resolved | Cycle time and review SLA measured weekly (Lab 4) |
| 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); 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
Link to section “Toolkit”Checklists
Link to section “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
Link to section “Templates”Template 1: content request and brief
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)
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
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
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
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
Link to section “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[4] | 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.
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.
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).[16]
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.[26] 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
Link to section “Going further”Advanced topics and emerging direction
Link to section “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, corpus ownership for operational knowledge to 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.[14]
- 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;[28][27] publishers should know what their tools emit and keep human responsibility clear. Media provenance in depth belongs to 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
Link to section “Learning path”- Prerequisites. None. Comfort with spreadsheets helps; basic Git helps for docs-as-code.
- One-day primer. Read What ContentOps is and Principles and operating model; read Barker’s post,[1] Halvorson’s 2008 article[5] and NPR’s COPE post;[6] run Lab 1.
- One-week practice. Inventory one real collection (export only), propose tiers and owners, run Lab 2 and Lab 4 on a copy of your data, and draft the charter.
- 30-day progression. Run the first 30 days of the roadmap; set up Vale with five rules (Lab 3); read GOV.UK’s retirement guidance[16] and the plain-language standard’s scope.[21]
- Specialisations. Content modelling and information architecture; localisation operations (XLIFF,[8] translation memory); structured authoring (DITA[7]); content analytics; accessibility (WCAG 2.2[20]).
- 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[12] and Content Science’s maturity material.[42]
Wrap-up
Link to section “Wrap-up”Executive recap and cheat sheet
Link to section “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?
Link to section “A judgement call: rewrite 4,000 stale pages with AI, or prune first?”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[25]), 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.[26]
The decision process.
- Run ROT triage on the full inventory (Lab 1): suppose it proposes 1,500 items to retire or merge.
- Withdraw or unpublish those with redirects, with owners’ approval; this alone removes 1,500 rename edits.
- 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.
- 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.
- 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
Link to section “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.
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.
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.
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.
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.
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.
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.
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).
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
Link to section “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
Link to section “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.
Further reading is listed in the 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.
The Need for Content Operations — Deane Barker, 2016-01-27. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
How To Deal With Redundant, Out-Of-Date And Trivial Content (ROT) — Paul Boag, Smashing Magazine, 2015-06-11. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
The rise of content ops (podcast) — Scriptorium, Sarah O’Keefe with Rahel Bailie, 2022-02-07. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Docs as Code — Write the Docs, undated. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
The Discipline of Content Strategy — Kristina Halvorson, A List Apart, 2008-12-16. Checked 2026-10-23. ↩︎ ↩︎
Clean Content = Portable Content — Daniel Jacobson, Inside NPR.org, 2009-02-04. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
DITA Version 1.3 Part 0: Overview, Plus Errata 02 — OASIS Standard, 2018-06-19. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
XLIFF Version 2.1 — OASIS Standard, 2018-02-13. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
How to Build a Content Operation — Content Science Review, 2023-08-22. Checked 2026-10-23. ↩︎
Content Operations Fact Sheet — Content Science Review, 2022-01-21. Checked 2026-10-23. ↩︎ ↩︎
Content operations comes of age — tekom webinar listing (Rahel Bailie), event date not shown. Checked 2026-10-23. ↩︎
Content operations from start to scale — Scriptorium page on the open-access collection edited by Carlos Evia (Virginia Tech Publishing). Checked 2026-10-23. ↩︎ ↩︎
Content modeling: what it is and how to get started — Sanity, last edited 2023-06-26. Checked 2026-10-23. ↩︎
ANSI/NISO Z39.19-2005 (R2010) Guidelines for the Construction, Format, and Management of Monolingual Controlled Vocabularies — NISO, 2005, reaffirmed 2010. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Localization vs. Internationalization — W3C Internationalization, undated. Checked 2026-10-23. ↩︎ ↩︎
Retire content — GOV.UK publishing guidance, Government Digital Service, undated. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Content Strategy 101 — Anna Kaley, Nielsen Norman Group, 2022-11-13. Checked 2026-10-23. ↩︎ ↩︎
Manage existing GOV.UK content — GOV.UK publishing guidance, undated. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Finding things audit (1/2): what, why, how — Alan Maddrell, Inside GOV.UK blog, 2016-02-19. Checked 2026-10-23. ↩︎ ↩︎
Web Content Accessibility Guidelines (WCAG) 2.2 — W3C Recommendation, 2024-12-12. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
ISO 24495-1:2023 Plain language — Part 1: Governing principles and guidelines — AccessibleEU catalogue entry (European Commission); standard text not read. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Darwin Information Typing Architecture (DITA) Version 2.0 — OASIS DITA TC specification site (cites a working draft). Checked 2026-10-23. ↩︎
XLIFF Version 2.2. Part 1: Core — OASIS Committee Specification 01, 2025-03-13. Checked 2026-10-23. ↩︎
Vale releases — GitHub, latest v3.25.1 published 2026-10-22. Checked 2026-10-23. ↩︎ ↩︎
NIST AI 600-1: Artificial Intelligence Risk Management Framework — Generative Artificial Intelligence Profile — NIST, 2024-07-26. Checked 2026-10-23. ↩︎ ↩︎ ↩︎
Article 50: Transparency obligations for providers and deployers of certain AI systems — reproduction of Regulation (EU) 2024/1689 by the Future of Life Institute (secondary; EUR-Lex holds the official text). Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎
The AI Digital Omnibus Regulation has been published, redefining deadlines and simplifying requirements for companies and developers — Garrigues (law firm), 2026-07-24 (secondary; the Official Journal holds the official text). Checked 2026-10-23. ↩︎ ↩︎
EU AI Act Watermarking Grace Period Ends December 2026 — Cloud Security Alliance research note, 2026-09-21 (secondary analysis). Checked 2026-10-23. ↩︎ ↩︎
Google Search’s guidance about AI-generated content — Google Search Central Blog, 2023-02-08. Checked 2026-10-23. ↩︎
Vale documentation: introduction — Vale project, live docs. Checked 2026-10-23. ↩︎
Vale: MinAlertLevel — Vale project, live docs. Checked 2026-10-23. ↩︎
Vale: .vale.ini — Vale project, live docs. Checked 2026-10-23. ↩︎
Vale: Styles — Vale project, live docs. Checked 2026-10-23. ↩︎
Departments, agencies and public bodies — 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. ↩︎
Overview of editing documentation on Microsoft Learn — Microsoft Learn, updated 2024-05-08. Checked 2026-10-23. ↩︎ ↩︎
Contribute to Microsoft Learn — contributor guide — Microsoft Learn, 2023-08-30. Checked 2026-10-23. ↩︎
Fact Sheet: New Rule on the Accessibility of Web Content and Mobile Apps Provided by State and Local Governments — 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. ↩︎
European Accessibility Act — European Commission, undated. Checked 2026-10-23. ↩︎
The EAA comes into effect in June 2025. Are you ready? — AccessibleEU, 2025-01-31. Checked 2026-10-23. ↩︎
Getting to know the European legislation on accessibility (guidance on legislation, PDF) — AccessibleEU final report (European Commission), undated; says small businesses providing services are generally exempted [Article 4]. Checked 2026-10-23. ↩︎
EN 301 549 V4.1.1 published — National Disability Authority (Ireland), 2026. Checked 2026-10-23. ↩︎
What’s Your Level of Content Operations Maturity? — Colleen Jones, Content Science Review, 2020-01-29 (modified 2021-03-24). Checked 2026-10-23. ↩︎