Skip to content

Schema Validation

This document covers JSON Schema validation keywords that can be used in the Extra Schema Definitions field when setting up properties in a schema.

Total CMS uses JSON Schema (Draft 2020-12) for data validation. In addition to the basic schema properties (type, field, label, etc.), you can add validation constraints to ensure data quality and consistency.

Where to add these: In the Schema admin interface, when editing a property, use the Extra Schema Definitions field to add validation keywords as JSON.

Important: Validation keywords like pattern, minLength, maxLength, minimum, maximum, etc. must be added in the Extra Schema Definitions section of a property — not in the property’s Settings. The Settings section controls display and behavior options, while Extra Schema Definitions is where all JSON Schema validation rules go.

By default, required string and array fields are automatically validated:

  • Strings: Cannot be empty ("")
  • Arrays (list, gallery, deck): Cannot be empty ([])
  • Files/Images: Validated on the frontend (must have a file uploaded)

You can override this behavior by explicitly setting minLength or minItems.

Enforce minimum and maximum string length.

{
"minLength": 3,
"maxLength": 100
}

Example - Username field:

{
"username": {
"type": "string",
"field": "text",
"label": "Username",
"minLength": 3,
"maxLength": 20
}
}

Use cases:

  • Usernames (3-20 characters)
  • Product names (minimum 5 characters)
  • Short descriptions (maximum 200 characters)
  • Passwords (minimum 8 characters)

Validate strings against a regular expression.

{
"pattern": "^[a-zA-Z0-9_-]+$"
}

Example - Slug field:

{
"slug": {
"type": "string",
"field": "text",
"label": "URL Slug",
"pattern": "^[a-z0-9-]+$"
}
}

Common patterns:

  • Alphanumeric: ^[a-zA-Z0-9]+$
  • URL-safe slug: ^[a-z0-9-]+$
  • Hex color: ^#[0-9A-Fa-f]{6}$
  • Phone (US): ^\\d{3}-\\d{3}-\\d{4}$

Use built-in format validators.

{
"format": "email"
}

Available formats:

  • email - Email address
  • uri / url - URL
  • date - Date (YYYY-MM-DD)
  • time - Time (HH:MM:SS)
  • date-time - ISO 8601 date-time
  • ipv4 / ipv6 - IP address

Example:

{
"website": {
"type": "string",
"field": "url",
"label": "Website",
"format": "uri"
}
}

Enforce minimum and maximum numeric values.

{
"minimum": 0,
"maximum": 100
}

Example - Percentage field:

{
"discount": {
"type": "number",
"field": "number",
"label": "Discount %",
"minimum": 0,
"maximum": 100
}
}

Like minimum/maximum, but excludes the boundary value.

{
"exclusiveMinimum": 0,
"exclusiveMaximum": 100
}

Example - Temperature (must be above 0, not equal to 0):

{
"temperature": {
"type": "number",
"field": "number",
"label": "Temperature (°C)",
"exclusiveMinimum": 0
}
}

Ensure number is a multiple of a specified value.

{
"multipleOf": 5
}

Example - Quantity (in packs of 5):

{
"quantity": {
"type": "integer",
"field": "number",
"label": "Quantity",
"multipleOf": 5,
"minimum": 5
}
}

Enforce minimum and maximum array length.

{
"minItems": 1,
"maxItems": 10
}

Example - Tags field:

{
"tags": {
"$ref": "https://www.totalcms.co/schemas/properties/list.json",
"label": "Tags",
"minItems": 1,
"maxItems": 5
}
}

Use cases:

  • Tags (1-5 items)
  • Gallery (minimum 3 images)
  • Options (maximum 10 choices)
  • Team members (minimum 2 members)

Ensure all items in an array are unique.

{
"uniqueItems": true
}

Example - Category tags:

{
"categories": {
"$ref": "https://www.totalcms.co/schemas/properties/list.json",
"label": "Categories",
"uniqueItems": true
}
}

Note: The list property type already has uniqueItems: true by default.

Restrict values to a specific set of allowed options.

{
"enum": ["draft", "published", "archived"]
}

Example - Status field:

{
"status": {
"type": "string",
"field": "select",
"label": "Status",
"enum": ["draft", "published", "archived"],
"options": [
{"value": "draft", "label": "Draft"},
{"value": "published", "label": "Published"},
{"value": "archived", "label": "Archived"}
]
}
}

Use cases:

  • Predefined statuses
  • Size options (S, M, L, XL)
  • Priority levels (low, medium, high)
  • Content types

You can combine multiple validation keywords for comprehensive data validation.

Example - Product SKU:

