Skip to content

One content model, three brand sites, zero duplicate entries

A headless CMS with one structured content model feeding three separately branded publications through the same API, so an article is written once and syndicated everywhere it belongs.

Entries · all titles
One list for the whole desk · where a story runs is a tick per title, not a second entry
New entry Thu 17 Sep 2026PC
Entries · 7–13 Sep 2026412written once each
Brand placements1,104across three titles
Typed twice0one record per story
HPHarbour Post410EEExaminer376TdTidal318
How the week spreadOn all three titles300On two92On one20

Today’s entries 13 of 58 updated since 06:00

LiveScheduledEmbargoedNot carried
Type: allTitle: all threeStage: anyTopic: anySorted by last edit · entry ids are the same on every title
EntryAuthorTopicWorkflowHPEETdEdited
Saltmarsh ferry winter timetable starts on Mondayart_9FT4 · ArticlePriya CastellTransportPublished09:14
West channel dredging approved after two-year waitart_7KQ2 · ArticleMorwenna TreloarHarbourPublished08:52
Boatyard jobs: Kestle Reach to take on 40 apprenticesart_7KR8 · ArticleJonah PellowBusinessScheduled08:47
Rail strike dates confirmed for south-west routeswir_3310 · WireDesk · wireTransportPublished08:31
Twelve harbour-side breakfasts worth the early startart_7KM1 · ArticleEsme KarranFood & drinkPublished08:20
Lifeboat crew recognised for night rescue off Gull Pointart_7KJ5 · ArticleMorwenna TreloarHarbourPublished08:05
Council budget meeting — liveliv_0092 · Live blogTom RowsePoliticsPublished07:58
Quayside market to move indoors for the winterart_7KH0 · ArticleEsme KarranRetailIn review07:44
Oyster beds reopen after water-quality testsart_7KF3 · ArticleJonah PellowEnvironmentPublished07:30
Interest rates held; lenders expected to followwir_3304 · WireDesk · wireBusinessPublished07:12
A slow weekend on the estuary path, in six stopsart_7KD9 · ArticleEsme KarranOutdoorsDraft06:58
School run: new crossing on Ferry Road from Mondayart_7KC2 · ArticleTom RowseTransportPublished06:40
Harbour board: what the dredging vote means for mooringsart_7KB6 · ArticleMorwenna TreloarHarbourDraft06:22

What the engagement involved

Industry
News & Digital Publishers
Duration
10 weeks
Cooperation model
Fixed price, phased
Services
Content modelingHeadless CMS buildEditor workflow
Integrations
StripeSendGridSegmentSentry
Technologies
Next.jsTypeScriptHeadless CMSGraphQLIncremental static regenerationTailwind CSS
Team
1 Project lead1 Product designer2 Frontend engineers1 Backend engineer

Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.

Introduction

What we were brought in to do

Three separate CMS instances ran for three branded publications, so a shared story had to be retyped into each one, and updates never stayed in sync across sites.

A publisher running three branded titles from one editorial desk, each on its own CMS instance chosen at a different time by a different team. Shared wire copy and desk-written features were typed into all three. The engagement was commissioned after a correction to a factual error made it onto one title and not the other two, which was noticed externally.

Content Platform Engineering

The problem

Where the old way broke

  1. 01

    Editors maintained the same wire-service and shared-desk content three separate times, formatting drifted between sites, and a correction on one publication rarely made it to the other two.

    Content was modeled as pages, so a shared story was three unrelated pages that happened to contain the same words. Nothing linked them, which meant a correction had no mechanism to propagate and depended on an editor remembering. Formatting drifted for the same reason: three sets of markup edited independently over four years.

    We modeled content as structured, reusable entries (articles, authors, topics) delivered through one headless API to all three branded frontends, with per-brand presentation layered on top and a single copy of the content underneath.

Write once, syndicate

An article is authored once and appears wherever it belongs, with no duplicate entry.

