DEV Community

Cover image for Easily Add TailwindCSS to Your AdonisJS Project
Warren Wong
Warren Wong

Posted on • Originally published at


Easily Add TailwindCSS to Your AdonisJS Project

If you haven't created a base AdonisJS project yet, check out my post on setting up VSCode for AdonisJS where I walk you through both creating a new AdonisJS project as well customizing the VSCode Prettier formatter to my liking.

Laravel Mix is a wrapper around Webpack that helps abstract away a lot of the confusing Webpack configurations and is especially useful when used with an MVC framework like Laravel and AdonisJS.

First, you'll need to install it through npm or yarn then create a webpack.mix.js file:

# 1a. npm
npm i -D laravel-mix

# 1b. yarn
yarn add -D laravel-mix

# 2.
touch webpack.mix.js
Enter fullscreen mode Exit fullscreen mode

Before we go any further, let's decide where to put our front end assets. Looking at some guidance from the AdonisJS 4.1 docs, looks like a good place to put them would be in resources/assets.

So let's create a TypeScript file that will serve as our entry into the front end scripts as well as a CSS file to load TailwindCSS.

mkdir resources/assets
mkdir resources/assets/ts
touch resources/assets/ts/app.ts
mkdir resources/assets/css
touch resources/assets/css/app.css
Enter fullscreen mode Exit fullscreen mode

Now let's install Tailwind and the associated dependencies:

# npm
npm i -D tailwindcss@latest postcss@latest autoprefixer@latest

# yarn
yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest
Enter fullscreen mode Exit fullscreen mode

Create the tailwind.config.js file:

npx tailwindcss init
Enter fullscreen mode Exit fullscreen mode

While you CAN just touch tailwind.config.js, this command actually tests to see if you have dependencies like PostCSS. If something went wrong, you'll know at this stage.

Now let's set it up to remove unused styles. This step is critical if you want to deliver the smallest bundle size.

If this was just a quick project where you didn't need to customize your Tailwind configuration and didn't care about the bundle size, the easiest way to leverage TailwindCSS would be to just bring in Tailwind via CDN.

  purge: [
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  variants: {
    extend: {},
  plugins: [],

Enter fullscreen mode Exit fullscreen mode

Now open up the webpack.mix.js file we created earlier and configure the entry and output for our TypeScript and CSS files.

const mix = require("laravel-mix");


  .ts("resources/assets/ts/app.ts", "js/app.js")
Enter fullscreen mode Exit fullscreen mode

We need to set the public path to public because that's where the static assets for our AdonisJS project are located. Laravel Mix can handle TypeScript files as long as you install ts-loader as a dependency, so let's do that:

# npm 
npm i -D ts-loader

# yarn
yarn add -D ts-loader
Enter fullscreen mode Exit fullscreen mode

You'll notice that I placed the transpiled JavaScript in the public/js directory and the resulting CSS file in public/css. We will need to know that when we edit our HTML file.

Now let's place our @tailwind directives in our empty app.css file as per a normal Tailwind setup:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Now let's run mix to build the front end assets:

npx mix
Enter fullscreen mode Exit fullscreen mode

You will now see the new files in your public directory. Go ahead and place them in your Edge template:

  <link rel="stylesheet" href="css/app.css'">
  <script src="js/app.js'"></script>
Enter fullscreen mode Exit fullscreen mode

Go ahead and inspect the app.css file to see that the @tailwind directives have been replaced with the Tailwind library.

Top comments (0)


11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields


Read the whole post now!