Blog
Headless CMS Content Modeling Examples for SaaS Products
March 22, 2026
SaaS products rarely have “one website.” They have marketing, docs, in-app UI, email, and changelog surfaces—often with multiple locales and different owners (growth, product, engineering). If you model content around pages only, you duplicate entities and break reuse.
Better: model entities your teams actually talk about (page, article, release, message), then compose experiences from relations and repeatable blocks.
Below are patterns you can copy. Collection names are examples; in Noma (Noma Core), each collection has a slug, fields with types like text, slug, richtext, relation, media, enumeration, group, and optional repeatable blocks—see the schema checklist for the full checklist.
Example 1: Marketing site (pages, sections, SEO)
Goal: Reusable building blocks and fast campaign iteration without new code per landing page.
Collections (suggested)
| Collection | Role | Notes |
|---|---|---|
pages | One row per URL intent (home, pricing, compare) | Usually repeating entries |
page_sections OR blocks inside pages | Hero, feature grid, logos, FAQ | Often group fields with repeatable on pages, or a separate collection if sections are shared across pages |
ctas | Named CTAs (trial, demo, contact) | Relation from sections to ctas avoids copy-paste button labels |
seo | Optional singleton or embedded group | Title, description, OG image—relation to media for share images |
Field patterns
slug— unique per locale; tie to a title field where helpful.richtext/longtext— body vs marketing blurbs; keep hero fields separate for layout control.media— hero image, social image; avoid hardcoding URLs in text.enumeration— page “type” or template key (landing,legal) if the frontend switches layout.
API usage
- List
pagesbylocale+state=publishedfor sitemap and static paths. - Use
excludeon list endpoints when you only need title + slug for navigation (see stable content APIs).
Locale
- One entry per locale per logical page, linked with
translation_group_idwhen you need parity across markets—see multilingual modeling.
Example 2: Documentation and knowledge base
Goal: Stable nav, versioned or tagged content, and searchable articles without turning the CMS into a second git repo.
Collections (suggested)
| Collection | Role |
|---|---|
doc_categories | Tree or flat nav sections (Getting started, API) |
docs | Articles: title, body, optional relation to category |
doc_versions (optional) | If docs are versioned per product release—relation from docs to doc_versions, or tag via enumeration |
changelog_entries | Short entries for “what shipped”; can feed docs and marketing |
Field patterns
slug— path segment or full path strategy (decide one and document it).richtext— body; use headings consistently so TOC generators work.relation— category, related articles (“see also”), optional media for diagrams.
API usage
wherefilters on category slug or version when the app builds sidebars.- Draft articles for internal review; published for public site—same schema, different
state.
Example 3: In-app copy and feature-flagged messaging
Goal: Product and growth change strings without redeploying the app; optional targeting by plan, locale, or flag.
Collections (suggested)
| Collection | Role |
|---|---|
ui_strings | Keyed messages: key, default text, optional enumeration for “surface” (modal, toast, settings) |
ui_string_overrides (optional) | When overrides are many-to-one per plan/locale |
feature_flag_messages | Copy tied to a flag name + audience |
Field patterns
text— stablekey(e.g.billing.upgrade.title); separatelongtextfor the string value.enumerationorjson— targeting metadata (plan tier, app section)—prefer structured fields over one big JSON blob for anything the product reads in hot paths.hiddenInAPIfor internal-only notes on a field if editors need context but the client must not receive it.
API usage
- Often bulk fetch by keys or by category; design
whereclauses or a dedicated app endpoint that wraps the CMS API. - Cache aggressively; revalidate when content webhooks fire (pattern depends on your stack).
Locale
- Either one entry per locale with the same
key, or one entry with locale-specific field strategy—Noma uses per-locale entries; alignlocalewith your i18n library.
Example 4: Release notes and product changelog
Goal: One source for in-app “What’s new,” public changelog, and optional email snippets.
Collections (suggested)
| Collection | Role |
|---|---|
releases | Version label, date, summary, relation to items |
release_items | Bullet-level changes: title, body, type (enumeration: feature, fix, breaking) |
audience_segments (optional) | If items differ for plan or region |
Field patterns
dateordatetime— ship date; sort lists bypublished_ator this date.relation— release → many items; items can relation back to docs for deep links.enumeration— severity / category for filtering (“Security,” “API”).
API usage
- Paginate
releases;firstor detail fetch for “latest release” hero on the marketing site. - RSS or JSON feeds are trivial if the model is already structured—avoid duplicating release content in
richtextonly.
Cross-cutting practices for SaaS
- Separate “global config” from “content” — use singleton collections for site-wide settings (nav, footer links) where the product allows a single row per scope; see the schema checklist for singleton semantics.
- Don’t store layout in prose — put structure in fields and repeatable groups so the API stays machine-readable.
- Plan ownership — marketing owns
pages; docs ownsdocs; product ownsui_strings. Conflicting ownership is a schema smell (split collections). - AI-assisted drafts — generation works best when fields are explicit—see How Developers Ship Faster with Headless CMS + AI.
Quick modeling checklist (before you ship)
- Required fields are explicit and validated.
- Relations are minimal; no deep cycles without a fetch strategy.
- Locale and translation grouping are defined for customer-facing collections.
- List vs detail API usage is defined (exclude heavy fields on lists).
- Draft → publish workflow is testable per team.
Related:
- Headless CMS
- Headless CMS Schema Design Checklist
- How to Model Multilingual Content Without Duplicate Entries
- How to Design Stable Content APIs for Frontend Teams
- How Developers Ship Faster with Headless CMS + AI
Implementation note (Noma)
Map these examples to collections and fields in the Noma admin; consume them via the REST content API with locale, state, sort, where, and exclude as needed. Entry linking across locales uses translation_group_id on content entries in Noma Core.