Content is modeled as structured entries (article, author, topic) with references between them, not as pages of markup, so an article can appear on three brands without being copied three times. An author update propagates everywhere their byline appears. The model refuses presentation fields entirely, and that discipline is what makes syndication actually work instead of merely possible on paper.

What shipped
  • Structured entries with references, not pages of markup
  • One article syndicated without duplication
  • No presentation fields in the model, by design
Article · content type
Entries with references, not pages of markup · shown for art_7KQ2 “West channel dredging approved after two-year wait”
References: Author, Topic, Article Thu 17 Sep 2026PC

Twelve fields · who reads each

A title reads a field or ignores it; nothing is copied
FieldKindHPEETd
HeadlineText · 120
Short headlineText · 60
StandfirstText · 280
Bodyshared, one copyRich text
Hero imageAsset · focal point
Image captionText
AuthorReference → Author
TopicsReference → Topic[]
LocationPlace
Published atDate-time
Related entriesReference → Article[]
Correction noteText

Refused by the model

Validation on save
layoutfontSizecolourcardStylecropRatiobrandCss
No presentation fields exist on any type. Crop, type scale and card style belong to each title’s frontend.

One entry, read three ways

art_7KQ2
HPHarbour Post16:9focal point keptWest channel dredging approved after two-year waitBy Morwenna TreloarReads12 of 12
EEExaminer3:2focal point keptWest channel dredging approved after two-year waitBy Morwenna TreloarReads11 of 12
TdTidal1:1focal point keptDredging approvedBy MorwennaReads9 of 12

Author · referenced, not copied

aut_0M3
MTMorwenna TreloarHarbours & transport · one record for every bylineEdits reach every byline
Byline rule · held by the title
HPHarbour PostFull nameBy Morwenna Treloar
EEExaminerFull nameBy Morwenna Treloar
TdTidalFirst name onlyBy Morwenna
The author entry stores the name once. How it is printed is a frontend decision.
On screen

The article type's twelve fields and which title reads each: one publication reads nine and crops to a square, the body is shared instead of duplicated, presentation fields are refused, and one author record gives full-name bylines on two titles and first name only on the third.

Correction · art_9FT4
Saltmarsh ferry winter timetable starts on Monday · corrected once by Priya Castell at 09:14:02
Live on 2 of 2 carrying titlesSaved 09:14:02 Thu 17 Sep 2026PC

Body · one field, one edit

Tracked change · marked for the desk
From Monday the winter timetable applies on the Saltmarsh Quay to Gull Point crossing. The first sailing of the day now leaves Saltmarsh Quay at 06:10 06:40, with the last return at 19:20. Weekend sailings run hourly until the end of March.
Correction note · field 12This article was amended on 17 September 2026. An earlier version gave the first sailing as 06:10; it is 06:40.
Saved to the one record·No per-title copy to update·Tidal does not carry this entry

After save · per title

Incremental regeneration of affected pages
0s1s2s3s4s5s6s7s8s9s10s
Saved 09:14:02HP live +7sEE live +8s
HPThe Harbour PostCarries this entry/transport/saltmarsh-ferry-timetableLive 09:14:09
EEThe Estuary ExaminerCarries this entry/transport/saltmarsh-ferry-timetableLive 09:14:10
TdTidalNever ran this entry No page to regenerate · nothing to correct
Both carrying titles live 8 seconds after save. Before, the same fix meant a separate edit in each CMS.

Presentation layer · per title

Resolved at build
HPThe Harbour PostDaily newsType scaleSerif display · 1.333Image crop · byline16:9 · full nameFields read
EEThe Estuary ExaminerRegional & businessType scaleSlab headline · 1.25Image crop · byline3:2 · full nameFields read
TdTidalWeekend & lifestyleType scaleGeometric sans · 1.2Image crop · byline1:1 · first name onlyFields read
A title restyles without touching an entry.

