Files
johannes.gasser 57af0b8386
Build and Deploy / build-and-deploy (push) Successful in 2m53s
add skills
2026-05-18 08:39:42 +02:00

2.1 KiB

Separation of Content and Presentation

The most important principle in structured content: separate what content IS from how it LOOKS.

The Problem

When content is tied to presentation:

  • Redesigns require content migration
  • Content can't be reused across channels (web, mobile, voice)
  • Editors make design decisions instead of content decisions
  • A/B testing requires duplicate content

The Principle

Model content based on meaning and purpose, not visual appearance.

Bad: Presentation-Focused

BigHeroText       → What if we want small heroes?
RedButton         → What if brand colors change?
ThreeColumnLayout → What if mobile needs one column?
LeftSidebar       → Position is a frontend concern
MobileImage       → Device-specific content is fragile

Good: Meaning-Focused

Headline          → The main message (render however)
CallToAction      → An action we want users to take
Features          → A list of things (columns decided by frontend)
RelatedContent    → Content relationships (position by context)
Image             → One image with responsive crops

Testing Your Model

Ask: "If we completely redesigned the site, would these field names still make sense?"

  • threeColumnFeatures Fails (what if 2 columns?)
  • features Works (describes the content's purpose: a list of product features)
  • blueHighlightBox Fails (what if we go purple?)
  • callout Works (describes the content's role: an attention-grabbing aside)

Sanity Implementation

// ❌ Avoid presentation-focused names
defineField({ name: 'bigHeroText', type: 'string' })
defineField({ name: 'fontSize', type: 'number' })
defineField({ name: 'backgroundColor', type: 'color' })

// ✅ Use meaning-focused names
defineField({ name: 'headline', type: 'string' })
defineField({ name: 'emphasis', type: 'string', options: { list: ['standard', 'prominent'] } })
defineField({ name: 'tone', type: 'string', options: { list: ['neutral', 'warning', 'success'] } })

The frontend translates tone: 'warning' to visual styles. Content stays semantic.