Environment Setup and Tooling Beginner 10 min read

Building a Minimal Shopify Theme from Scratch

Create a barebones Shopify theme with only the essential files. Perfect as a sandbox for learning Liquid and following along with tutorials.

When learning Liquid, a full theme like Dawn can feel overwhelming. Thousands of lines of code, complex sections, and features you don’t need yet. What if you could start with just the essentials?

In this tutorial, we’ll build a minimal Shopify theme from scratch: a clean sandbox where you can experiment with Liquid code without any distractions.

Why Build from Scratch?

Dawn is excellent, but it has:

  • ~50+ files across multiple directories
  • Complex sections with many settings
  • CSS and JavaScript that can obscure what’s happening
  • Features you don’t need when learning basics

Our minimal theme will have:

  • ~5 files total
  • No CSS (we’re focusing on Liquid, not styling)
  • Clear, readable code you can understand completely
  • A foundation you can build on as you learn

Think of it as your Liquid laboratory.

What We’re Building

By the end of this tutorial, you’ll have a working theme with:

  • A basic layout that wraps all pages
  • A functional homepage
  • Proper Shopify integration (so it actually works!)

Let’s get started.

Required Theme Files

Shopify needs certain files to recognize a valid theme. Here’s the absolute minimum:

my-sandbox-theme/
├── config/
│ └── settings_schema.json
├── layout/
│ └── theme.liquid
├── sections/
│ └── main-content.liquid
└── templates/
└── index.json

That’s it. Just 4 files. Let’s create each one.

Step 1: The Layout File

The layout file is the master template. Every page on your store is wrapped by this file.

Create layout/theme.liquid:

<!DOCTYPE html>
<html lang="{{ request.locale.iso_code }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ page_title }} - {{ shop.name }}</title>
{{ content_for_header }}
</head>
<body>
<header>
<h1>{{ shop.name }}</h1>
</header>
<main>
{{ content_for_layout }}
</main>
<footer>
<p>&copy; {{ 'now' | date: '%Y' }} {{ shop.name }}</p>
</footer>
</body>
</html>

Key parts explained:

CodePurpose
{{ request.locale.iso_code }}Sets the page language
{{ page_title }}Dynamic page title from Shopify
{{ shop.name }}Your store’s name
{{ content_for_header }}Required! Shopify injects tracking scripts, analytics, and other essential code here
{{ content_for_layout }}Required! This is where your page content appears
{{ 'now' | date: '%Y' }}Current year for the copyright

Important: Never remove {{ content_for_header }} or {{ content_for_layout }}. Without them, your theme won’t function properly.

Step 2: The Homepage Template

In modern Shopify themes, templates are JSON files that define which sections to load.

Create templates/index.json:

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

This tells Shopify:

  1. Load a section called main-content
  2. Give it the ID main
  3. Display sections in the specified order

Step 3: The Homepage Section

Sections contain the actual Liquid code for your content.

Create sections/main-content.liquid:

<section>
<h2>Welcome to {{ shop.name }}</h2>
<p>This is a minimal Shopify theme for learning Liquid.</p>
<h3>Your Products</h3>
{% if collections.all.products.size > 0 %}
<ul>
{% for product in collections.all.products limit: 5 %}
<li>
<a href="{{ product.url }}">{{ product.title }}</a>
<span>{{ product.price | money }}</span>
</li>
{% endfor %}
</ul>
{% else %}
<p>No products yet. Add some in your Shopify admin!</p>
{% endif %}
</section>
{% schema %}
{
"name": "Main Content",
"settings": []
}
{% endschema %}

What’s happening here:

  1. We display a welcome message with the shop name
  2. We check if there are any products in the store
  3. If yes, we loop through the first 5 and display them
  4. If no, we show a helpful message

The {% schema %} block at the bottom is required for all sections. It defines settings (ours is empty for now) and tells Shopify about the section.

Step 4: Theme Configuration

Every theme needs a configuration file that defines theme settings.

Create config/settings_schema.json:

[
{
"name": "theme_info",
"theme_name": "Sandbox Theme",
"theme_version": "1.0.0",
"theme_author": "Your Name",
"theme_documentation_url": "",
"theme_support_url": ""
}
]

