Skip to content

Deep dive · 5 min read

Merchant-editable coffee pages with Shopify metafields

How purchasable variants stay in Shopify while origin, process, roast, tasting notes, and brewing guidance live in reusable, metafield-driven product sections.

  • Metafields
  • Product modeling

Picture a customer comparing two single-origin coffees. They are not weighing the price. They are reading the origin, the process, the elevation, the roast profile, and the tasting notes, and deciding which cup they want to wake up to. A general-purpose commerce theme has no concept of those specialty-coffee attributes. It provides the core commerce primitives, but the coffee-specific fields still have to be designed and connected to the product.

That gap is the whole problem this part of the Boxwood build had to solve. Specialty coffee is an information product as much as a physical one, and the storefront needed to carry that information in a way the merchandising team could edit for every new release, without a theme-code change each time.

This deep dive expands the Boxwood Coffee case. Here is how the data was modeled.

Two kinds of information

The first decision was to stop treating "product information" as one thing. On a coffee product there are really two kinds, and one question separates them: does this information change the cart, or does it inform the decision?

Purchasable choices

Grind and weight. These change what goes in the cart, the price, and the inventory count.

Descriptive attributes

Origin, region, elevation, variety, process, roast profile, tasting notes, brewing guidance. These do not change the cart. They inform the decision to buy.

Treating descriptive attributes as variants would create unnecessary option combinations, complicate inventory and pricing logic, and present informational details as purchasable choices. Hardcoding them into the theme layout traps the content in code and puts a developer in the path of every new coffee. So the two kinds were kept apart, each in the tool built for it.

Variants stay variants, attributes become metafields

Grind and weight stayed as native Shopify variant options. That is exactly what they are, and the native product form, cart, and checkout already handle them reliably. I styled the variant selectors to match the brand and left the behavior alone.

The descriptive attributes were stored as product metafields, so they live with the product in Shopify rather than inside the theme layout. They were grouped into four reusable product-page sections.

Coffee data

Reads: origin, region, elevation, variety, process, roast profile

Renders: a structured specification grid

Tasting note

Reads: tasting note

Renders: a prominent tasting line

Origin story

Reads: story image and story text

Renders: an image and short product narrative

Product information

Reads: brewing guidance, roast and shipping details, storage, and subscription information

Renders: collapsible practical guidance

The card badge on collection pages was extended the same way, reading a short label and a tasting line from the product so the coffee vocabulary shows up before the customer even opens the page.

Sections that read the data, not hold it

Each of the four sections follows the same three rules, and those rules are what make the model reusable.

01 · Read from the product

The section pulls the metafield off the current product and renders it; the content is not typed into the section. That is what lets one section serve every coffee in the catalog.

02 · Fall back gracefully

Each field checks the product metafield first, then a section setting, so a product that has not been filled in yet still looks right in the theme editor and never renders an empty label.

Simplified Liquid pattern. Field names and control flow are simplified for readability.

{%- liquid
  assign brewing = product.metafields.custom.brewing_recommendations.value
  assign brewing_title = product.metafields.custom.brewing_title.value
    | default: section.settings.brewing_title
-%}
{%- if brewing != blank -%}
  {% render 'accordion', title: brewing_title, content: brewing %}
{%- endif -%}

03 · Render only when data exists

If a coffee has no origin story, the story section renders nothing at all, rather than an empty box. The specification grid checks whether any of its fields have a value before it draws a single row. A product page only shows the parts that have real data behind them.

One more detail worth naming: the collapsible section reuses the theme's own accordion component rather than reinventing it. The custom code supplies the data and the structure; the proven native UI does the opening and closing.

One template is not enough

Not every product is a bag of coffee. A subscription product and a pre-order need a different page than a single-origin lot. Rather than accumulate product-type conditionals inside one increasingly complex template, the store uses separate product templates, assigned per product in the admin.

  • Coffee product → full coffee data sections
  • Subscription product → leaner subscription layout
  • Pre-order product → dedicated pre-order layout

Assigning a template is a dropdown in the product admin, so the merchandising team controls which layout a product gets without a code change. The descriptive sections are assigned only to the relevant product templates, preventing them from rendering on unrelated product types.

What the merchant actually gets

The payoff is a workflow, not a feature. To launch a new seasonal coffee, the Boxwood team:

  1. creates the product
  2. adds grind and weight variants
  3. fills in the coffee metafields (origin, process, roast, tasting notes, brewing, and so on)
  4. assigns the appropriate template and collection
  5. publishes

That is the routine launch path. When the new release fits the existing sections and metafields, no theme-code change is required. A limited release and a year-round blend use the exact same sections and render correctly on their own data. Fields that are left empty simply do not appear. Routine seasonal releases became a content workflow rather than a recurring engineering change.

Where the line is

This model is honest about its limits, and I would rather state them than oversell.

Adding a brand-new kind of attribute, say an "altitude range" field that has never existed before, is not self-serve. It means adding a field to a section and defining the metafield, which is developer work. Day-to-day content and new coffee releases that fit the existing model are self-serve. Changing the shape of the model is deliberate and reviewed.

Content is merchant-owned. Changes to the field structure itself remain engineering work.

Takeaway

Split product information by asking one question: does it change the cart, or does it inform the decision? Purchasable choices belong in variants. Descriptive attributes belong in metafields, close to the product, rendered by reusable sections that read the data and hide when it is absent.

Do that, and the theme stops being where content lives and goes back to being what it should be: the thing that renders the content. For a specialty brand launching coffees throughout the year, that difference separates a routine product-data workflow from a recurring theme change.

Back to the caseBoxwood Coffee

Need a Shopify build that knows when custom code is worth it?

I adapt, extend, and build around real catalog, content, and platform constraints, while keeping purchase-critical systems reliable and maintainable.

Start a conversation