Proper way to set up theme with node dependencies

Hey all,

I looked through a few repository examples but I’m not sure what the best way do this is. What I’d like to do is pretty straightforward — create a theme that I can reuse, that uses Tailwind CSS and other dependencies like AlpineJS.

From what I can see, a lot of themes have a package.json in their theme folder. How does this transfer to a development environment and to deployment? Are node_modules installed within the theme folder? Do I also potentially have a package.json and node_modules folder in the project root? How do I decouple the project from the theme? That is, if I pull in the theme to a brand new Hugo project and set the theme in the project config.toml file, do I have to do more to get the theme’s package.json, node_modules, etc. to work?

Did you already read that tutorial: https://thoughtexpo.com/setup-hugo-with-tailwindcss-for-netlify/

Thanks for the link cmlnet. I really appreciate you taking the time to help.

I did take a look at this, but my question is specific to adding Tailwind to a theme, not to a project. Am I missing something?

It looks like themes using Tailwind CSS have package.json files in the theme’s folder. I just don’t understand how I should be setting up the dev and production environments for that. Does Hugo automatically install the packages somehow? Do I do that manually?

Related, it looks like themes using Tailwind CSS do something like this in their head:

{{- $styles := resources.Get "css/styles.css" | postCSS (dict "config" "./assets/css/postcss.config.js") -}}

Does Hugo evaluate this and run postCSS from that config at build time? Does it also look for a package.json? Does Hugo expect a globally installed PostCSS instead?

1 Like

To be honest, I don’t know the answer to your problem. Building my own theme just sits on my todo list.

However, it might be a starting point to look at themes that already use Tailwind CSS. On the themes page there are three of them listed: https://themes.gohugo.io/tags/tailwindcss

@schwartzmj i had my fair share of challenges in blending tailwind with hugo and below is the gist for your queries, i can write a follow up for my initial blog post if you can elaborate your needs and below answer doesn’t solve your queries in full.

Code snippet taken from https://github.com/leelavg/thoughtexpo

How does this transfer to a development environment and to deployment?

  • In case of Hugo with Tailwind, we potentially need purgeCSS in deployment and faster renders in development
  • For example with below code in your head partial $ hugo serve (typically used in dev) hugo will invoke postcss-cli to act up on css/tailwind.css according to it’s config
{{$tailwind := resources.Get "css/tailwind.css" | resources.PostCSS (dict "inlineImports" true)}}
{{if (eq (getenv "NODE_ENV") "production")}}
    {{$tailwind = $tailwind | minify | fingerprint | resources.PostProcess}}
{{end}}
  • But with $ NODE_ENV=production hugo (typically used in deploy) postcss-cli also triggers purgeCSS as specified in tailwind.config.js and hugo in addition to above also minifies and fingerprints css.

Are node_modules installed within the theme folder?

  • You will never be committing node_modules to git, typically this folder goes into .gitignore and yes, packages mentioned in package.json will be downloaded to this folder locally upon running npm install or yarn install but when deployed to, typically Netlify, it installs these packages before hugo builds the site.

Do I also potentially have a package.json and node_modules folder in the project root?

  • You will only be committing package.json (vs node_modules) to version control but once these packages get installed locally in node_modules, hugo and postcss-cli utilizes them without you needing any manual intervention.

How do I decouple the project from the theme?

Does Hugo evaluate this and run postCSS from that config at build time?

  • I assume config as in tailwind.config.js, package.json, postcss.config.js but not config.[yaml/toml] then yes hugo with the feature Hugo Pipes talks typically with postcss-cli which then uses postcss.config.js and calls the plugins mentioned in that config.

Does it also look for a package.json?

  • yes, hugo typically looks for package.json in root dir if postcss is used or any other location which is specified inline.

Does Hugo expect a globally installed PostCSS instead?

  • hugo expects postcss-cli executable be available either globally or locally.

Please take my response as a rebuttable presumption and disregard the info which you already know of.

HTH, @leelavg.

3 Likes