Motivation
Let me begin by stating the reason of this post. You might have noticed that I wrote another blog on why I chose Slater and how I used it to develop themes on Shopify. After digging around the default theme in Slater, it was apparent that the JavaScript they used in the theme was too heavily integrated. They were using PicoApp and I thought to myself, "If I need to learn Pico, why don't I just start a theme from scratch and use my JavaScript framework of choice -- Vue.js?"
If you wish to start a theme from scratch and use Vue.js, read on.
Setting Up Themekit
Follow the installation instructions for Themekit up till you have a password. To get started with a totally barebones theme, I utilised Themekit CLI to create an empty theme that can be uploaded to Shopify. This meant that the most essential folders and files were created by Themekit to make sure it works with Shopify.
theme new --password=[your-password] --store=[your-store.myshopify.com] --name=[theme name]
I've tried other themes such as Skeleton or Starter themes by Shopify (recommended by Slate) but somehow Slate was unable to build them properly, causing issues with the theme when I uploaded them to Shopify. Since I'm gonna be customising my client's site quite a bit, I guess I could start from scratch.
You can also choose to update an existing theme by getting it. Your theme id can be grabbed from the end of the URL, such as when you edit the code from Shopify's site. 123456123456
will be your theme id from this URL https://your-shop.myshopify.com/admin/themes/123456123456
.
cd to/your/folder/of/choice
theme get -p=[your-password] -s=[you-store.myshopify.com] -t=[your-theme-id]
Ignore settings_data.json file
In Shopify, settings_data.json file in config is somewhat like a database to store whatever the user has configured in Shopify's theme editor page. Unless you already have populated a settings_data.json, we do not need to push this file if we are starting from scratch. We will just let Shopify's theme editor handle this.
To ignore the file, simply add the following to your config.yml file.
development:
password: your_password_here
theme_id: "your_theme_id_here"
store: your_shopify_store_link_here
ignore_files:
- config/settings_data.json
Running Themekit
The purpose of Themekit is to sync your local theme files with Shopify. So whenever you make a change on your machine, Themekit would watch for these changes and push it to Shopify, thereby updating the theme. Unfortunately, there is no live-reloading or local testing built into Themekit. This meant that you have to reload your Shopify site manually after changing a file.
The command to watch for file changes
theme watch
The command to open the theme on Shopify to preview
theme open
Using Gulp for a Sass Workflow
Being a huge fan of Sass, I've always wanted to use it whenever I can. I particularly like the partial imports, nesting of selectors and file structure guidelines to organise my styles. When setting up Themekit, they prompted whether I would be using Sass. If you select it, the CLI will also generate a styles.scss in your assets folder, which will also be referenced in your theme.liquid file.
To make our lives easier, we can use Gulp to compile all the .scss files in the various folders to replace the styles.scss found in assets. I followed the guide by Code Shopify for setting up Gulp.
- Install gulp globally
npm install --global gulp-cli
- Create
gulpfile.js
in the root of your theme folder - Initialise node
npm init
- Install dependencies
npm install gulp gulp-sass gulp-replace gulp-autoprefixer gulp-rename --save-dev
My gulpfile.js
looks like this
var gulp = require("gulp");
var sass = require("gulp-sass");
var replace = require("gulp-replace");
var autoprefixer = require("gulp-autoprefixer");
var rename = require("gulp-rename");
gulp.task("sass", function () {
//root scss file (import all your partials into here)
return (
gulp
.src("./sass/styles.scss")
.pipe(sass({ outputStyle: "compressed" }).on("error", sass.logError))
// add vendor prefixes
.pipe(autoprefixer())
// change the file name to be styles.scss.liquid file
.pipe(rename("styles.scss.liquid"))
// remove the extra set of quotations used for escaping the liquid string (we'll explain this in a sec)
.pipe(replace('"{{', "{{"))
.pipe(replace('}}"', "}}"))
// save the file to the theme assets directory
.pipe(gulp.dest("./assets/"))
);
});
gulp.task("default", function () {
// this assumes your sass is in a directory named sass
gulp.watch("./sass/**/*.scss", gulp.series("sass"));
});
As for my sass
folder structure, it looks something like this
/sass
/components
/_component-a.scss
/...other components
/global
/_typography.scss
/styles.scss
Run gulp
command and it'll run whenever you save a SCSS file. Gulp will update the styles.scss file, which runs some configuration to replace the /assets/styles.scss.liquid
file which would then trigger Themekit to sync it with Shopify. As such, we have a pretty good system to manage our .scss files in a nice and organised manner.
Vue.js
Last but not least, Themekit would also ask if you need an application.js file. By choosing so, you will find one in your assets folder. This file will host all of our Vue code.
To install Vue.js, we will make use of the CDN method. Include the following in your theme.liquid file.
<head>
...
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
..
</div>
</body>
{{ application.js | asset_url | script_tag }}
Then in your application.js file, setup Vue with a custom delimiter since Liquid uses the same delimiter.
const app = new Vue({
delimiters: ['${', '}'],
el: '#app',
data: {
message: 'Hello Vue!'
}
})
So from this point onwards, you can make use of Vue in all your pages. If you need to use the data from Vue, you can do so like this.
<span>${message}</span>
Vue.js with Liquid
Some fun thing you can do with Liquid and Vue is to use them together. You can do stuff like this:
<a href="/" v-bind:class="['fr ac sidebar-item item-icon', '{{ handle }}' ? '' : 'active']"></a>
This will check if the handle from Liquid exists and populate the class name.
Dynamic Sections in the Home Page
The power of using a custom theme is giving our clients the flexibility to choose the content for their shopfront. Shopify provides our clients with the ability to add 'sections' we have created for them to add to their home page (index.liquid). Note that only index.liquid will have the ability to add sections as and when the user pleases using the Shopify Theme editor.
To get this working, there are 3 main parts to this.
1. Configuring index.liquid file
To allow for dynamic sections, simply use this line for your entire index.liquid file.
{{ content_for_index }}
2. Adding a custom section
The main gist of a custom, yet dynamic section is to have a "presets" attribute in the schema object. An example of a valid dynamic section is as follows:
<div>
...
</div>
{% schema %}
{
"name": "Blog posts",
"settings": [
{
"type": "text",
"id": "title",
"label": "Heading",
"default": "Journal"
},
{
"type": "blog",
"id": "blog",
"label": "Blog posts",
"info": "Posts will be pulled from this blog."
}
],
"presets": [
{
"category": "Blog",
"name": "Blog posts",
"settings": {
"blog": ""
}
}
]
}
{% endschema %}
3. Edit settings_data.json file
Go to your Shopify Theme Editor for this theme and check if you are able to "Add section" to your Home Page. If you can see this "Add section" button, skip this step. You're done! Otherwise, read on.
When we configured our theme kit according to the instructions above, I mentioned to ignore the settings_data.json file. Since theme kit has provided us with an empty settings_data.json, we sort of have to trigger Shopify by manually adding our dynamic section. Note that you only have to do this once. Afterwards, your clients can simply add dynamic sections through the Shopify's Theme Editor.
So, for our Blog Posts dynamic section, we will have to add the following to settings_data.json file. I've only gotten this to work the first time I tried it but the idea is there.
{
"current": {
...,
"sections": {
"1533544588949": {
"type": "home-blog-posts",
"settings": {
"title": "Journal",
"blog": "news"
}
},
"content_for_index": [
"1533544588949"
]
},
"presets": {
"Default": {}
}
}
Current object holds the data user has configured. So, the value of "1533544588949" simply holds the id for our blog post section, as well as the data it comes with.
"content_for_index" stores the section ID added to the index page.
Lastly, the "presets" is used for changing theme which we will be leaving it blank.
With these 3 steps, you should have a dynamic section that could be added to your Home Page on the Shopify Theme Editor.
Things to Note
You have to understand that Liquid variables are populated before Vue is loaded on any page. This means that you cannot programatically refresh the Liquid variable unless you refresh the webpage itself.
I ran into this problem where I have a sidebar cart overlay and I couldn't refresh this cart if I added an item to the cart without refreshing. This means that if the cart shows 2 items, and I add another item to cart, the cart will still show 2 items unless I manually refresh the entire page. To solve this, I simply used the Ajax API to manually load the cart.
Conclusion
I hope this blog post is useful for those who wish to use Vue with the Shopify theme customisation. I'm getting a hang of this and I'll be writing about the project soon.