Presentation on top

On screen

A ferry timetable corrected once in the body, with its correction note, live on both sites that carry it eight seconds later while the third never ran it, beside each title's own presentation layer: type scale, crop, byline rule and the fields it reads.

Per-brand styling layered over shared content, never duplicated beneath it.

Each brand is a presentation layer over the same GraphQL API: its own type scale, palette and component choices, resolved at build time and regenerated incrementally when the content behind it changes. A brand can restyle without touching content, and content can be corrected once and appear corrected on all three within seconds, with no separate edits.

What shipped
  • Three frontends over one GraphQL API
  • Per-brand styling resolved at build, regenerated incrementally
  • A correction lands on all three brands within seconds

One editor workflow

A single review and publish flow with per-brand controls, replacing three separate CMS habits.

One editorial workflow (draft, review, schedule, publish) with per-brand release controls sitting on top, so a piece can go live on one brand and stay embargoed on another without becoming two records. Editors moving between brands work the same way in each, which was most of the point: three CMS habits had been producing three sets of inconsistencies.

What shipped
  • One draft-review-schedule-publish flow for all three brands
  • Per-brand release control without splitting the record
  • Editors work identically whichever brand they're on
Workflow · every title, one flow
Draft → review → schedule → publish, identical on every title · release is set per title on the same record
Send to review Thu 17 Sep 2026PC

Today on the desk

Cards carry title pips, never duplicates
Draft9
Harbour board: what the dredging vote means for mooringsMorwenna TreloarHPEE
A slow weekend on the estuary path, in six stopsEsme KarranTd
Fish market prices ahead of the half-term rushJonah PellowHPEETd
In review4
Quayside market to move indoors for the winterEsme KarranHPEETd
Planning committee defers marina hotel decisionTom RowseHPEE
Sea-swimming clubs report a record autumnEsme KarranHPTd
Scheduled6
Boatyard jobs: Kestle Reach to take on 40 apprenticesJonah PellowHPEE
Weekend: three tide-pool walks for small legsEsme KarranTd
Bus route 14 diverted during bridge worksTom RowseHPEETd
Published38
Saltmarsh ferry winter timetable starts on MondayPriya CastellHPEE
West channel dredging approved after two-year waitMorwenna TreloarHPEETd
Lifeboat crew recognised for night rescue off Gull PointMorwenna TreloarHPEETd

Release · Boatyard jobs: Kestle Reach to take on 40 apprentices

art_7KR8 one record on every title
Shared workflow
DraftJonah Pellow · 07:12
In reviewPassed by Priya Castell · 08:40
3ScheduledPer-title times below
4PublishedPer title, when due
Same steps on every titleAn editor moving between titles works the same way in each.
Release per title
HPThe Harbour PostDaily newsScheduledThu 17 Sep · 12:00Scheduled after review
EEThe Estuary ExaminerRegional & businessEmbargoedFri 18 Sep · 00:01Business pages embargo · company statement
TdTidalWeekend & lifestyleNot carried—Not carried · weekend title
Live on one title, embargoed on another, and still one entry, one id.
On screen

One draft, review, schedule and publish board for every title, and one record released per title: scheduled on one publication, embargoed on another and not carried by the third, without becoming a second entry.

What we built together

  1. 01

    Modeled articles, authors, and topics as structured, reusable content types

    Editors validated the model against real stories before any frontend work, since a model that can't express what the desk writes is one they route around.

  2. 02

    Built a shared editor workflow with per-brand publishing controls

    One draft-review-schedule-publish flow serves all three titles, with per-brand release control so a piece can go live on one and stay embargoed on another.

  3. 03

    Delivered content through one API to three independently branded frontends

    Three frontends read one GraphQL API, with per-brand styling resolved at build and regenerated incrementally when the content behind it changes.

  4. 04

    Migrated existing content from three CMS instances into the shared model

    Migration ran as its own phase, because moving four years out of three instances is where the real work and the accumulated divergence both were.

