Skip to content

Define Content Types for CMS SaaS

⏱ 25 minutes intermediate
📜Corecms

Why content type definition differs on SaaS

Section titled “Why content type definition differs on SaaS”

On CMS PaaS, content types live inside your .NET application. You define a C# class, deploy the application, and CMS discovers the type at startup. The type definition and the rendering code ship together in the same deployment.

CMS SaaS separates these concerns. Content types are defined and pushed to the cloud independently of your frontend application. Your frontend queries content through Graph and renders it however it chooses. This separation means the content model can evolve without redeploying your frontend — and your frontend can change without touching the content model.

The tradeoff: you lose the convenience of a single .NET project that contains everything. You gain a cleaner architecture where content modeling, content delivery, and content rendering are independent layers.

  1. Define a content type using the SaaS content type schema
  2. Configure properties with validation and editor hints
  3. Deploy the type to your CMS SaaS environment using the CLI
  4. Verify the type in the CMS editor and Visual Builder
AspectCMS PaaSCMS SaaS
Definition formatC# classes with attributesJSON/YAML manifest files or the management API
DeploymentBuilt into the .NET applicationPushed via CLI or API, independent of frontend
DiscoveryCMS scans assemblies at startupCMS receives type definitions from the cloud pipeline
Property types.NET types (string, XhtmlString, ContentReference)Platform-defined types (Text, RichText, ContentReference)
Visual Builder supportNot availableTypes define canvas behavior — sections, allowed components
RenderingRazor views, MVC controllersExternal frontend via Graph (React, Next.js, etc.)

Content types for CMS SaaS are defined in manifest files that describe the type’s properties, validation rules, and editor configuration.

Content type manifest
json
{
  "key": "HeroBlock",
  "displayName": "Hero Banner",
  "description": "A full-width hero section with heading, body text, image, and call-to-action",
  "baseType": "Component",
  "sortOrder": 100,
  "features": {
    "localization": {
      "enabled": true
    }
  },
  "properties": {
    "heading": {
      "type": "Text",
      "displayName": "Heading",
      "required": true,
      "sortOrder": 10,
      "editorSettings": {
        "maxLength": 120
      }
    },
    "bodyText": {
      "type": "RichText",
      "displayName": "Body Text",
      "sortOrder": 20
    },
    "backgroundImage": {
      "type": "ContentReference",
      "displayName": "Background Image",
      "allowedTypes": ["Image"],
      "sortOrder": 30
    },
    "ctaText": {
      "type": "Text",
      "displayName": "Button Text",
      "sortOrder": 40,
      "editorSettings": {
        "maxLength": 50
      }
    },
    "ctaLink": {
      "type": "Url",
      "displayName": "Button Link",
      "sortOrder": 50
    }
  }
}

Key fields:

  • key — The unique identifier for this type. Use PascalCase. This value is permanent once deployed — changing it creates a new type rather than renaming the existing one.
  • baseType — Determines how the type behaves. Page for standalone pages with URLs. Component for blocks used within Visual Builder. Media for uploadable assets.
  • properties — Each property has a platform-defined type. Common types: Text, RichText, ContentReference, Url, Boolean, Number, DateTime.
  • features.localization — When enabled, property values can differ per language.

Page types that support Visual Builder need layout section definitions. Sections define the grid structure that authors see on the canvas.

Page type with Visual Builder sections
json
{
  "key": "LandingPage",
  "displayName": "Landing Page",
  "baseType": "Page",
  "properties": {
    "metaTitle": {
      "type": "Text",
      "displayName": "Meta Title",
      "sortOrder": 10,
      "group": "SEO"
    },
    "metaDescription": {
      "type": "Text",
      "displayName": "Meta Description",
      "sortOrder": 20,
      "group": "SEO"
    }
  },
  "visualBuilder": {
    "sections": [
      {
        "key": "headerSection",
        "displayName": "Header",
        "columns": 1,
        "allowedTypes": ["HeroBlock", "NavigationBlock"]
      },
      {
        "key": "mainContent",
        "displayName": "Main Content",
        "columns": 2,
        "allowedTypes": ["TextBlock", "ImageBlock", "CardBlock", "FormBlock"]
      },
      {
        "key": "footerSection",
        "displayName": "Footer",
        "columns": 1,
        "allowedTypes": ["FooterBlock", "NewsletterSignupBlock"]
      }
    ]
  }
}

Section configuration:

  • columns — Number of columns in the grid (1 for full-width, 2 for side-by-side, etc.)
  • allowedTypes — Restricts which component types can be dropped into the section. Omit this field to allow all components.

Content types deploy through the Optimizely CLI. The CLI reads your manifest files and pushes the definitions to the cloud.

Deploy content types
bash
# Authenticate with your CMS SaaS environment
optimizely login --environment production

# Validate manifests before deployment
optimizely content-types validate ./content-types/

# Deploy content types to the target environment
optimizely content-types push ./content-types/ --environment development

# Verify deployed types
optimizely content-types list --environment development

Deployment workflow:

  1. Validate locallycontent-types validate checks your manifests for syntax errors, missing required fields, and type conflicts before anything reaches the cloud.
  2. Deploy to development — Push to your development environment first. Create test content and verify the types work in Visual Builder.
  3. Promote to staging — Once validated, push the same manifests to staging for integration testing.
  4. Promote to production — After staging verification, push to production.

After deployment:

  1. Open the CMS editor in the target environment
  2. Create a new page using your page type
  3. Verify that Visual Builder opens with the sections you defined
  4. Add components to each section and confirm that allowedTypes restrictions work
  5. Fill in property values and verify validation rules (required fields, max length)
SaaS typePaaS equivalentDescription
TextstringSingle-line or multi-line plain text
RichTextXhtmlStringHTML content with formatting toolbar
ContentReferenceContentReferenceLink to another content item
UrlUrlExternal or internal URL
BooleanboolTrue/false toggle
Numberint / doubleNumeric value
DateTimeDateTimeDate and optional time
ContentAreaContentAreaOrdered list of content references (Visual Builder sections)
IssueCauseFix
Type not visible after deploymentDeployment targeted wrong environmentRun content-types list to verify the target environment
Property missing in editorProperty key typo in manifestCompare manifest keys against the deployed type definition
Validation error on pushInvalid property type or missing required fieldRun content-types validate and fix reported errors
Visual Builder sections missingPage type lacks visualBuilder.sectionsAdd the visualBuilder configuration to the page type manifest