Improve Shopify Templates with TypeScript and Tailwind CSS
As developers, we aim to utilize tools that enhance our code quality, maintainability, and overall productivity. Personally, I’ve become attached to using Tailwind CSS and TypeScript. I frequently incorporate these tools into my Next.js projects and find them particularly useful when creating Shopify themes. This post serves as a guide for implementing TypeScript and Tailwind within Shopify themes.
Dev Dependencies
To begin, we will need to install a few development dependencies in our project. Although we'll be using pnpm for this tutorial, npm or yarn can also be used.
Create your package.json
in the root directory of the theme.
pnpm init
Create or update the package.json
file in the root directory. Initialize it and follow the instructions in the terminal.
Vite
Our development environment will utilize Vite. Vite will transpile our TypeScript into JavaScript and construct Tailwind using JIT, which generates a stylesheet containing only the classes utilized in your project. We will also leverage PostCSS to add vendor-specific prefixes for cross-browser compatibility.
pnpm add vite fast-glob -D
This command installs Vite and fast-glob. Fast-glob is a plugin that helps traverse our directory and find files matching the patterns we specify.
TypeScript
TypeScript has proven valuable in catching minor bugs early during development. It also integrates seamlessly with editors such as VS Code, providing helpful auto-completions.
pnpm add typescript ts-node -D
Tailwind CSS
Tailwind is quite popular nowadays, and for good reason. It enables quicker iterations without the hassle of creating class names or worrying about inheritance.
pnpm add tailwind postcss autoprefixer -D
.shopifyignore
If you’re using the Shopify CLI for themes, you can create a .shopifyignore
file in the root of your theme directory to instruct the CLI not to upload specific files to Shopify’s servers.
*.cjs
src
vite.config.ts
tsconfig.json
package.json
pnpm-lock.yaml
Our .shopifyignore
file excludes the src
directory and other configuration files.
Vite Configuration
In our configuration file, we will define build options that direct Vite on how to operate.
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: [],
})
Summary
outDir
: Specifies the directory relative to the root where the build output will be stored.emptyOutDir
: This is set to false to prevent the outDir from being cleared and replaced each time Vite builds. While this feature is handy, our outDir is theassets
folder, where you might also have other files aside from those built by Vite.rollupOptions
: Allows for direct customization of the underlying Rollup bundle (refer to the documentation).rollupOptions.input
: Files that fit this pattern will be processed by Vite.glob-input
: A plugin is added to pass our input to fast-glob, allowing for faster file traversing.
Tailwind Configuration
Let’s create a Tailwind configuration 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
Summary
/** @type {import('tailwindcss').Config} */
: This adds TypeScript types for improved intellisense.content
: Specifies where Tailwind should look for class names. This powers the Just-In-Time Engine that constructs your stylesheet with only the minimal CSS required.theme.extend
: We can extend Tailwind's default theme to utilize CSS variables defined intheme.liquid
or elsewhere in your theme. This functionality allows the Tailwind theme to be controlled from the theme settings in the Shopify admin.
Base Styles
With Tailwind, you don't have to write custom stylesheets; instead, you utilize the class names directly in your markup. You’ll create a single global stylesheet that imports a reset alongside some base styles. This file will reside in your src
folder, ensuring it gets built with Vite.
@tailwind base;
@tailwind components;
@tailwind utilities;
src/base.css
PostCSS Configuration
Make sure to include the PostCSS configuration for Tailwind.
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
postcss.config.cjs
Development Workflow
Now that we have everything set up and configured, we’re ready to start building our theme. I typically use two terminal windows to run the pnpm scripts I’ve included in 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
PNPM Scripts
pnpm dev
: This command runs our Vite configuration and monitors for changes.pnpm shopify
: This launches your development server for your Shopify theme. Ensure you replace the--store
flag with your Shopify store.
Once everything is set up, you can modify your theme files and use Tailwind classes. Vite will generate the necessary stylesheet, and the Shopify CLI will notice that Vite has modified a file, triggering a hot reload of your theme to keep everything in sync. You can also incorporate TypeScript files into your src
folder for any necessary functionality or user interactions within your theme.
I’ve found this setup to be straightforward to establish yet extremely powerful. I hope this guide assists you in starting to create Shopify themes utilizing Tailwind CSS and TypeScript.
If you have any questions or feedback, feel free to reach out to me on Twitter. Follow me there for more guides and updates like this!
Conclusion
In conclusion, integrating TypeScript and Tailwind CSS into Shopify themes development can significantly enhance the development process by improving code quality, maintainability, and productivity. By leveraging tools like Vite for efficient build processes and PostCSS for cross-browser compatibility, developers can create more robust and responsive themes. This setup not only streamlines the workflow but also allows for greater customization and control over the theme's appearance and functionality. Embracing these modern technologies can lead to a more efficient and enjoyable development experience, ultimately resulting in better-performing Shopify themes.
Subscribe to my newsletter
Read articles from Younis Ahmed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Younis Ahmed
Younis Ahmed
Hey there! 👋 Developer by day, Graphic Designer by night, and Software Engineer Student in between. 🌟 Join me on this journey as I explore the world of coding, design, and everything tech-related. 🖥️✨ #DeveloperLife #GraphicDesignPassion #TechJourney