This is the minimal config. It just identifies your theme. You can add custom settings later.

Uploading to Your Dev Store

You have two options for getting your theme into Shopify:

Option A: Using the Online Code Editor

  1. Go to your store admin → Online StoreThemes
  2. Click Add themeUpload zip file
  3. Zip your theme folder and upload it

Or create files manually:

  1. In Themes, click on any theme → Edit code
  2. Create each file in the appropriate folder
  3. Copy-paste the code from above

Option B: Using Shopify CLI

If you’ve set up local development:

Terminal window
cd my-sandbox-theme
shopify theme push --unpublished

This uploads your theme as an unpublished theme you can preview.

Testing Your Theme

  1. Go to Online StoreThemes
  2. Find your sandbox theme
  3. Click Preview

You should see:

  • Your shop name in the header
  • A welcome message
  • A list of products (if you have any)
  • A footer with the copyright

It’s bare-bones and unstyled, but it works!

Using This Theme for Tutorials

This sandbox theme is designed for learning. Here’s how to use it with our lessons:

Adding Code Examples

When a lesson shows you Liquid code, you can:

1. Create a new snippet

Most code examples work great as snippets:

{# snippets/example-code.liquid #}
{# Paste the tutorial code here #}

Then include it in your section:

{% render 'example-code' %}

2. Edit the main section

For larger examples, edit sections/main-content.liquid directly:

<section>
<h2>Tutorial Example</h2>
{# Paste the tutorial code here #}
</section>
{% schema %}
{
"name": "Main Content",
"settings": []
}
{% endschema %}

3. Create a new section

For complete features:

  1. Create a new file like sections/tutorial-example.liquid
  2. Add it to templates/index.json

Where to Put Different Code

Code TypeLocation
Small examplessnippets/ folder
Page componentssections/ folder
Reusable piecessnippets/ folder
Full page changesEdit templates/*.json

Resetting After Experiments

Made a mess? Easy reset options:

Option 1: Revert a file

In the code editor, the Older versions dropdown shows previous saves.

Option 2: Re-upload the theme

Keep your original minimal files saved locally. If things break, just re-upload.

Option 3: Delete and recreate

Themes are disposable during development. Delete it and push a fresh copy.

Extending the Theme

As you learn more, you can grow your sandbox:

Add More Page Templates

Create templates/product.json:

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

Then create sections/product-content.liquid:

<section>
<h2>{{ product.title }}</h2>
<p>{{ product.description }}</p>
<p>Price: {{ product.price | money }}</p>
</section>
{% schema %}
{
"name": "Product Content",
"settings": []
}
{% endschema %}

Add Theme Settings

Expand config/settings_schema.json:

[
{
"name": "theme_info",
"theme_name": "Sandbox Theme",
"theme_version": "1.0.0",
"theme_author": "Your Name"
},
{
"name": "Custom Settings",
"settings": [
{
"type": "text",
"id": "welcome_message",
"label": "Welcome Message",
"default": "Welcome to our store!"
}
]
}
]

Then use it in your section:

<p>{{ settings.welcome_message }}</p>

Add Basic Styling

When you’re ready for CSS, create assets/theme.css:

* {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}

Then include it in layout/theme.liquid:

<head>
...
{{ 'theme.css' | asset_url | stylesheet_tag }}
{{ content_for_header }}
</head>

Key Takeaways

  1. A Shopify theme needs at minimum: layout, template, section, and config files
  2. content_for_header and content_for_layout are required in your layout
  3. Sections need a schema block, even if it’s empty
  4. Templates are JSON that reference sections
  5. Start simple and add complexity as you learn

🛠 Ready to Build Sections? When you start creating more complex sections, our Schema Builder helps you visually design schemas with settings, blocks, and presets.

What’s Next?

You now have a working sandbox! Continue with the course to learn more advanced Liquid concepts:

  • Explore Filters in depth
  • Learn about Sections and Blocks
  • Build real theme components

This minimal theme is your playground. Experiment, break things, and learn. That’s what it’s for!

Finished this lesson?

Mark it complete to track your progress.

Discussion

Loading comments...