Intro to Shopify Theme Development

Written by

In this post, we’re going to introduce you to Shopify Theme Development by creating a local work environment and reviewing the Shopify Theme directory structure.

Install the Shopify Theme Kit

The Shopify Theme Kit is a utility created and maintained by Shopify that connects to the Shopify store and uploads all of our changes. Enter the commands below to install it on your operating system.

On Mac:

brew tap shopify/shopify
brew install themekit

On Windows:

choco install themekit

On Linux:

curl -s https://shopify.github.io/themekit/scripts/install.py | sudo python

Get API access

To access the store, we need API access. On the Shopify Admin page, go to Apps and click on Manage private apps link at the bottom of the screen. Then, click Create a new private app and set a name and an email address. In the Admin API section, click on the Review disabled admin API permissions, scroll to Theme templates and theme assets, and select Read and write as the access option. Press the Save button and then copy the API key and Password.

Start Developing a Theme

You can create a theme using the theme new command with your password, store link, and theme name. First, create a directory for the theme and cd into that directory. Then use the theme new command as follows:

mkdir CoolTheme && cd CoolTheme
theme new --password=[your-password] --store=[your-store.myshopify.com] --name=CoolTheme

If you already have a theme, you can download it by finding the theme id with:

theme get --list -p=[your-password] -s=[you-store.myshopify.com]

And then:

theme get -p=[your-password] -s=[you-store.myshopify.com] -t=[your-theme-id]

In the project root we can find a file called config.yml with the following structure:

development:  
	password: [your_shopify_api_password]  
    theme_id: "[your_theme_id]"  
    store: your-test-store.myshopify.com
production:   
	password: [your_production_shopify_api_password]  
    theme_id: "[your_productuon_theme_id]"  
    store: your-production-store.myshopify.com

This is used by Theme Kit to connect to the store and apply your changes.

You can also separate environments, such as development and production, by using different stores or different themes in the same store. The config.yml file can use variable interpolation to get the values from the environment. This allows us to commit our theme to a git repository while keeping the store secrets protected.

development:  
	password: ${DEV_PASSWD}  
    theme_id: ${DEV_THEME_ID}  
    store: ${DEV_STORE}
production:   
	password: ${PROD_PASSWD}  
    theme_id: ${PROD_THEME_ID}  
    store: ${PROD_STORE}

And you can store the environment values in the variables file in the Theme Kit installation folder, which is located in different places depending on your operating system:

Windows	%APPDATA%\Shopify\Themekit\variables
Linux/BSDs	${XDG_CONFIG_HOME}/Shopify/Themekit/variables
MacOSX	${HOME}/Library/Application Support/Shopify/Themekit/variables

If you’re familiar with the .env notation, it’s the same structure for the variables file:

DEV_PASSWD=YOUR_SECRET_DEV_PASSWORD
DEV_THEME_ID=123
DEV_STORE=your-test-store.myshopify.com
PROD_PASSWD=YOUR_SECRET_PROD_PASSWORD
PROD_THEME_ID=123
PROD_STORE=your-production-store.myshopify.com

Now, you can deploy by simply signaling to Theme Kit what environment you want to use:

theme deploy --env=production

You can also use it with other commands such as watch:

theme watch --env=development

Enabling live reload

You can enable live reload for the site by using Browsersync with the theme watch command.

We start by installing Browsersync:

npm install -g browser-sync

Then use the  --notify flag with the theme command to tell Theme Kit to notify us when an update is completed:

theme watch --notify=/var/tmp/theme_ready --env=development

Finally, we tell Browsersync to watch the /var/tmp/theme_ready and reload the site when it changes:

browser-sync https://your-test-store.myshopify.com /var/tmp/theme_ready -w --reload-delay 1000

However, there will be conflict between Shopify and Browsersync because both try to add some content to the page head. To avoid this problem, go to layout/theme.liquid file and add the following to the end of thehead tag:

{% if request.host != 'your-test-store.myshopify.com' or 
content_for_header contains 'designMode'%} 
	{{ content_for_header }}
{% endif %}

Your site should now be live at http://localhost:3000/.

The Shopify Theme Structure

A theme is defined by Shopify as a set of files organized in a certain folder structure. At the highest level we find the following directories:

  • assets
  • config
  • layout
  • locales
  • sections
  • snippets
  • templates

Let’s go over what each folder is for and how it should be used.

Assets folder

The assets directory contains everything for your theme, including javascript files, images, sounds, videos, and stylesheets. 

Speaking of stylesheets, Shopify allows you to have Sass files and will handle the conversion to CSS by itself. The catch is that you cannot use @import statements. If you are using the default theme provided by Shopify as your starting point, you’ll find the theme.scss.liquid file that contains all the styles. If you're intrigued about that .liquid extension, you can use the syntax inside your stylesheet for further customization. 

