This post is going to walk you through how to set up Tailwind CSS and Vite in a Kirby CMS project. There are numerous examples and even plugins using Vite and Tailwind CSS with Kirby CMS; however, I couldn’t find any that offered a simple approach to set these up in the standard folder template structure.
Kirby CMS Project
First off, in order to set this up, you will need either a new or preexisting Kirby CMS project setup. If you already have a project then you can skip this step and move on to installing the necessary dependencies.
Install New Project
The simplest way to get a new project setup would be to download any of the templates offered on the Kirby website at the below link.
For instructions on how to install via composer or other methods:
Install Dependencies
Run the below command in your terminal to add the necessary npm dependencies. The -D is a shorthand for the --dev flag for yarn and --save-dev flag for npm.
yarn add -D vite vite-plugin-live-reload tailwindcss autoprefixer
npm install -D vite vite-plugin-live-reload tailwindcss autoprefixer
Set Up Files
- Create a srcfolder in the root directory and add anindex.jsandindex.cssfile. Import thecssfile at the top of thejsfile.
import './index.css'
- In the index.cssfile add the below to include Tailwind CSS.
/* Filename can be whatever you want */
@tailwind base; 
@tailwind components; 
@tailwind utilities; 
- Add a vite.config.jsfile in the root directory. Note that the default method for adding Vite currently only works on Firefox and Safari browsers. If you are using Chrome and using a non php server like Laravel Valet, then you will need to sethosttotrueand use the provided Network IP for your scripts (see step 6).
import liveReload from 'vite-plugin-live-reload' 
import { resolve } from 'path' 
export default () => ({ 
  // set the input source path 
  root: 'src', 
  server: { 
    strictPort: true
    // If using Chrome then need to set "host" to true
    host: true
  }, 
  build: { 
    outDir: resolve(process.cwd(), 'public'), // production output directory 
    emptyOutDir: true, 
    manifest: true, 
    rollupOptions: { 
        input: resolve(process.cwd(), 'src/index.js'), // input source path for rollupjs 
        output: { 
          // remove hashes from file names 
          entryFileNames: '[name].js', 
          chunkFileNames: '[name].js', 
          assetFileNames: '[name].[ext]' 
        } 
      }
    }, 
  plugins: [ 
    // add live reload to the php pages 
    liveReload([
      'content/**/*', 
      'site/**/*.php'
    ], { root: process.cwd() }) ] 
}) 
- Setup Tailwind CSS - run npx tailwindcss init -pwhile in the root directory.
The below config is based off of Tailwind CSS  v3. If you are using or intend to use a version of Tailwind CSS below v3, then you will need to replace "content"  with the word "purge" and to add mode: 'jit' to the config. Refer to the Tailwind CSS migration guide for more details.
module.exports = {
  // If using Tailwindcss version below v3 then replace "content" with "purge"
  content: [
	'./site/templates/**/*.{twig,php}',
	'./site/snippets/**/*.{twig,php}',
	'./src/index.css',
  ],
  // If using Tailwindcss version below v3 then need to uncomment below
  // mode: 'jit',
  darkMode: false, // or 'media' or 'class'
  theme: {
	extend: {},
  },
  variants: {
	extend: {},
  },
  plugins: [],
}
- Add scripts to package.json:
{
  "scripts": {
	"dev": "vite",
	"build": "vite build"
  },
  "devDependencies": {
  	// ...dependencies
  }
}
- Add necessary script tags in a headersnippet.
If using Firefox or Safari:
This will also work with Chrome if you are using a php server (ex: php -S localhost:8000).
<?php if (c::get('debug')): ?>
<script type="module" src="http://localhost:3000/@vite/client"></script>
<script type="module" src="http://localhost:3000/index.js"></script>
<?php else: ?>
<link rel="stylesheet" href="/public/index.css">
<script type="module" crossorigin src="/public/index.js"></script>
<?php endif;?>
If using Chrome and a non-php server (ex: Laravel Valet):
Currently there is a cors issue when using Chrome due to a new feature that prevents you from allowing scripts from localhost:3000 if your site/app dev server is different than localhost. If using Chrome, you will need to use the Network IP provided in the terminal after running yarn dev.
<?php if (c::get('debug')): ?>
  <script type="module" src="http://XXX.XXX.XXX.XXX:3000/@vite/client"></script>
  <script type="module" src="http://XXX.XXX.XXX.XXX:3000/index.js"></script>
<?php else: ?>
  <link rel="stylesheet" href="/public/dist/index.css">
  <script type="module" crossorigin src="/public/dist/index.js"></script>
<?php endif;?>
# ...
</head>
- In order to determine if in development or production mode, you can create a config.[local-url].phpfile in thesite/configdirectory (if it doesn't exist then create this directory) and set debug totrue. This will allow you to only run the development scripts when developing locally and use production build for production. You can get more information about a multi config file setup from the Kirby website.
# config.localhost.php
<?php
return [
	'debug' => true,
];
- Great! Now just run yarn devwhen developing andyarn buildto create your production build. If you end up only using oneconfig.phpfile be sure to setdebugtofalsebefore using for production.
That's it! After setting up everything above you should now be able to leverage all of Vite's glory in your Kirby project. If you would like a head start, you can use the below starter template I have created.
If you are able to use the public folder structure, I would recommend using arnoson's kirby-vite plugin.