Orientation and Shopify Theme Ecosystem Beginner 10 min read

Key Theme Directories and How Rendering Works

Understand the Shopify theme folder structure and how Liquid templates are processed to generate your storefront pages.

Now that you understand what Liquid is, let’s explore where it lives. Every Shopify theme follows a specific folder structure, and understanding this structure is essential before you start building. In this lesson, we’ll walk through each directory and see how Shopify transforms your templates into the pages customers see.

The Shopify Theme Structure

Every Shopify theme contains these directories:

your-theme/
├── assets/
├── config/
├── layout/
├── locales/
├── sections/
├── snippets/
└── templates/

Let’s explore what each folder does and why it matters.

The layout/ Directory

The layout directory contains your theme’s master templates. Think of a layout as the outer shell that wraps every page on your store.

The most important file here is theme.liquid:

<!DOCTYPE html>
<html lang="{{ request.locale.iso_code }}">
<head>
<meta charset="utf-8">
<title>{{ page_title }} | {{ shop.name }}</title>
{{ content_for_header }}
{{ 'base.css' | asset_url | stylesheet_tag }}
</head>
<body>
<header>
{% section 'header' %}
</header>
<main>
{{ content_for_layout }}
</main>
<footer>
{% section 'footer' %}
</footer>
</body>
</html>

Two special Liquid objects appear here:

  • {{ content_for_header }}: Shopify injects essential scripts here (analytics, app scripts, etc.). Never remove this.
  • {{ content_for_layout }}: This is where page-specific content appears. When someone visits a product page, the product template’s output goes here.

You can have multiple layouts. For example, layout/checkout.liquid for the checkout page or layout/password.liquid for password-protected stores.

The templates/ Directory

Templates define the content structure for different page types. When a customer visits /products/cool-shirt, Shopify looks for a product template to render.

In modern Shopify themes (Online Store 2.0), templates are JSON files:

templates/
├── index.json # Homepage
├── product.json # Product pages
├── collection.json # Collection pages
├── cart.json # Cart page
├── page.json # Standard pages
├── blog.json # Blog listing
├── article.json # Blog posts
├── search.json # Search results
└── 404.json # Not found page

A JSON template specifies which sections appear on that page type:

{
"sections": {
"main": {
"type": "main-product",
"settings": {}
},
"recommendations": {
"type": "product-recommendations",
"settings": {
"heading": "You may also like"
}
}
},
"order": ["main", "recommendations"]
}

This approach lets merchants customize each page type through the theme editor without touching code.

The sections/ Directory

Sections are the building blocks of your theme. They’re modular, reusable components that merchants can add, remove, and rearrange.

sections/
├── header.liquid
├── footer.liquid
├── main-product.liquid
├── featured-collection.liquid
├── slideshow.liquid
└── newsletter.liquid

Each section file contains both the markup and a schema that defines its settings:

<section class="featured-collection">
<h2>{{ section.settings.heading }}</h2>
<div class="products">
{% for product in section.settings.collection.products limit: 4 %}
<div class="product-card">
<h3>{{ product.title }}</h3>
<p>{{ product.price | money }}</p>
</div>
{% endfor %}
</div>
</section>
{% schema %}
{
"name": "Featured Collection",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Featured Products"
},
{
"type": "collection",
"id": "collection",
"label": "Collection"
}
]
}
{% endschema %}

The schema defines what options appear in the theme editor for this section.

The snippets/ Directory

Snippets are reusable code fragments that you include in sections, templates, or other snippets. Unlike sections, they don’t have settings schemas and can’t be customized through the theme editor.

snippets/
├── product-card.liquid
├── price.liquid
├── icon-cart.liquid
└── social-sharing.liquid

You include snippets using the render tag:

{% render 'product-card', product: featured_product %}

Use snippets for:

  • Components used in multiple places (product cards, icons)
  • Complex logic you want to keep separate
  • Code that doesn’t need merchant customization

The assets/ Directory

This folder holds all your static files:

assets/
├── base.css
├── theme.js
├── logo.png
└── custom-font.woff2

