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 pageA 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.liquidEach 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.liquidYou 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.woff2You 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 valuesThe 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.jsonA 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 browserVisualizing 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
- Every theme has 7 directories: layout, templates, sections, snippets, assets, config, and locales
- Layouts are the outer shell: They wrap every page with
{{ content_for_layout }} - Templates define page structure: JSON templates list which sections appear on each page type
- Sections are customizable modules: Merchants can edit them in the theme editor
- Snippets are reusable code: Include them with
{% render 'snippet-name' %} - 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...