Skip to content

Card Fields

A card is a single-instance deck. It renders the properties of another schema as inline sub-fields and stores the collected values as a nested object on the parent. Use it to group related settings (sitemap config, auth options, integration credentials, etc.) without the deck UX of add/remove/duplicate.

The card’s shape is defined by a separate schema, referenced via schemaref. This keeps the nested structure reusable across collections and makes the parent schema easy to read.

DeckCard
CardinalityMany itemsExactly one
UIModal dialog with add/remove/duplicateInline sub-fields, no buttons
Stored asObject keyed by item IDsSingle nested object keyed by property name
Schemaschemaref defines item shapeschemaref defines the card’s shape

If you want a single named-object grouping, use a card. If you want a list of named objects, use a deck.

{
"sitemap": {
"$ref" : "https://www.totalcms.co/schemas/properties/card.json",
"field" : "card",
"label" : "Sitemap Settings",
"schemaref" : "https://www.totalcms.co/schemas/sitemap-meta.json"
}
}

The referenced schema (sitemap-meta.json here) defines the sub-fields the card will render. Its properties become the card’s properties at save time.

A card stores as a single nested object keyed by sub-property name:

{
"sitemap": {
"enabled" : true,
"frequency" : "weekly",
"priority" : 0.7
}
}

In Twig, access values with dot notation:

{% if object.sitemap.enabled %}
<priority>{{ object.sitemap.priority }}</priority>
{% endif %}

Required. URL of the schema that defines the card’s sub-fields.

{
"schemaref" : "https://www.totalcms.co/schemas/sitemap-meta.json"
}

Legacy alias: deckref is still accepted as an alias for schemaref and will continue to work indefinitely. New schemas should use schemaref.

Sub-fields are rendered using the referenced schema’s properties, required, and formgrid. A few rules apply:

  • The referenced schema’s id field is skipped — a card is a single object with no meaningful identifier of its own.
  • Sub-field default values are applied when the card has no value for that property.
  • Sub-field settings are run through the same preset pipeline as top-level fields, including named presets and type-default presets.
  • The referenced schema’s formgrid is honored for sub-field layout. Any sub-field not listed in formgrid is appended automatically.

Card values must be basic types or simple property schemas. The following are not allowed inside a card:

  • gallery, depot, folder (plurality models that don’t fit the single-value-per-child shape)
  • Other decks (cards inside decks are fine; decks inside cards are not)

Allowed property types include string, number, boolean, card (nested), color, date, email, file, image, list, password, phone, slug, svg, time, and url.

Referencing nested images and files in Twig

Section titled “Referencing nested images and files in Twig”

Images and files stored inside a card are addressed by dot-notation in the property option of the standard media/render macros:

{# URL only #}
{{ cms.media.imagePath('post-1', {w: 800}, {property: 'mycard.image'}) }}
{# Full <img> tag #}
{{ cms.render.image('post-1', {w: 800}, {property: 'mycard.image'}) }}
{# File download URL #}
{{ cms.media.download('post-1', {property: 'mycard.attachment'}) }}

The first segment is the card field’s name on the parent object; subsequent segments walk down into the card. The Image Builder dialog (opened from the admin form) emits the correct dotted-property macro automatically. See cms.media → Nested images for full reference.

A card that groups sitemap configuration into a single nested object:

Parent schema:

{
"sitemap": {
"$ref" : "https://www.totalcms.co/schemas/properties/card.json",
"field" : "card",
"label" : "Sitemap Settings",
"schemaref" : "https://www.totalcms.co/schemas/sitemap-meta.json"
}
}

Referenced schema (sitemap-meta.json):

{
"properties": {
"enabled": {
"type" : "boolean",
"field" : "checkbox",
"label" : "Include in Sitemap",
"default" : true
},
"frequency": {
"type" : "string",
"field" : "select",
"label" : "Change Frequency",
"options" : ["always", "hourly", "daily", "weekly", "monthly", "yearly", "never"],
"default" : "weekly"
},
"priority": {
"type" : "number",
"field" : "number",
"label" : "Priority",
"default" : 0.5
}
}
}

Resulting object value:

{
"sitemap": {
"enabled" : true,
"frequency" : "weekly",
"priority" : 0.7
}
}

Because a card’s shape is defined by a separate schema, the same schema can back multiple card fields on the same parent. This is the most common real-world pattern: one reusable building block, dropped in wherever it’s needed.

The classic example is an address. An order needs both a billing address and a shipping address — same shape, same fields, two distinct values. Define the address shape once, then reference it from both cards.

Address schema (address.json):

{
"properties": {
"street1": {
"type" : "string",
"field" : "input",
"label" : "Street Address"
},
"street2": {
"type" : "string",
"field" : "input",
"label" : "Apt / Suite"
},
"city": {
"type" : "string",
"field" : "input",
"label" : "City"
},
"state": {
"type" : "string",
"field" : "input",
"label" : "State / Region"
},
"zip": {
"type" : "string",
"field" : "input",
"label" : "Postal Code"
},
"country": {
"type" : "string",
"field" : "select",
"label" : "Country",
"options" : ["US", "CA", "GB", "DE", "FR"],
"default" : "US"
}
}
}

Order schema — two cards, one referenced shape:

{
"id": {
"$ref" : "https://www.totalcms.co/schemas/properties/id.json",
"field" : "input",
"label" : "Order ID"
},
"billing_address": {
"$ref" : "https://www.totalcms.co/schemas/properties/card.json",
"field" : "card",
"label" : "Billing Address",
"schemaref" : "https://example.com/schemas/address.json"
},
"shipping_address": {
"$ref" : "https://www.totalcms.co/schemas/properties/card.json",
"field" : "card",
"label" : "Shipping Address",
"schemaref" : "https://example.com/schemas/address.json"
}
}

Resulting order object:

{
"id": "ord-1042",
"billing_address": {
"street1" : "123 Main St",
"street2" : "Suite 400",
"city" : "Austin",
"state" : "TX",
"zip" : "78701",
"country" : "US"
},
"shipping_address": {
"street1" : "456 Oak Ave",
"street2" : "",
"city" : "Portland",
"state" : "OR",
"zip" : "97201",
"country" : "US"
}
}

In Twig:

<h3>Ship to</h3>
<address>
{{ order.shipping_address.street1 }}<br>
{% if order.shipping_address.street2 %}
{{ order.shipping_address.street2 }}<br>
{% endif %}
{{ order.shipping_address.city }}, {{ order.shipping_address.state }} {{ order.shipping_address.zip }}<br>
{{ order.shipping_address.country }}
</address>

The same pattern applies anywhere you’d otherwise duplicate field definitions — author bios, contact blocks, geographic coordinates, social-link sets. Define the shape once, reference it as many times as you need.

  • Grouped settings — sitemap, SEO, OpenGraph, schema.org metadata
  • Integration credentials — paired API keys and endpoints (combine with secret fields for the sensitive parts)
  • Feature toggles — a single features card with checkbox sub-fields
  • Reusable address blocks — billing/shipping/mailing addresses sharing one address schema (see Reusing a Card Schema)