You reference assets in your Liquid files using the asset_url filter:

{{ 'base.css' | asset_url | stylesheet_tag }}
{{ 'theme.js' | asset_url | script_tag }}
<img src="{{ 'logo.png' | asset_url }}" alt="Logo">

Shopify serves these files from their CDN for fast global delivery.

The config/ Directory

This directory contains your theme’s settings configuration:

config/
├── settings_schema.json # Defines available settings
└── settings_data.json # Stores current setting values

The settings_schema.json file defines the options merchants see in “Theme Settings”:

[
{
"name": "Colors",
"settings": [
{
"type": "color",
"id": "color_primary",
"label": "Primary color",
"default": "#000000"
}
]
}
]

You access these settings anywhere in your theme:

<button style="background-color: {{ settings.color_primary }}">
Add to Cart
</button>

The locales/ Directory

Locales contain translation strings for multi-language support:

locales/
├── en.default.json
├── es.json
└── fr.json

A locale file maps keys to translated text:

{
"products": {
"add_to_cart": "Add to cart",
"sold_out": "Sold out"
}
}

You use the t filter to output translations:

<button>{{ 'products.add_to_cart' | t }}</button>

How Rendering Works

Now let’s see how these pieces work together when a customer visits your store.

The Request Lifecycle

1. Customer visits /products/cool-shirt
2. Shopify identifies: product template needed
3. Loads product.json template
4. Resolves sections listed in template
5. Wraps everything in theme.liquid layout
6. Processes all Liquid code
7. Returns final HTML to browser

Visualizing the Nesting

Think of rendering as Russian nesting dolls:

┌─────────────────────────────────────────────┐
│ layout/theme.liquid │
│ ┌───────────────────────────────────────┐ │
│ │ {{ content_for_layout }} │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ templates/product.json │ │ │
│ │ │ ┌───────────────────────────┐ │ │ │
│ │ │ │ sections/main-product │ │ │ │
│ │ │ │ ┌─────────────────────┐ │ │ │ │
│ │ │ │ │ snippets/price │ │ │ │ │
│ │ │ │ └─────────────────────┘ │ │ │ │
│ │ │ └───────────────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

The layout wraps the template, which contains sections, which may include snippets. All Liquid code is processed on Shopify’s servers before the final HTML reaches the browser.

What Shopify Adds

Remember {{ content_for_header }}? Shopify automatically injects:

  • Analytics and tracking scripts
  • App scripts and styles
  • Preview mode functionality
  • Required Shopify JavaScript

This is why you should never remove that tag, even if your theme seems to work without it.

Putting It Together

Here’s a simplified example of how a product page comes together:

layout/theme.liquid:

<!DOCTYPE html>
<html>
<head>
{{ content_for_header }}
</head>
<body>
{% section 'header' %}
{{ content_for_layout }}
{% section 'footer' %}
</body>
</html>

templates/product.json:

{
"sections": {
"main": { "type": "main-product" }
},
"order": ["main"]
}

sections/main-product.liquid:

<div class="product">
<h1>{{ product.title }}</h1>
{% render 'price', product: product %}
<button>Add to Cart</button>
</div>

snippets/price.liquid:

<span class="price">{{ product.price | money }}</span>

When rendered, the customer sees a complete HTML page with the product information filled in.

Key Takeaways

  1. Every theme has 7 directories: layout, templates, sections, snippets, assets, config, and locales
  2. Layouts are the outer shell: They wrap every page with {{ content_for_layout }}
  3. Templates define page structure: JSON templates list which sections appear on each page type
  4. Sections are customizable modules: Merchants can edit them in the theme editor
  5. Snippets are reusable code: Include them with {% render 'snippet-name' %}
  6. Rendering happens server-side: Customers only see the final HTML, never your Liquid code

What’s Next?

Now that you understand how themes are organized and rendered, you’re ready to set up your development environment. In the next module, we’ll create a Shopify Partner account, set up a development store, and install the tools you need to start building themes locally.

Finished this lesson?

Mark it complete to track your progress.

Discussion

Loading comments...