Skip to main content
Lead Generation Websites, Google Maps Ranking, WhatsApp Funnels, Ecommerce, SEO, Web DesignSpeed Optimization · Conversion Optimization · Monthly Lead Systems · AI AutomationLead Generation Websites, Google Maps Ranking, WhatsApp Funnels, Ecommerce, SEO, Web Design

How I Add Custom Sections and Blocks in Shopify Without Breaking the Theme

Published: October 8, 2025
Written by Sumeet Shroff
How I Add Custom Sections and Blocks in Shopify Without Breaking the Theme

One of the biggest challenges for Shopify developers is adding custom sections and blocks without breaking the theme. I’ve seen it happen countless times — a new block is added directly to the theme files, the layout crashes, and suddenly half the homepage disappears.

Over time, I’ve developed a foolproof process for creating modular, reusable, and theme-safe custom sections that enhance flexibility without compromising stability. Here’s how I do it — step by step.


Understanding How Shopify Themes Work

Every modern Shopify theme uses a combination of:

  • Liquid for structure and logic
  • JSON templates for defining sections
  • Schema blocks for configuration in the Shopify Editor

When you modify these files incorrectly, even a missing comma or misplaced bracket can break rendering. That’s why my method follows a component-based approach similar to frameworks like Next.js — where every section is treated as an independent, reusable unit.


Step 1: Duplicate Before You Modify

Before touching anything, I duplicate the active theme. In Shopify’s admin panel:

Online Store → Themes → Actions → Duplicate

This ensures that if something breaks, I can instantly revert to the working version.

Then I create a local development environment using:

shopify theme dev

This allows real-time previewing without affecting the live store.

Rule #1: Never edit live theme files. Always use a copy or a staging branch.


Step 2: Understand Where the Section Lives

Every section in Shopify resides inside:

/sections

and is linked via JSON templates inside:

/templates

Example:

/templates/index.json → homepage layout
/templates/product.json → product page layout

If I’m adding a new hero banner, I’ll name it clearly:

/sections/custom-hero-banner.liquid

Then I’ll define it inside the homepage JSON:

{
  "sections": {
    "main": { "type": "custom-hero-banner" }
  },
  "order": ["main"]
}

Now Shopify recognizes it as an editable section — ready for customization.


Step 3: Build the Section Using Modular Liquid

I design each section as a self-contained module:

<section class="custom-hero-banner">
  <div class="max-w-6xl mx-auto px-6 py-12 text-center">
    <h1>{{ section.settings.heading }}</h1>
    <p>{{ section.settings.subheading }}</p>
    <a href="{{ section.settings.button_link }}" class="btn">{{ section.settings.button_label }}</a>
  </div>
</section>

{% schema %} { "name": "Custom Hero Banner", "settings": [ { "type": "text", "id": "heading", "label": "Heading" }, { "type": "text", "id": "subheading", "label": "Subheading" }, { "type": "url", "id": "button_link", "label": "Button Link" }, { "type": "text", "id": "button_label", "label": "Button Label" } ], "presets": [{ "name": "Custom Hero Banner" }] } {% endschema %}

This Liquid structure is clean, independent, and editor-friendly. It uses Tailwind CSS classes for rapid, responsive styling — just like my Next.js design systems.


Step 4: Use Dynamic Blocks for Flexibility

Instead of hardcoding content, I define dynamic blocks inside the schema. This gives clients full control over adding, removing, or reordering components within the section.

Example:

{% schema %}
{
  "name": "Feature Highlights",
  "settings": [],
  "blocks": [
    {
      "type": "feature",
      "name": "Feature Item",
      "settings": [
        { "type": "text", "id": "title", "label": "Feature Title" },
        { "type": "textarea", "id": "description", "label": "Feature Description" },
        { "type": "image_picker", "id": "icon", "label": "Feature Icon" }
      ]
    }
  ],
  "presets": [{ "name": "Feature Highlights" }]
}
{% endschema %}

Inside the HTML, I loop through them:

{% for block in section.blocks %}
  <div class="p-6 text-center">
    <img src="{{ block.settings.icon | img_url: '200x200' }}" alt="{{ block.settings.title }}">
    <h3>{{ block.settings.title }}</h3>
    <p>{{ block.settings.description }}</p>
  </div>
{% endfor %}

Dynamic blocks = infinite flexibility. The client can add unlimited items without any developer assistance — and the theme remains stable.


Step 5: Keep Styles Scoped and Maintainable

A common mistake is injecting CSS directly into the global stylesheet. That leads to conflicting styles and layout issues across sections.

Instead, I:

  • Use Tailwind CSS utilities directly in Liquid templates.
  • For unique styles, add inline <style> blocks scoped to the section class.
  • Maintain consistent naming conventions like .custom-section-name.

This ensures updates don’t bleed into other parts of the theme.

Example:

<style>
  .custom-hero-banner h1 {
    font-size: clamp(2rem, 4vw, 3rem);
  }
</style>

Clean, modular, and completely safe.


Step 6: Avoid Hardcoding Global Assets

Never directly reference static files or fonts from /assets using absolute paths. Instead, use Shopify’s built-in helpers:

{{ 'banner.jpg' | asset_url | img_tag }}

This keeps all assets theme-relative and prevents path issues when cloning or migrating.

If I’m reusing a JavaScript snippet, I add it via section.settings and wrap it with defer or async for performance.


Step 7: Test, Validate, and Deploy Safely

Before pushing to production, I always:

  1. Validate Liquid syntax (shopify theme check)
  2. Run accessibility checks
  3. Test all breakpoints manually
  4. Preview via shopify theme dev

Only after everything passes, I publish changes to the live store. If the theme is versioned in Git, I commit using clear messages like:

feat: added feature highlights section with dynamic blocks

Controlled deployment = zero surprises.


Bonus Tip: Use JSON Templates for Page-Level Control

Instead of creating one massive template, I use unique JSON templates for special pages like:

page.about.json
page.contact.json
page.faq.json

This lets me assign custom sections per page without duplicating code — a modular structure that’s fast, flexible, and future-proof.


Common Mistakes Developers Make (and How I Avoid Them)

MistakeResultFix
Editing core theme files directlyBroken layoutsAlways duplicate and test locally
Missing or extra commas in schemaTheme fails to loadValidate JSON schema before upload
Inline JS errorsScript crashesUse async/defer + Shopify asset helpers
No section-level scopingCSS conflictsScope everything inside .section-name
Ignoring mobile testingLayout distortionTest on multiple devices early

Clean code is happy code — and happy code never breaks a theme.


Final Thoughts: Custom Without Chaos

Adding custom sections and blocks doesn’t have to be risky. When done right, it gives brands the flexibility of a CMS and the reliability of a production-ready Shopify theme.

By combining Liquid modularity, Tailwind responsiveness, and Next.js-style component thinking, you can create stunning, editable Shopify designs that stay stable even after endless edits.

Remember — modularity isn’t just a coding style. It’s a mindset. Build every section like it’s its own app, and your Shopify theme will never break again.


Sumeet Shroff
Sumeet Shroff
Sumeet Shroff is a renowned expert in web design and development, sharing insights on modern web technologies, design trends, and digital marketing.

Comments

Leave a Comment

Loading comments...