FullStack Labs

Please Upgrade Your Browser.

Unfortunately, Internet Explorer is an outdated browser and we do not currently support it. To have the best browsing experience, please upgrade to Microsoft Edge, Google Chrome or Safari.
Upgrade
Welcome to FullStack Labs. We use cookies to enable better features on our website. Cookies help us tailor content to your interests and locations and provide many other benefits of the site. For more information, please see our Cookies Policy and Privacy Policy.

Intro to Shopify Theme Development

Written by 
Carlos Angarita
,
Senior Software Engineer
Intro to Shopify Theme Development
blog post background
Recent Posts
Integrating GitHub Actions and Docker for a Java Project
Businesses Must Seize the AI Wave (Or Cease to Exist)
Code, Deploy, Succeed: Next.js, Firebase, and Tailwind CSS Unleashed

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.

Table of contents

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:

-- CODE language-jsx keep-markup --
brew tap shopify/shopify
brew install themekit

On Windows:

-- CODE language-jsx keep-markup --
choco install themekit

On Linux:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
theme get --list -p=[your-password] -s=[you-store.myshopify.com]

And then:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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.

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
theme deploy --env=production

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

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
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:

-- CODE language-jsx keep-markup --
{% 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:

-- CODE language-jsx keep-markup --
<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:

-- CODE language-jsx keep-markup --
{{ '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:

-- CODE language-jsx keep-markup --
{
   "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:

-- CODE language-jsx keep-markup --
// en.default.json
{
...
"article":{
    "read_more": "Read More"
  }
}

-- CODE language-jsx keep-markup --
// es.json
{
"article":{
"read_more": "Leer mas"
}
}

And to show it:

-- CODE language-jsx keep-markup --
<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:

-- CODE language-jsx keep-markup --
// 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: 

-- CODE language-jsx keep-markup --
{% render 'icon-cart' %}

You can also pass parameters to the snippet:

-- CODE language-jsx keep-markup --
{% 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!

Using techniques like what is listed above, we have had the opportunity to address our clients’ concerns and they love it! If you are interested in joining our team, please visit our Careers page.

Carlos Angarita
Written by
Carlos Angarita
Carlos Angarita

I've had a passion for computers since a young age. When I grew older and was deciding what I wanted to do with my life, becoming a developer felt like the most natural course. Devs have one of the coolest skill sets that I can think of — we can build anything imaginable just by typing on a keyboard. The way a product can grow from an idea into something that can impact the life of others is the best and most rewarding feeling this job can offer. I've developed apps that help GoDaddy users market their products and that connect Covid-19 researchers with one another to help solve the pandemic. My favorite technology is TypeScript; when I’m developing, it's nice to see every piece fall into his place, and TypeScript helps me see it a lot better. I love different storytelling mediums, and lately I've been enjoying tabletop RPGs and videogames, but I also spend plenty of time with television series, movies, anime, manga, and books.

People having a meeting on a glass room.
Join Our Team
We are looking for developers committed to writing the best code and deploying flawless apps in a small team setting.
view careers
Desktop screens shown as slices from a top angle.
Case Studies
It's not only about results, it's also about how we helped our clients get there and achieve their goals.
view case studies
Phone with an app screen on it.
Our Playbook
Our step-by-step process for designing, developing, and maintaining exceptional custom software solutions.
VIEW OUR playbook
FullStack Labs Icon

Let's Talk!

We’d love to learn more about your project.
Engagements start at $75,000.

company name
name
email
phone
Type of project
How did you hear about us?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.