Improve Shopify Templates with TypeScript and Tailwind CSS

Younis AhmedYounis Ahmed
5 min read

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 the assets 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 in theme.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.

0
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