Template Components

Bento Card

A visually-rich feature showcase card. The Bento Card renders a tiered information block with an icon, badge, title, hero metric, feature list, and call-to-action. Ideal for plan comparisons, service tiers, product offerings, and KPI summaries.

A Bento Card (bento_card) is a self-contained presentation card designed for side-by-side tier comparisons and feature showcases. It combines four optional zones into a single cohesive block:

  1. Header - icon composite tile, badge, title, and subtitle
  2. Hero - large metric with period and description (for example, price, score, or capacity)
  3. Feature list - icon rows with optional labels and values
  4. CTA - one or two action labels

Four pre-built variants (light, standard, premium, dark) automatically adapt colors, backgrounds, and accent tones to the active theme. Every color property can be overridden from the payload at runtime.

Bento Cards are designed to sit inside a Layout Group for side-by-side column arrangements. When placed inside a Layout Group, borders and backgrounds are promoted to the parent cell so all columns share equal heights.


Variants

VariantBackgroundAccentBest for
lighttheme.headerShade (light grey tint)theme.primaryEntry-level or free tiers
standard#FFFFFF (white)theme.primaryMid-range plans, default
premiumSoft tint of theme.secondarytheme.secondaryFeatured or recommended tiers
dark#1F2937 (slate)#FBBF24 (amber)Enterprise, top-tier, highlight