{
"sku": {
"type": "string",
"field": "text",
"label": "Product SKU",
"minLength": 8,
"maxLength": 12,
"pattern": "^[A-Z]{3}-[0-9]{4,8}$"
}
}

Example - Price field:

{
"price": {
"type": "number",
"field": "number",
"label": "Price (USD)",
"minimum": 0.01,
"maximum": 999999.99,
"multipleOf": 0.01
}
}

Example - Feature list:

{
"features": {
"$ref": "https://www.totalcms.co/schemas/properties/list.json",
"label": "Product Features",
"minItems": 3,
"maxItems": 10,
"uniqueItems": true
}
}

Ensure that a property’s value is unique across all objects in the collection.

{
"unique": true
}

Example - Email field:

{
"email": {
"$ref": "https://www.totalcms.co/schemas/properties/email.json",
"label": "Email Address",
"unique": true
}
}

Example - Username field:

{
"username": {
"type": "string",
"field": "text",
"label": "Username",
"unique": true,
"minLength": 3,
"maxLength": 20
}
}

Important requirements:

  • Must be indexed: Unique properties must be included in the schema’s index array for performance
  • Case-sensitive: Uniqueness validation is case-sensitive (e.g., “[email protected]” and “[email protected]” are considered different)
  • Empty values allowed: Multiple objects can have empty/null values for a unique field
  • Update behavior: When updating an object, you can keep the same value, but cannot change to a value used by another object

Use cases:

  • User emails (prevent duplicate registrations)
  • Usernames (ensure unique login identifiers)
  • Product SKUs (avoid inventory conflicts)
  • Slug fields (ensure unique URLs)

Error message: When a duplicate value is detected, users will see an error message like:

Email must be unique. The value '[email protected]' already exists in another object.

Schema setup example with index:

{
"id": "user",
"type": "object",
"properties": {
"id": {
"type": "string",
"label": "ID",
"field": "input"
},
"email": {
"$ref": "https://www.totalcms.co/schemas/properties/email.json",
"label": "Email",
"unique": true
},
"username": {
"type": "string",
"label": "Username",
"field": "text",
"unique": true
}
},
"required": ["id", "email", "username"],
"index": ["id", "email", "username"]
}

Note: If you mark a property as unique but don’t include it in the index, you’ll receive a helpful error message prompting you to add it to the index.

If you want to allow empty values for a required field, explicitly set:

Allow empty strings (for required fields):

{
"minLength": 0
}

Allow empty arrays (for required fields):

{
"minItems": 0
}

Example - Optional notes on a required field:

{
"notes": {
"type": "string",
"field": "textarea",
"label": "Additional Notes",
"minLength": 0,
"maxLength": 500
}
}

When validation fails, Total CMS will display clear error messages to users:

  • minLength/maxLength: “String must be at least X characters” or “String exceeds maximum length of X”
  • minimum/maximum: “Value must be at least X” or “Value must not exceed X”
  • pattern: “Value does not match required format”
  • enum: “Value must be one of: X, Y, Z”
  • minItems/maxItems: “Array must contain at least X items” or “Array exceeds maximum of X items”
  1. Be specific: Use validation to enforce your data requirements clearly
  2. Provide context: Use help text to explain validation requirements to users
  3. Balance strictness: Don’t over-validate - allow reasonable flexibility
  4. Test thoroughly: Verify validation works as expected in the admin interface
  5. Consider UX: Validation should help users, not frustrate them
{
"email": {
"$ref": "https://www.totalcms.co/schemas/properties/email.json",
"label": "Email Address",
"maxLength": 255
}
}
{
"phone": {
"$ref": "https://www.totalcms.co/schemas/properties/phone.json",
"label": "Phone Number",
"pattern": "^\\d{3}-\\d{3}-\\d{4}$"
}
}
{
"zipcode": {
"type": "string",
"field": "text",
"label": "ZIP Code",
"pattern": "^\\d{5}(-\\d{4})?$"
}
}
{
"completion": {
"type": "integer",
"field": "range",
"label": "Completion %",
"minimum": 0,
"maximum": 100
}
}
{
"gallery": {
"$ref": "https://www.totalcms.co/schemas/properties/gallery.json",
"label": "Product Images",
"minItems": 3,
"maxItems": 20
}
}
{
"username": {
"type": "string",
"field": "text",
"label": "Username",
"unique": true,
"minLength": 3,
"maxLength": 20,
"pattern": "^[a-z0-9_-]+$"
}
}
{
"email": {
"$ref": "https://www.totalcms.co/schemas/properties/email.json",
"label": "Email Address",
"unique": true,
"maxLength": 255
}
}

For complete JSON Schema documentation, see: