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.
How It Differs From a Deck
Section titled “How It Differs From a Deck”| Deck | Card | |
|---|---|---|
| Cardinality | Many items | Exactly one |
| UI | Modal dialog with add/remove/duplicate | Inline sub-fields, no buttons |
| Stored as | Object keyed by item IDs | Single nested object keyed by property name |
| Schema | schemaref defines item shape | schemaref 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.
Basic Usage
Section titled “Basic Usage”{ "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.
Storage Format
Section titled “Storage Format”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 %}Settings
Section titled “Settings”schemaref
Section titled “schemaref”Required. URL of the schema that defines the card’s sub-fields.
{ "schemaref" : "https://www.totalcms.co/schemas/sitemap-meta.json"}Legacy alias:
deckrefis still accepted as an alias forschemarefand will continue to work indefinitely. New schemas should useschemaref.
Sub-Field Behavior
Section titled “Sub-Field Behavior”Sub-fields are rendered using the referenced schema’s properties, required, and formgrid. A few rules apply:
- The referenced schema’s
idfield is skipped — a card is a single object with no meaningful identifier of its own. - Sub-field
defaultvalues are applied when the card has no value for that property. - Sub-field
settingsare run through the same preset pipeline as top-level fields, including named presets and type-default presets. - The referenced schema’s
formgridis honored for sub-field layout. Any sub-field not listed informgridis appended automatically.
Property Restrictions
Section titled “Property Restrictions”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.
Complete Example
Section titled “Complete Example”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 }}Reusing a Card Schema
Section titled “Reusing a Card Schema”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.
Common Use Cases
Section titled “Common Use Cases”- Grouped settings — sitemap, SEO, OpenGraph, schema.org metadata
- Integration credentials — paired API keys and endpoints (combine with
secretfields for the sensitive parts) - Feature toggles — a single
featurescard with checkbox sub-fields - Reusable address blocks — billing/shipping/mailing addresses sharing one
addressschema (see Reusing a Card Schema)