Shopify has fostered a good-sized community of themes for sale, and lot of them can be configured easily. However, they may not have the right combination of features, support, content priority, and brand feel that you are looking for. In that case, it is reasonable to find a Shopify partner (such as thoughtbot) to build you one from scratch.
This article is intended to be a guide for the developer or designer tasked with building a Shopify theme.
Shopify theme developer stack
Developing a theme for Shopify is a little bit different than for something like Wordpress. First of all, you do not run a local server instance or database. I’m not sure why, but I bet it is because Shopify made a choice to reduce complexity for the entire community by hosting and guaranteeing the quality of the data model. That way, you don’t have to worry about ever updating your server.
Instead, you work locally and use a syncing utility to push your changes to the server instantly, where you can view them. Shopify officially supports two utilities for syncing:
- shopify_theme gem is a RubyGem for the command-line.
- The Shopify Desktop Theme Editor is a Mac App and text editor.
If you are comfortable with the command-line, I highly recommend the shopify_theme gem. The rest of this guide will assume you made this choice.
There are other utilities out there, such as grunt-shopify, but I have not experimented with them.
The Shopify asset CDN
Every asset you push up to the server (images, fonts, CSS, JavaScript) is automatically deployed, concatenated, minified (except for JavaScript), gzipped, and finger-printed on Shopify’s CDN. The templating language provides you with asset helpers to reference the assets.
So, you have everything you need for asset packaging and delivery. However, it does create issues when developing because you are looking at minified CSS. The JavaScript is not minified or uglified.
Developing with a starter theme
Like any hosted CMS platform, there are a multitude of small details that are specific to that platform. Choosing to use a starter theme helps you understand the low-hanging fruit of the platform as quickly as possible without spending too much time Googling the basics.
Shopify officially supports two starter themes:
- The Shopify Skeleton Theme has more minimal styling, although it does contain a simple grid system and basic styling.
- The Shopify Timber Theme has more styling to start, includes the csswizardry-grids grid system, a version of Bootstrap, a fancy Ajax cart and a live style guide.
On my latest project, I chose Timber because both projects have some level of styling and layout, and the styling markup is already littered throughout the templates. If I truly wanted to start from scratch, I’d have to go in and remove all the classes and start over with the Sass. I didn’t have time for that, so I decided to leverage Timber.
I had never used csswizardry-grids before, but it works just fine and has not created any blockers for me.
Shopify theme developer workflow
Once your sync is up and running with shopify_theme gem, be
careful because by default you will be syncing directly to production. If
you do not specify a
theme_id in your configuration file, the default is to
push to the currently published theme. Typically this is only comfortable for a
day or two, but the moment your client wants begin showing it to others
(investors, co-founders, friends, etc.) you should consider switching to a more
stable workflow.
We wanted to create something similar to how thoughtbot works on any other project. We want an environment where we have:
- Feature branches
- Green tests (we’ll get to that)
- Pull requests
In the Shopify world, because they own the server and database, the traditional concept of production environment is a bit different. you have to think about the published theme instead. That is the theme currently published and live on the site. It is possible to have additional unpublished themes that an administrator can view but don’t show up for regular users. We can leverage this with the shopify_theme gem.
Shopify theme development workflow
Here is our typical workflow for a single feature branch:
- Pull from
masterand checkout a new branch
- Log into Shopify store admin
- Duplicate the published theme theme
- Rename the duplicated theme to the name of your branch
- Click “Customize Theme” of your new branch theme
- Note the theme ID in the URL (example:
/admin/themes/9542224/settings)
- Edit the
theme_idin
config.ymlto point to your branched theme
theme watchand do your work
- Preview your work by navigating to that theme in Shopify admin and clicking preview
- Pull Request
- Rebase onto master, push to master repo
- Delete your branch (local and server)
- Delete your branched theme in Shopify Admin
Deployment
When it’s time to deploy, force-deploy the theme in the master branch onto the production site:
- Make sure to kill your local theme watcher
- Remove your theme ID (to point it to the published theme)
theme uploadto push master onto the primary theme. If you have deleted files you can also run
theme replace.
If you’re doing it right, you should always be confident in pushing master onto
the published theme, provided you blacklisted the
settings_data.json.
Ignore the Shopify theme settings data
As a developer, you can expose theme settings to the admin user by adding to
config/settings.html. When an admin changes a setting, it is written to
config/settings_data.json on the server, however the
theme watch is not a
two-way street. The local copy of
config/settings_data.json will not reflect
settings made through the admin interface, and if you edit it locally, it will
push up and overwrite what is on the server. Therefore, it is best to ignore
this file altogether from your repository and let it live only on the server.
Update the
config.yml:
:api_key: 000000000000000000000000000000 :password: 000000000000000000000000000000 :store: mystore.myshopify.com :theme_id: :ignore_files: - config/settings_data.json
Update the
.gitignore:
config/settings_data.json
Shopify’s pseudo-staging environment
The workflow discussed so far set up a pseudo-staging environment. Admin users can view the branched themes to work on development, or do acceptance, but the underlying database is still the production database. However, this has not been a problem for us because we almost never affect the data while developing, testing or just clicking around.
The final step of checkout (actually clicking purchase) needs very little testing because that portion is hosted by Shopify and has it’s own test coverage provided by Shopify (presumably). Even if we did purchase a product and thereby decrease inventory, we can cancel it right away in the admin.
Maintaining a true Shopify staging environment
It would be plausible to create a second development store, entirely separate from the production store. As a Shopify Partner, you can do that easily and for free. However, it would expose some considerations that must be handled to use it effectively:
- The client will likely be affecting product data constantly (images, options, variants, etc.) and the data on a true staging environment would likely grow stale quickly.
- The client and other admins will be affecting theme settings frequently. Which means the
config/settings_data.jsonfile on production would also have to be synced frequently to staging to create a realistic production environment.
Therefore, I would be resistant to creating a completely stand-alone staging environment until we had a compelling reason to incur those costs. We have not had one yet.
Using Sass with Shopify
In the Spring of 2013, Shopify introduced Sass (scss syntax only) compilation to their themes. If you are new to Sass, it is a CSS pre-compiler that gives you a lot of very handy things (variables, control flow, includes, etc.).
However, on Shopify, you can not use the Sass
@import rule because of how the
Liquid templates are included. If you have multiple stylesheets, you can use the
CSS
@import, but that will not carry your Sass variable namespace across files
because it occurs in the browser, after the Sass has been compiled and delivered
to the user.
That means you have a choice between:
- One long Sass file that contains all the things
- Not using Shopify’s Sass compilation, compiling locally in development, and pushing up the rendered CSS.
Consider what level of ongoing support you need to provide. Unless the team using the theme going forward has developers, it is best to let Shopify perform the Sass compilation. That way, an admin can make small changes and not require a full development machine setup.
Other Reading
- Learn how to separate your rending vs. non-rendering sass for better Sass file organization