Operational results after launch

0

Duplicate content entries

−90%

Cross-site correction time

14

Editor hours saved weekly

Duplicate content entries is structural: an article is one record, so the count is zero by construction, not by measurement. Cross-site correction time compares the same operation before and after. The fourteen hours weekly is the editorial team's own estimate of retyping removed, and is reported as their figure.

Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.

Process

Phase by phase

  1. Phase 1: Model

    Content as structure

    Modeled articles, authors, and topics as structured reusable types instead of per-site pages.

    • Content model
    • Taxonomy
  2. Phase 2: Workflow

    One way to publish

    Built a shared editorial workflow with per-brand publishing controls and review states.

    • Editorial workflow
    • Role matrix
  3. Phase 3: Deliver

    Three frontends, one API

    Delivered content through one API to three independently branded frontends.

    • Delivery API
    • Three frontends
  4. Phase 4: Migrate

    Three instances into one

    Migrated existing content out of three CMS instances into the shared model, reconciling conflicts.

    • Migrated corpus
    • Conflict log
    • Editor guide
Topics · merge
Taxonomy is shared by every title · merging moves entries and writes redirects, so no site needs an edit
Merge complete Thu 17 Sep 2026PC

Merge City life into Retail

Run by Priya Castell · 08:02
From · retiredCity life/city-life
IntoRetail/retail
Topic references rewritten on each entry Old topic page redirects on every title Frontends regenerate the pages affected
Entries moved214
Redirects created214
Manual site edits0

Redirects written

10 of 214 · one per moved entry
Old path → new pathTitlesCode
/city-life/quayside-bakery-opens-second-shop/retail/quayside-bakery-opens-second-shopHPEE301
/city-life/high-street-vacancy-rate-falls/retail/high-street-vacancy-rate-fallsHPEE301
/city-life/late-night-shopping-returns-for-december/retail/late-night-shopping-returns-for-decemberHPEETd301
/city-life/independent-bookshop-marks-fifty-years/retail/independent-bookshop-marks-fifty-yearsHPTd301
/city-life/market-traders-back-new-pitch-fees/retail/market-traders-back-new-pitch-feesEE301
/city-life/a-saturday-of-secondhand-shops/retail/a-saturday-of-secondhand-shopsTd301
/city-life/chandlery-moves-to-harbour-arcade/retail/chandlery-moves-to-harbour-arcadeHPEE301
/city-life/pop-up-food-hall-extends-lease/retail/pop-up-food-hall-extends-leaseHPEETd301
/city-life/shopfront-grants-open-to-applications/retail/shopfront-grants-open-to-applicationsHPEE301
/city-life/the-last-ironmonger-on-fore-street/retail/the-last-ironmonger-on-fore-streetHPTd301
Each title serves its own copy of the redirect map from the API.

Migration · conflict log

Three instances into one model
Taxonomy“City life”, “Town centre” and “Shops” for one subject One topic, merged into Retail
BylinesInitials on one title, full names on two Name stored once; rule held by the title
StyleThree spellings of Saltmarsh Quay One place entry, referenced
CorrectionsFree text at the foot of the body on two titles Correction note field on every article
ImagesPre-cropped copies uploaded per title One asset, focal point, crop by title
Go-live · each desk reads its own migrated content first
HPThe Harbour Post Read by its deskEEThe Estuary Examiner Read by its deskTdTidal Read by its desk
On screen

Merging City life into Retail: 214 entries moved and 214 redirects created with no site needing a manual edit, beside the migration conflict log from three CMS instances and each desk reading its own migrated content before go-live.

Ways of working