The premium variant automatically computes its background by blending theme.secondary at 25% opacity onto white. For a blue primary or indigo secondary theme, this produces a soft lavender (approximately #D8D9FC). The icon tile uses theme.primary at 25% opacity to ensure hue contrast against the blended background.

The variant can be set statically on the node or driven from the data payload. See Payload-driven overrides.


Top-level Properties

PropertyTypeDefaultDescription
variant"light" | "standard" | "premium" | "dark""standard"Visual treatment. Can be overridden at runtime via _repeatItem.variant.
titlestring"BentoCard"Main card heading. Supports {{FIELDNAME}} tokens.
subtitlestringOptional secondary line rendered beneath the title in muted grey.
iconstringIcon key from the icon registry (for example, "star", "shield", "zap", "box"). Rendered as a 30×30 composite tile with background fill.
badgestringShort label rendered above the title in accent color (for example, "BEST VALUE", "POPULAR"). Supports {{FIELDNAME}} tokens.
backgroundColorcolor(variant default)Override the card background. Accepts any hex color or theme token.
textColorcolor(variant default)Override the main text color for title, period, and feature labels.
accentColorcolor(variant default)Override the accent color used for badge, hero value, feature icons, and CTA.
iconBackgroundColorcolor(variant default)Override the icon tile background fill. Accepts full hex (#RRGGBB) or 8-digit hex (#RRGGBBAA) for opacity.

Hero Section

The hero section displays a large primary metric — typically a price, score, or capacity — with optional period and description text below it.

Add it by setting the heroSection property object on the card.

PropertyTypeDefaultDescription
heroSection.valuestringThe main hero metric (for example, "$299", "{{price}}", "99.9%"). Rendered at 28pt bold in accent color. Supports {{FIELDNAME}} tokens.
heroSection.periodstringUnit or frequency label below the hero value (for example, "/ month", "per user"). Rendered at 14pt in text color.
heroSection.descriptionstringSupporting text below the period (for example, "billed annually", "includes tax"). Rendered at 11pt in muted grey.
heroSection.hasSeparatorbooleantrueWhen true, draws a hairline separator between the header and hero sections at 85% card width. Set to false to suppress the divider.

Features

The features array renders a vertical list of icon and label rows below the hero section. Each feature shows a check icon by default, with an optional custom icon, secondary value, and highlight treatment.

PropertyTypeDefaultDescription
featuresFeature[][]Array of feature objects. Can also be a {{path}} token resolving to an array at runtime.

Feature object

PropertyTypeDefaultDescription
labelstringFeature name or description. Supports {{FIELDNAME}} tokens.
valuestringOptional secondary value rendered below the label in a smaller font (for example, "Up to 50 users", "{{storageLimit}} GB").
iconstringOverride the row icon. Defaults to "check" when omitted.
colorcolor(accent color)Override the icon and value color for this row.
highlightedbooleanfalseWhen true, renders the label in accent color and bold. Useful for marking key differentiators.

Zebra striping

When there are more than 5 features and the card has a light background, alternate rows automatically receive a subtle #F8FAFC background tint. This improves scannability on long feature lists without requiring any configuration.


CTA Section

The cta object renders one or two call-to-action labels at the bottom of the card, centered, in accent color.

PropertyTypeDefaultDescription
cta.primarystringPrimary action label (for example, "Get Started", "{{ctaLabel}}").
cta.secondarystringSecondary action label separated from primary by `

Payload-driven Overrides

Every visual property — including the variant itself — can be driven entirely from the JSON data payload. This is the recommended approach for generating tier-comparison grids from a CRM or product catalogue.

When the card is used inside a _repeat context, properties are read from _repeatItem first:

  • _repeatItem.variant — sets the card variant
  • _repeatItem.features — replaces the static features array
  • _repeatItem.badge, _repeatItem.title, _repeatItem.subtitle, etc. — all standard card props can be sourced from payload

You can also pass a {{path}} binding for the features property to resolve a nested array from any path in the payload:

"features": "{{plans.professional.features}}"

Usage in a Layout Group

Bento Cards are designed to be placed as direct children of a Layout Group. The Layout Group assigns equal column widths and the cards automatically delegate their border and background to the parent cell, ensuring all cards in a row share the same height regardless of content length.

{
  "type": "layout_group",
  "props": { "columns": [{"width": "star"}, {"width": "star"}, {"width": "star"}], "columnGap": 12 },
  "children": [
    { "type": "bento_card", "props": { "variant": "light", ... } },
    { "type": "bento_card", "props": { "variant": "standard", ... } },
    { "type": "bento_card", "props": { "variant": "premium", ... } }
  ]
}

Examples

Simple Static Card

A minimal card with a title, icon, and feature list — no hero section, no data binding.

{
  "type": "bento_card",
  "props": {
    "variant": "standard",
    "title": "Starter",
    "subtitle": "For individuals and small teams",
    "icon": "zap",
    "features": [
      { "label": "5 active projects" },
      { "label": "2 GB storage" },
      { "label": "Email support" }
    ]
  }
}

Card with Hero Pricing

A standard pricing card with badge, hero price, period, and CTA.

{
  "type": "bento_card",
  "props": {
    "variant": "premium",
    "title": "Professional",
    "subtitle": "For growing teams",
    "icon": "shield",
    "badge": "MOST POPULAR",
    "heroSection": {
      "value": "$149",
      "period": "/ month",
      "description": "billed annually, per workspace",
      "hasSeparator": true
    },
    "features": [
      { "label": "Unlimited projects" },
      { "label": "50 GB storage" },
      { "label": "Priority support", "highlighted": true },
      { "label": "SSO & SCIM provisioning" },
      { "label": "Audit logs (90 days)" }
    ],
    "cta": {
      "primary": "Start Free Trial",
      "secondary": "Talk to Sales"
    }
  }
}

Full Tier Comparison Grid (Static)

A 4-column grid using all four variants, demonstrating a complete service tier comparison.

{
  "type": "layout_group",
  "props": {
    "columns": [
      {"width": "star"}, {"width": "star"}, {"width": "star"}, {"width": "star"}
    ],
    "columnGap": 10
  },
  "children": [
    {
      "type": "bento_card",
      "props": {
        "variant": "light",
        "title": "Starter",
        "subtitle": "Individuals & freelancers",
        "icon": "zap",
        "heroSection": { "value": "Free", "period": "forever" },
        "features": [
          { "label": "3 active projects" },
          { "label": "1 GB storage" },
          { "label": "Community support" }
        ],
        "cta": { "primary": "Sign Up Free" }
      }
    },
    {
      "type": "bento_card",
      "props": {
        "variant": "standard",
        "title": "Team",
        "subtitle": "Growing companies",
        "icon": "users",
        "heroSection": { "value": "$49", "period": "/ month", "description": "up to 10 seats" },
        "features": [
          { "label": "20 active projects" },
          { "label": "25 GB storage" },
          { "label": "Email & chat support" },
          { "label": "Role-based access control" }
        ],
        "cta": { "primary": "Start Trial" }
      }
    },
    {
      "type": "bento_card",
      "props": {
        "variant": "premium",
        "title": "Business",
        "subtitle": "Scaling organisations",
        "icon": "star",
        "badge": "BEST VALUE",
        "heroSection": { "value": "$149", "period": "/ month", "description": "billed annually" },
        "features": [
          { "label": "Unlimited projects" },
          { "label": "200 GB storage" },
          { "label": "Priority support", "highlighted": true },
          { "label": "SSO & SCIM" },
          { "label": "Audit logs (1 year)" },
          { "label": "Custom integrations" }
        ],
        "cta": { "primary": "Get Started", "secondary": "Schedule Demo" }
      }
    },
    {
      "type": "bento_card",
      "props": {
        "variant": "dark",
        "title": "Enterprise",
        "subtitle": "Dedicated infrastructure",
        "icon": "shield",
        "heroSection": { "value": "Custom", "period": "per agreement", "description": "volume pricing available" },
        "features": [
          { "label": "Unlimited everything" },
          { "label": "Dedicated cloud region" },
          { "label": "24/7 SLA support", "highlighted": true },
          { "label": "MSA & DPA included" },
          { "label": "On-premise option" },
          { "label": "Dedicated CSM" }
        ],
        "cta": { "primary": "Contact Sales" }
      }
    }
  ]
}

Payload-driven Cards (Repeat Context)

This is the recommended pattern when plan data lives in the payload. The template node is defined once; the renderer expands it for each item in the data array.

Template node:

{
  "type": "layout_group",
  "props": {
    "columns": [{"width": "star"}, {"width": "star"}, {"width": "star"}],
    "columnGap": 12
  },
  "_repeat": "plans",
  "children": [
    {
      "type": "bento_card",
      "props": {
        "title": "{{name}}",
        "subtitle": "{{tagline}}",
        "icon": "{{iconKey}}",
        "badge": "{{badge}}",
        "heroSection": {
          "value": "{{price}}",
          "period": "{{billingPeriod}}",
          "description": "{{pricingNote}}"
        },
        "features": "{{features}}",
        "cta": { "primary": "{{ctaPrimary}}", "secondary": "{{ctaSecondary}}" }
      }
    }
  ]
}

Example payload:

{
  "plans": [
    {
      "name": "Starter",
      "tagline": "For solo practitioners",
      "iconKey": "zap",
      "badge": null,
      "price": "Free",
      "billingPeriod": "forever",
      "pricingNote": null,
      "ctaPrimary": "Get Started",
      "ctaSecondary": null,
      "features": [
        { "label": "3 active matters" },
        { "label": "Document vault (500 MB)" },
        { "label": "Email delivery" }
      ]
    },
    {
      "name": "Professional",
      "tagline": "For boutique firms",
      "iconKey": "shield",
      "badge": "POPULAR",
      "price": "$89",
      "billingPeriod": "/ month",
      "pricingNote": "billed annually",
      "ctaPrimary": "Start Trial",
      "ctaSecondary": "Talk to Sales",
      "features": [
        { "label": "Unlimited matters" },
        { "label": "Document vault (10 GB)" },
        { "label": "Priority support", "highlighted": true },
        { "label": "E-signature included" },
        { "label": "Client portal access" }
      ]
    },
    {
      "name": "Enterprise",
      "tagline": "For large law firms",
      "iconKey": "box",
      "badge": null,
      "price": "Custom",
      "billingPeriod": "per agreement",
      "pricingNote": "volume discounts available",
      "ctaPrimary": "Contact Sales",
      "ctaSecondary": null,
      "features": [
        { "label": "Unlimited everything" },
        { "label": "Dedicated storage region", "highlighted": true },
        { "label": "On-premise deployment" },
        { "label": "MSA & DPA included" },
        { "label": "Dedicated account manager" },
        { "label": "Custom retention policies" }
      ]
    }
  ]
}

When driving the variant from the payload, add "variant": "{{tier}}" (or any field key) to the props. The renderer reads _repeatItem.variant first, falling back to the static variant prop. This lets different rows in the same repeat loop render with different visual treatments automatically.


Per-card Color Override

All four color properties can be set explicitly to override variant defaults — useful for branded one-off cards or when the theme colors do not match the intended hierarchy.

{
  "type": "bento_card",
  "props": {
    "variant": "standard",
    "title": "Regulated Markets Package",
    "subtitle": "Financial services add-on",
    "icon": "shield",
    "badge": "COMPLIANCE READY",
    "backgroundColor": "#FFF7ED",
    "textColor": "#1C1917",
    "accentColor": "#EA580C",
    "iconBackgroundColor": "#EA580C33",
    "heroSection": {
      "value": "$1,200",
      "period": "/ year per entity",
      "description": "includes annual review"
    },
    "features": [
      { "label": "SOX-aligned reporting templates", "highlighted": true },
      { "label": "Immutable audit trail (7 years)" },
      { "label": "SEC filing export" },
      { "label": "Dedicated compliance officer" }
    ],
    "cta": { "primary": "Request Proposal" }
  }
}

KPI Summary Grid

Bento Cards are not limited to pricing. Use the hero section to show any large metric (throughput, SLA scores, error rates, etc.) and the feature list to show supporting breakdowns.

{
  "type": "layout_group",
  "props": {
    "columns": [{"width": "star"}, {"width": "star"}, {"width": "star"}],
    "columnGap": 10
  },
  "children": [
    {
      "type": "bento_card",
      "props": {
        "variant": "light",
        "title": "API Gateway",
        "subtitle": "Last 30 days",
        "icon": "zap",
        "heroSection": { "value": "99.98%", "period": "uptime", "hasSeparator": true },
        "features": [
          { "label": "Avg latency", "value": "42 ms" },
          { "label": "Requests", "value": "14.2 M" },
          { "label": "Error rate", "value": "0.02%", "highlighted": true }
        ]
      }
    },
    {
      "type": "bento_card",
      "props": {
        "variant": "standard",
        "title": "Data Pipeline",
        "subtitle": "Last 30 days",
        "icon": "box",
        "heroSection": { "value": "2.4 TB", "period": "processed", "hasSeparator": true },
        "features": [
          { "label": "Jobs completed", "value": "8,410" },
          { "label": "Failed jobs", "value": "3" },
          { "label": "Avg processing time", "value": "1.8 s" }
        ]
      }
    },
    {
      "type": "bento_card",
      "props": {
        "variant": "dark",
        "title": "Security Events",
        "subtitle": "Last 30 days",
        "icon": "shield",
        "heroSection": { "value": "0", "period": "critical alerts", "hasSeparator": true },
        "features": [
          { "label": "Auth attempts blocked", "value": "127" },
          { "label": "Policy violations", "value": "4", "highlighted": true },
          { "label": "Scans completed", "value": "360" }
        ]
      }
    }
  ]
}

Color Contrast Guard

The renderer automatically checks whether the accent color is readable on the card background using a luminance-ratio formula. If the ratio falls below 1.5 (for example, a very light accent on a light background), the accent is automatically swapped for theme.textOnShade to preserve legibility. This affects the badge, hero value, feature icons, highlighted feature labels, and CTA text.

You can bypass the guard entirely by setting accentColor explicitly in the node props or payload — an explicit override is always used as-is.


Best Use Cases

Use CaseRecommended VariantNotes
Pricing or plan comparisonAll four in a gridUse premium for the featured plan, dark for enterprise
Product feature highlightslight or standardHero value for a key spec; features for capability list
Service tier proposalspremium and dark side by sideBadge on the recommended tier
KPI dashboards in reportslight / standard / dark mixHero value for the headline metric; features for breakdowns
Quote line summariesstandardHero for total price; features for line items
Compliance or certification blocksCustom color overrideAmber or orange accent for regulated or flagged status

Bento Cards produce fixed-height PDF blocks. Very long feature lists (10 or more items) will make the card tall. Consider splitting into two cards side-by-side or limiting the feature list to the 6–8 most important items for clean visual balance.

On this page