Using Typescript and Tailwind CSS in a Shopify theme
Shopify themes with Tailwind CSS and Typescript
As developers we want to use tools that help make our code better and more maintainable and allow us to be our most productive. For me those tools include Tailwind CSS and Typescript. I’ve grown fond of using these tool in projects I build with Nextjs and find myself reaching for them when I develop Shopify themes. This post is a guide to using Typescript and Tailwind in Shopify themes.
If you want to skip the explanation and view the code check out the Tradewind starter theme on Github.
Dev Dependencies
To get started we’ll need to install some dev dependencies in our project. We’ll use yarn
for this tutorial but npm
or pnpm
would work as well.
Create your package.json
in the theme’s root directory.
yarn init
Create or update package.json file in root directory. Init and follow the steps in the terminal.
Vite
Our dev environment will be powered by Vite. Vite will transpile our Typescript to Javascript. It will also build Tailwind with JIT, which builds a stylesheet with only the classes used in your project. We’ll also use Postcss to add vendor specific prefixes for cross browser support.
yarn add vite fast-glob -D
Install Vite and fast-glob. fast-glob is a plugin to traverse our directory and find files that match patterns we provide it.
Typescript
TypeScript has helped me catch small bugs early in development. It also integrates with editors like VS Code to provide helpful autocompletions.
yarn add typescript ts-node -D
Tailwind CSS
Tailwind is all the rage these days, and for good reason. I am able to iterate much faster without having to think about creating class names and worrying about inheritance.
yarn add tailwind postcss autoprefixer -D
.shopifyignore
If you’re using the Shopify CLI for themes you can add a .shopifyignore
file to the root of your theme directory to tell the CLI not to push certain files to Shopify’s servers.
*.cjs
src
vite.config.ts
tsconfig.json
package.json
yarn.lock
Our .shopifyignore file ignores our src directory and other config files.
Vite configuration
In our config file we will set build options that tell Vite what to do.
import fg from 'fast-glob'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
outDir: 'assets',
emptyOutDir: false,
rollupOptions: {
input: 'src/**/*.{ts,js,css}',
output: {
dir: 'assets',
entryFileNames: '[name].js',
assetFileNames: '[name].[ext]',
},
plugins: [
{
name: 'glob-input',
options(options) {
const inputs = typeof options.input === 'string' ? [options.input] : options.input
return Array.isArray(inputs)
? { ...options, input: inputs.flatMap((input) => fg.sync(input)) }
: null
},
},
],
},
},
plugins: [],
})
vite.config.cjs
What’s happening?
outDir
: Directory relative from root where build output will be placed.emptyOutDir
: We set this tofalse
so ouroutDir
is not emptied and replaced each time Vite builds. This is a nice feature but ouroutDir
is the assets folder where you’ll probably have other files than what is built from Vite.rollupOptions
: Directly customize the underlying Rollup bundle (see docs).rollupOptions.input
: Files that match this pattern will be built with Vite.glob-input
: We’re adding a plugin to pass ourinput
tofast-glob
for faster file traversing.
Tailwind configuration
Let’s add a Tailwind config file with some options.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./**/*.liquid', './src/**/*.{ts,js}'],
theme: {
extend: {
fontFamily: {
body: 'var(--font-body-family)',
heading: 'var(--font-heading-family)',
},
colors: {
text: 'rgba(var(--color-base-text), <alpha-value>)',
accent1: 'rgba(var(--color-base-accent-1), <alpha-value>)',
accent2: 'rgba(var(--color-base-accent-2), <alpha-value>)',
background1: 'rgba(var(--color-base-background-1), <alpha-value>)',
background2: 'rgba(var(--color-base-background-2), <alpha-value>)',
},
},
},
plugins: [],
}
tailwind.config.cjs
What’s happening?
/** @type {import('tailwindcss').Config} */
: Add Typescript types for better intellisense.content
: Tell Tailwind where to look for class names. This powers the Just In Time Engine that builds your stylesheet with the bare minimum CSS you need.theme.extend
: We can extend the default Tailwind theme to use CSS variables you add intheme.liquid
or somewhere else in your theme. This is useful to allow the Tailwind theme to be controlled from theme settings in the Shopify admin.
Base styles
With Tailwind you don’t have to write stylesheets you just use the class names in your markup. You will create one global stylesheet that imports a reset and some base styles. This file will be in your src
folder so it gets built with Vite.
@tailwind base;
@tailwind components;
@tailwind utilities;
src/base.css
Postcss Configuration
Be sure to add the Postcss config for Tailwind.
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
postcss.config.cjs
Development workflow
Now that we have everything installed and configured we’re ready to start building our theme. I use 2 terminal windows to run yarn scripts I’ve added to package.json
.
{
"name": "tailwind-typescript-theme",
"version": "0.0.1",
"scripts": {
"dev": "vite build --watch",
"shopify": "shopify theme dev --store=REPLACE_WITH_YOUR_STORE",
"build": "tsc && vite build"
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"fast-glob": "^3.2.12",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.4",
"ts-node": "^10.9.1",
"typescript": "^4.9.5",
"vite": "^4.1.1"
}
}
package.json
Yarn scripts
yarn dev
: This runs our Vite configuration and watches for changes.yarn shopify
: This spins up your dev server for your Shopify theme. Be sure to replace the—store
flag with your Shopify store.
Once you’re up and running you can edit your theme files and use Tailwind classes and Vite will build the necessary stylesheet. The Shopify CLI will see Vite changed a file and hot reload your theme and keep everything in sync. You can add Typescript files in you src
folder for any functionality or user interaction you need on your theme.
I’ve found this set up to be simple to set up, yet really powerful. I hope this guide helps you start writing Shopify themes with Tailwind CSS and Typescript.
If you want to see an example of this in practice check out the Tradewind starter theme on Github.
If you have questions or feedback you can reach me on twitter. Follow me there for more guides and updates like this.