Skip to main content
MDCMS uses a code-first schema system. You define content types in mdcms.config.ts using TypeScript and Zod, then sync the schema to your server. The schema drives Studio form generation, content validation, and API behavior automatically — there is no manual schema editor in Studio.

Basic syntax

Use defineType() to create a content type and defineConfig() to register it:
mdcms.config.ts

Type options

Each type accepts the following options:

Field types

Every Zod type maps to a specific Studio form control. MDCMS serializes each field into a schema registry snapshot that drives both server-side validation and client-side rendering.

Primitives

Complex types

Modifiers

Modifiers control whether fields are required, nullable, or have defaults. They affect both the schema registry snapshot and Studio form behavior.
A field with .default() is implicitly optional in the schema registry. The default value is stored in the registry snapshot and applied during validation.

Validation

Zod check methods are serialized into the schema registry as checks entries. They run both server-side (on write) and in Studio (on form input).

Common validators

Available checks by type

| Method | Description | |---|---| | .min(n) | Minimum length | | .max(n) | Maximum length | | .email() | Valid email format | | .url() | Valid URL format | | .regex(pattern) | Matches regular expression (pattern and flags are serialized) |
| Method | Description | |---|---| | .min(n) | Minimum value | | .max(n) | Maximum value | | .int() | Must be an integer |
| Method | Description | |---|---| | .min(n) | Minimum array length | | .max(n) | Maximum array length |
Custom Zod validators (.refine(), .transform(), .pipe()) cannot be serialized to the schema registry and will cause a sync error. Use only built-in Zod checks.

Registering types

Add your types to the types array in defineConfig():
mdcms.config.ts
Then sync the schema to your server:
This serializes every type into a registry snapshot, computes a schema hash, and uploads it to the server. The server stores the resolved schema and uses it for all subsequent content validation.

Schema hash

Every write operation to the MDCMS API requires an x-mdcms-schema-hash header that matches the currently synced schema. This prevents writes against a stale schema.
  • The CLI and SDK handle the schema hash automatically.
  • If the hash doesn’t match, the server returns a SCHEMA_HASH_MISMATCH error.
  • Re-run mdcms schema sync to update after config changes.
In CI/CD pipelines, always run mdcms schema sync before mdcms push to ensure the schema hash is current.

Environment overlays

Environment overlays let you customize the schema per environment without duplicating type definitions. Define them in the environments config:
mdcms.config.ts

Overlay operations

Field-level environment targeting

For simpler cases, you can use the .env() modifier directly on field definitions to target specific environments:
Fields with .env() are only included in the specified environments. This is syntactic sugar that gets expanded into add overlays during config parsing.
You cannot use .env() on fields inside overlay add/modify maps. Keep environment targeting on the base type only.

Complete example

A full configuration with multiple types, localization, validation, references, and environment overlays:
mdcms.config.ts
Changing type names or removing types that have existing content requires a migration. Use mdcms migrate to handle these changes safely.