About our collaboration

  1. 01

    A cross-functional team of 4 worked on a fixed price, phased basis over 10 weeks, covering Content modeling, Headless CMS build, Editor workflow. We ran a standing mid-week checkpoint and written decisions in place of status meetings. Nothing shipped that they had not seen working first.

    Ten weeks, phased, with migration as its own phase instead of a closing step. Moving four years out of three CMS instances is where the real work sat, and where those years of undecided divergence in style, taxonomy and byline conventions finally became visible to anyone. Each brand's frontend went live only once its migrated content had been read by its own desk.

What we'd carry into the next one

Duplicate entry was a symptom; the cause was content modeled as pages instead of as things.

Editors were retyping because there was nothing to reference: pages can't be shared, only copied, and every copy is a correction waiting to be missed.

Layering brand presentation over shared content is what made a third brand cheap to add.

Presentation on top, with one copy of the content underneath, is what makes the fourth title a frontend instead of a project. That's the property the publisher was buying.

Migration surfaced years of quiet divergence between the three sites that nobody had cataloged.

The migration audit found style, taxonomy and byline conventions that had diverged without anyone deciding to. Nobody had ever had cause to compare the three.

One entry, three publications

Each title reads what it needs. A correction is made once.

Switch between the three publications to see which fields each one reads and how it presents the same record, then correct the date once and watch every title pick it up. Use the arrow keys once a tab is focused.

One entry · art_7KL4 · carried by all three titles

West channel to reopen to leisure craft next month

Fields this title reads

12 of 12

  • Headline
  • Short headline
  • Standfirst
  • Body
  • Hero image
  • Image caption
  • Author
  • Topics
  • Location
  • Published at
  • Related entries
  • Correction note

Fields a title doesn't read are simply ignored by its frontend. Crop and byline rule belong to the title, not the entry: the model holds no presentation fields.

As The Harbour Post renders itShowing original
The Harbour Postcrop 16:9

West channel to reopen to leisure craft next month

Leisure craft return to the west channel once dredging finishes.

By Morwenna Treloar · Saltmarsh Quay

The harbour master confirmed the channel will reopen to leisure craft on 2 October, once the last dredging barge has cleared the moorings.

The Harbour PostShowing original
The Estuary ExaminerShowing original
TidalShowing original

Correct the date once and watch each title pick it up. Illustrative timings (Harbour Post 4.2s, Examiner 5.6s, Tidal 6.8s), inside the “within seconds” the desk sees. Not measured.

Architecture

From a story written once to every title that carries it

Presentation sits on top of shared content instead of being duplicated underneath it, so the only place a story exists is the one entry the desk edits.

  1. 01 · Desk
    One editorial workflowDraft, review, schedule, publish for every title, with per-brand release control that never splits the record in two.
  2. 02 · Model
    Article, author, topic entriesStructured entries with references between them. The model refuses presentation fields, so nothing ties an entry to one title.
  3. 03 · API
    One GraphQL APIAll three frontends read the same entries. An article on three titles is one record, so duplicate entries are zero by construction.
  4. 04 · Build
    Incremental regenerationPer-brand styling resolved at build; pages regenerate incrementally when the content behind them changes, so a correction lands within seconds.
  5. 05 · Titles
    Three branded frontendsEach title owns its type scale, palette and components. A brand restyles without touching content, and a new title is a frontend, not a project.

Same facts on every title

Corrections, embargoes & a migration read before go-live

A correction has one place to go

A shared story is one entry, not three pages that happen to hold the same words. The fix is made once and every title carrying the entry regenerates from it, so nothing depends on an editor remembering the other two.

Embargo without a second copy

Release is set per title on the same record, so a piece can go live on one publication and stay embargoed on another. Holding it back never means duplicating it, so there's no copy to drift.

Nothing live that its desk hasn't read

Migration ran as its own phase and surfaced years of diverged style, taxonomy and byline conventions. Each title's frontend went live only once its migrated content had been read by that title's own desk.

Running several titles from one desk, and still correcting the same story more than once? Scope your build in 3 minutes.

Scope your build
Have a project?

Let's talk

Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.