When importing a file from your assets directory you’ll need to use the asset_url liquid filter:

<script src="{{ 'theme.js' | asset_url }}" defer="defer"></script>

If you need to import a stylesheet, you can use the `stylesheet_tag` filter as well:

{{ 'theme.scss.css' | asset_url | stylesheet_tag }}

The settings_schema.json allows you to define theme settings that merchants can access using the theme editor. A merchant accesses the editor by clicking Customize from the Themes page of their Shopify admin. If you want to define the color_button setting for a color picker you will need to add:

{
	"type": "color",   
    "id": "color_button",   
    "label": {   
    "da": "Primære knapper",   
    "de": "Primäre Buttons",   
    "en": "Primary buttons",   
    "es": "Botones primarios",   
    "fi": "Ensisijaiset painikkeet",   
    "fr": "Boutons primaires",   
    "hi": "प्राथमिक बटन",   
    "it": "Pulsanti primari",   
    "ja": "主なボタン",   
    "ko": "기본 버튼",   
    "nb": "Primærknapper",   
    "nl": "Primaire knoppen",   
    "pt-BR": "Botões primários",   
    "pt-PT": "Botões principais",   
    "sv": "Primära knappar",   
    "th": "ปุ่มหลัก",   
    "zh-CN": "主要按钮",   
    "zh-TW": "主要按鈕"  
    },  
    "default": "#3a3a3a"
}

Layout folder

The layout directory contains the theme.liquid file. This is the master template for the theme and is in charge of rendering any elements that need to be repeated in all pages like headers and footers. This file requires that you render two things: the {{ content_for_header }} object in head tag and {{ content_for_layout }}  in the body tag. The content_for_layout object will have the content of each page generated by one of the templates such as index.liquid for the home page or collection.liquid for the product list.

Locals folder

The locales folder contains the localization strings for several languages. To define the default text, Shopify needs a file with the structure *.default.json. If the theme is in English, by default it will be en.default.json. Shopify doesn’t allow for hardcoded strings on internationalization. It only works if you use translation keys and the translation filter to render the correct string. So, if we want to have a Read more string for, let’s say, an article from our blog, we’ll need to create:

// en.default.json
{
...
"article":{    
	"read_more": "Read More"  
    }
}

es.json
{
"article":{ 
	"read_more": "Leer mas" 
    }
}

And to show it:

<a>{{ 'article.read_more' | t }}</a>

Sections folder

The sections directory contains reusable components for the site. These are liquid template files that can be called in other templates and can have standalone configurations. Shopify has two kinds of sections: static and dynamic. 

Static sections are simply sections that are hard-coded in a template. An example of this can be a header or footer section for the theme layout that will make Shopify go to the sections folder and load the header.liquid file:

// theme.liquid
...
{% section 'header' %}
...

Dynamic sections are sections you can add, remove, and reorder from the theme editor. Currently they are only available for the index page, however. Since they are dynamic, no markup is necessary to render them. It’s up to the merchant to select which ones to show and the content will appear wherever {{ content_for_index }} is located.

A section can be a self-contained entity that should include a {% schema %} and can have its own {% stylesheet %} and {% javascript %}. The schema has a similar structure to the settings_schema.json file from the config folder, and it allows the section to be configurable from the theme editor. It can also contain blocks, which are like dynamic sections within a section that you can add, remove, or reorder.

Snippets folder

The snippets directory contains code snippets that can be referenced in other templates. An example of this can be SVG icons. If you need to include a new icon for the theme, create a file inside snippets, like icon-cart.liquid and paste in your SVG code. Then, you render the icon just where you need it: 

{% render 'icon-cart' %}

You can also pass parameters to the snippet:

{% assign my_class = 'icon' %}
{% render 'icon-cart', my_class: my_class, my_other_class: 'icon-cart' %}

This way you can access the {{ my_class }} and {{ my_other_class }} variables inside the snippet.

Templates folder

Finally, we have the templates directory which contains the liquid templates for all pages including index.liquid for the home page, article.liquid for a blog article, and so on. Templates are responsible for rendering the particular sections for a page. There are some customization options for the merchant as well, so a merchant can choose a template to apply when creating a page or a blog post. This is done by following Shopify naming conventions and creating a page.your_template.liquid or article.your_template.liquid so the merchant will get a dropdown with the options.

Conclusion

Thanks for reading. I hope this post has helped get you started with Shopify and Theme Development. Please let us know if you have any questions or, better yet, show us your theme!

If you are interested in joining our team, please visit our Careers page.

Frequently Asked Questions