Noma

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)

CollectionRoleNotes
pagesOne row per URL intent (home, pricing, compare)Usually repeating entries
page_sections OR blocks inside pagesHero, feature grid, logos, FAQOften group fields with repeatable on pages, or a separate collection if sections are shared across pages
ctasNamed CTAs (trial, demo, contact)Relation from sections to ctas avoids copy-paste button labels
seoOptional singleton or embedded groupTitle, 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 pages by locale + state=published for sitemap and static paths.
  • Use exclude on 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_id when 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)

CollectionRole
doc_categoriesTree or flat nav sections (Getting started, API)
docsArticles: 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_entriesShort 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

  • where filters 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)

CollectionRole
ui_stringsKeyed 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_messagesCopy tied to a flag name + audience

Field patterns

  • text — stable key (e.g. billing.upgrade.title); separate longtext for the string value.
  • enumeration or json — targeting metadata (plan tier, app section)—prefer structured fields over one big JSON blob for anything the product reads in hot paths.
  • hiddenInAPI for 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 where clauses 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; align locale with 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)

CollectionRole
releasesVersion label, date, summary, relation to items
release_itemsBullet-level changes: title, body, type (enumeration: feature, fix, breaking)
audience_segments (optional)If items differ for plan or region

Field patterns

  • date or datetime — ship date; sort lists by published_at or 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; first or 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 richtext only.

Cross-cutting practices for SaaS

  1. 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.
  2. Don’t store layout in prose — put structure in fields and repeatable groups so the API stays machine-readable.
  3. Plan ownership — marketing owns pages; docs owns docs; product owns ui_strings. Conflicting ownership is a schema smell (split collections).
  4. 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)

  1. Required fields are explicit and validated.
  2. Relations are minimal; no deep cycles without a fetch strategy.
  3. Locale and translation grouping are defined for customer-facing collections.
  4. List vs detail API usage is defined (exclude heavy fields on lists).
  5. Draft → publish workflow is testable per team.

Related:

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.