Shopify App Blocks vs Theme Sections: A Developer Guide From Real Projects
App blocks and theme sections solve different problems on Online Store 2.0. We break down when to build each, how they interact in JSON templates, and mistakes we see on client stores.
Share with Shopify developers — useful guides spread faster in theme dev communities.
The Slack thread always starts the same way: marketing wants reviews on the product page, a developer proposes a custom section, and someone mentions Judge.me is already installed. That fork — theme section you own in Git versus app block the merchant updates independently — is where most OS 2.0 rebuilds waste budget.
The confusion usually starts in a Slack thread: a PM wants a reviews carousel on the product page, a developer proposes a custom section, and someone else mentions the merchant already installed Judge.me or Yotpo. That is the fork—theme section you control in Git, or app block the merchant installs and updates independently. Both render inside the storefront, both appear in the theme editor, but they have different deployment models, schema contracts, and support burdens. The decision tree below reflects dozens of client builds — not Shopify docs rewritten generically. When you ship theme-owned sections, run the client handoff checklist so merchants understand what they can edit versus what apps own.
What theme sections actually are
A theme section is a Liquid file in your theme's sections/ folder with markup, optional {% stylesheet %} tags, and a {% schema %} JSON block at the bottom. Merchants add sections to JSON templates—index.json, product.json, collection.json—and edit settings in the sidebar. You deploy sections through theme Git, ZIP upload, or Shopify CLI. When we build a hero, FAQ, or featured collection module for a client, it is almost always a theme section because the agency owns the code, the merchant owns the content, and there is no third-party runtime dependency. Sections can define their own blocks (repeatable rows), presets (so they appear in Add section), and limits like max_blocks. If you are new to section anatomy, read Section Schema Explained and keep our Liquid cheat sheet open while you work.
Minimal theme section example
{% comment %} sections/promo-banner.liquid {% endcomment %}
{% schema %}
{
"name": "Promo banner",
"settings": [
{ "type": "text", "id": "heading", "label": "Heading", "default": "Free shipping over $50" },
{ "type": "richtext", "id": "body", "label": "Body" }
],
"presets": [{ "name": "Promo banner" }]
}
{% endschema %}
This is deliberately boring on purpose. Production sections grow—color_scheme pickers, padding ranges, image pickers—but the contract is the same: schema defines merchant-editable fields, Liquid reads section.settings, presets make the section discoverable. We have seen client themes with fifty custom sections and zero presets; merchants call the agency for every homepage tweak. Always ship presets with realistic defaults.
What app blocks are and where they live
App blocks are storefront UI extensions shipped by Shopify apps. The app registers a block type; your theme section (or core theme section like main-product) must explicitly allow @app blocks in schema. The app renders its Liquid or remote UI into that slot. Updates to the block logic ship through the app, not your theme deploy. That is powerful for reviews, subscriptions, bundling, and loyalty—features that need app backend APIs and merchant billing. It is painful when you need pixel-perfect layout control and the app's markup does not match the design system. We treat app blocks as integration points, not layout primitives.
Opening a section to app blocks
{% schema %}
{
"name": "Product details",
"blocks": [
{ "type": "@app" }
],
"settings": [
{ "type": "checkbox", "id": "show_vendor", "label": "Show vendor", "default": true }
]
}
{% endschema %}
The blocks array with type @app is the entire handshake. Without it, installed apps cannot inject UI into that section. Dawn's main-product section allows @app blocks on the product template—that is why merchants can drop review stars below the title without editing code. When we build custom product sections for Prestige or bespoke themes, we copy that pattern: reserve a column or stack for @app blocks, document it for the client, and test with at least two installed apps before launch.
Decision matrix we use on client projects
Ask four questions before writing code. First: does this feature need server-side app data or OAuth scopes only an app can hold? If yes, app block or app embed—not a theme section pretending to call private APIs. Second: does the merchant need to update logic without redeploying the theme? Subscription widgets and dynamic discounts usually yes. Third: is layout fidelity contractual—brand guidelines, Figma pixel specs, animation timing? Theme sections win. Fourth: will this exist on every store you maintain or only stores running a specific app? Universal layout belongs in sections; app-specific capability belongs in app blocks. We write this matrix in the project README so future developers do not "just add another section" and duplicate an app the client already pays for.
- Theme section — hero banners, lookbooks, brand storytelling, custom product grids, FAQ accordions, anything in Figma that must match CSS exactly
- App block — reviews, referrals, post-purchase upsells, complex bundles, loyalty points, anything with app admin configuration and API polling
- Hybrid — custom section wrapper with @app slot; you control spacing and typography, app supplies functional widget
- Neither — checkout UI (Shopify Plus checkout extensibility), admin-only features, or headless storefronts outside Liquid entirely
JSON templates tie both together
Online Store 2.0 JSON templates list section instances and their order. Each entry has a type (filename), settings object, and optional blocks array. App blocks added by merchants persist in that JSON—theme Git pulls show block entries with app-owned types. When we merge a client's theme update, we diff templates/*.json carefully: a merchant-added Yotpo block is easy to wipe with a bad merge. Teach clients which changes live in the editor versus code deploys. For section workflow from HTML to deploy, see HTML to Shopify Liquid and use the converter for section scaffolding.
{
"sections": {
"main": {
"type": "main-product",
"blocks": {
"title": { "type": "title", "settings": {} },
"price": { "type": "price", "settings": {} },
"reviews_app": {
"type": "shopify://apps/judge-me/blocks/reviews/abc123",
"settings": {}
}
},
"block_order": ["title", "price", "reviews_app"],
"settings": {}
}
},
"order": ["main"]
}
Merchant experience differences
Merchants experience theme sections and app blocks similarly in the editor—drag, configure, preview—but the mental model differs. Theme section settings use labels you wrote; app blocks use labels from the app developer, sometimes verbose or branded. A client once had seven apps on the product page and the sidebar scroll felt endless. We grouped custom sections with clear headers in schema and moved optional apps lower in block_order. For theme-owned sections, invest in merchant-friendly schema: short labels, sensible defaults, header settings to group fields. Our merchant-friendly schema patterns article covers what we learned from 120+ sections.
Editor clutter is a real cost
Every block type you add—native or @app—increases cognitive load. Agencies love building granular blocks; merchants want "change the headline" not "which of fourteen blocks is the headline block." We consolidate when possible: one richtext field instead of five text blocks for simple content. App blocks you cannot consolidate, but you can document a recommended install order and hide redundant custom sections that duplicate app features.
CSS, JavaScript, and performance
Theme sections should scope CSS with #shopify-section-{{ section.id }} or {% stylesheet %} tags so rules do not leak. App blocks load app assets—you inherit their weight. On performance audits we routinely find three review apps left over from migrations, each injecting scripts on product pages. Sections you optimize; app blocks you audit. Before launch we run Lighthouse on product, collection, and homepage with the client's real app stack, not a clean dev store. Our performance checklist includes an app inventory step for exactly this reason.
If an app block duplicates a custom section already in the theme, delete the section. Merchants will enable both and blame the theme for slow load times.
Common mistakes we still fix on client stores
- Building a custom reviews section when the client pays for Judge.me—duplicated markup, broken star schema, and support tickets when ratings do not sync
- Forgetting @app in blocks array, then filing support tickets with apps that "do not work on our theme"
- Hardcoding app block types in JSON templates—those URLs are store-specific; let merchants place blocks in the editor
- Mixing app embeds (theme-wide scripts) with blocks on the same feature—double renders and console errors
- Shipping sections without presets so developers add instances only via JSON—merchants never discover the section
Hybrid pattern: wrapper section with app slot
Our preferred compromise for product pages: a custom section controlling grid, typography, and media gallery, with a dedicated stack region for @app blocks beneath the buy box. Liquid loops native blocks for title, price, variant picker, then yields to app blocks in block_order. Merchants reorder within constraints; design stays on-brand. Study Dawn's main-product.liquid in the reference theme—it is the syllabus for OS 2.0 product architecture.
{%- for block in section.blocks -%}
{%- case block.type -%}
{%- when '@app' -%}
{% render block %}
{%- when 'buy_buttons' -%}
{% render 'buy-buttons', block: block, product: product %}
{%- endcase -%}
{%- endfor -%}
When we choose theme-only (no apps)
Some clients ban apps—enterprise security review, performance budgets, or horror stories from broken installs. We build theme sections with metafields and Shopify Functions where possible, accepting that merchants lose slick app UIs. Collection filters might use Search & Discovery; gift messages might be line item properties; FAQs are always theme sections. Know the platform ceiling: you cannot rebuild Recharge in Liquid alone. Scope honestly in proposals.
Documentation we hand to clients
Every handoff includes a one-page map: which sections are theme-owned, which features require which apps, which templates host @app slots, and who to contact when an app updates break layout. Screenshots of the editor with arrows beat paragraphs. Link to Schema Guide for internal dev onboarding. This reduces "the reviews moved after update" panic—usually a block_order change after an app auto-migrated.
Testing checklist before sign-off
- Install top three apps client uses; verify blocks render in custom sections
- Remove all apps; verify theme sections still function
- Mobile preview: app blocks often break grid at 375px
- Theme editor: block highlight (shopify_attributes) present on custom blocks
- Git diff templates after merchant training session—capture real edits
- Compare Lighthouse with apps on versus off
Versioning theme sections alongside app updates
App vendors ship breaking UI changes without your deploy calendar. Theme sections you own should use semantic class names and minimal coupling to app internals—style the wrapper, not the app's inner div ids. When Judge.me or Okendo redesigns their block, your spacing should survive. We snapshot visual regression screenshots on product pages after every major app update in client maintenance retainers. Theme sections get semver-style filenames only when schema is breaking; app blocks get vendor changelogs. Keeping a shared Liquid reference for the team reduces one-off hacks that break when apps update.
Security and data boundaries
Theme sections cannot access admin APIs or protected customer data beyond what Liquid exposes on the storefront. App blocks exist precisely when you need authenticated app proxies, subscription contracts, or third-party inventory. Do not attempt to embed API keys in section settings—merchants can read schema defaults. If a feature requires secret keys, it belongs in an app or Shopify Function, not a theme section pretending to be an integration. We have audited client themes that exposed private metafield namespaces in HTML comments—remove debug output before production.
FAQ
Can a theme section include app blocks?
Yes—declare { "type": "@app" } in the section schema blocks array. Merchants add app blocks from installed apps inside that section. Your Liquid must iterate section.blocks and render @app types via {% render block %}.
Should I build a custom section or an app block for reviews?
Use the app's block unless you have a rare no-app requirement. Reviews need backend storage, moderation, and sync—rebuilding that in a theme section creates permanent agency liability.
Next steps
Solidify section fundamentals with Sections for Beginners, How Shopify Sections Work, and Liquid for Beginners. When you build theme-owned layout, start from HTML to Liquid and validate schema in Schema Generator. App blocks are not your enemy—they are integration slots. Design sections that welcome them where appropriate and stay out of the way everywhere else.
Frequently asked questions
Can a theme section include app blocks?
Yes. Sections declare supported app block types in their schema via blocks with type @app. Merchants then add app blocks inside that section in the theme editor—common on product pages and the homepage.
Should I build a custom section or an app block for a reviews widget?
If the feature needs app backend data, merchant install flow, and updates across stores, build an app block. If it is static layout tied to one theme, a theme section is simpler and avoids app overhead.
Do app blocks work on vintage themes?
No. App blocks require Online Store 2.0 JSON templates and section schema that accepts @app block types. Vintage Liquid templates cannot host app blocks in the theme editor.
Who owns the CSS when an app block renders inside my section?
Both. Your section provides layout and spacing; the app ships its own assets. Scope section CSS tightly and test for style collisions—especially on product templates where multiple apps inject blocks.
Can merchants reorder app blocks like theme blocks?
Yes, when your section schema allows @app blocks and the template uses JSON. Merchants drag app blocks within the section in the editor, same as native blocks—if you exposed the slot correctly.
Topic cluster
Shopify Sections
OS 2.0 sections, JSON templates, and section architecture.
Convert HTML to Shopify Liquid
Paste HTML & generate Liquid with schema, blocks, and scoped CSS. No signup required.
Share
Share this guide
Found this guide useful? Share it with other Shopify developers on LinkedIn, X, or Reddit.
Authors
About the authors
Practical Shopify section workflows from the developers who build and maintain this tool.

Dhruv Goyani
3 years web design + 3 years Shopify development experience
Dhruv combines web design and Shopify theme development — converting Figma and static HTML into merchant-editable OS 2.0 sections for client stores. He focuses on schema structure, section presets, and clean handoffs between design and Liquid.
Follow Dhruv on LinkedIn
Nishad Kikani
2 years web design + 6 years Shopify development experience
Nishad has six years of Shopify theme engineering — Dawn migrations, JSON templates, performance tuning, and complex block-based sections. He leads client delivery, code review, and the production standards behind every export from HTML to Liquid Converter.
Follow Nishad on LinkedInRelated articles from our team
Editorial review
Reviewed by the HTML to Liquid Converter team


Content is reviewed by the HTML to Liquid Converter Shopify development team before publication. Technical accuracy is validated against current Shopify Online Store 2.0 conventions and active client theme work.
Last updated:
Questions or corrections? Contact us.