Skip to content

Compose a feature-card grid

Use a container with display.layout set to grid, then put canonical card blocks in its children. This is a static composition: the grid owns placement while each card owns its title, description, and optional footer copy.

Copy this complete tree and adapt the IDs and card copy. display.columns: 3 is the grid mechanism, display.gap: 24 sets the spacing, and display.full_width: true is required to emit w-full.

{
"blocks": [
{
"id": "feature-grid",
"type": "container",
"display": {
"layout": "grid",
"columns": 3,
"gap": 24,
"full_width": true
},
"style": {
"class": "px-6 py-12"
},
"blocks": [
{
"id": "feature-model",
"type": "card",
"content": {
"title": "Model your work",
"description": "Describe the records and fields your team needs.",
"footer": "Data model"
}
},
{
"id": "feature-page",
"type": "card",
"content": {
"title": "Compose pages",
"description": "Arrange reusable blocks into clear customer flows.",
"footer": "Page builder"
}
},
{
"id": "feature-publish",
"type": "card",
"content": {
"title": "Publish confidently",
"description": "Ship a consistent experience with governed access.",
"footer": "Delivery"
}
}
]
}
]
}

Pick one column mechanism. display.columns emits an inline grid-template-columns, so it wins over any md:grid-cols-N in style.class; a container uses one mechanism, not both. Use display.columns for this static, deterministic grid and reserve style.class for non-competing utilities such as padding, margins, or typography.

The gap mapping divides numeric pixels by four: gap: 24 becomes gap-6. Named values map as xs to 1, sm to 2, md to 4, lg to 6, xl to 8, and 2xl to 12. display.full_width: true is required for w-full; it is intentionally not the default.

Keep this same grid-and-card composition and replace each card’s title, description, and footer with tier name, price, and billing or action copy. Do not use the table block for pricing: TableBlock.svelte:10-11,30-35 renders display.rows placeholder rows whose every cell is the literal {header} {row}, so it cannot represent authored plan features. A Markdown table is also unsuitable because it renders as preformatted text.

Use one accordion block instead of a grid when the visitor needs expandable answers. Its content.items is an array of {title, content} objects, and display.type is either single or multiple. Item content is plain text: it does not render Markdown.

{
"blocks": [
{
"id": "pricing-faq",
"type": "accordion",
"content": {
"items": [
{
"title": "Can I change plans later?",
"content": "Yes. Choose the plan that fits today and update it when your needs change."
},
{
"title": "Is onboarding included?",
"content": "Every plan includes guided setup and product documentation."
}
]
},
"display": {
"type": "single"
}
}
]
}