How to include JS/CSS from node_modules folder in Hugo

In our previous posts:

we showed how to configure Hugo and your Theme to include custom JS/CSS file.

A usecase that is often relevant (especially considering EU GDPR laws) is to include Javascript and CSS not from a CDN, but include them locally from your site.

In practice, that means that we want to include it from the node_modules folder instead of, for example, jsDelivr.

In this example, we’ll include the katex library from the node_modules folder. It requires that you have configured Hugo to accept both custom CSS & custom Javascript as shown in the previous posts.

It requires that you have katex installed in your node_modules folder:

npm_install_katex.sh
npm install --save katex

Hugo does not support including from the node_modules folder directly. The recommended way is to use module mounts to mount the relevant node_modules subdirectories into Hugo’s assets filesystem.

Note: In Hugo versions before v0.162.0, symlinking files from node_modules into the assets folder was a common workaround. However, starting with v0.162.0, Hugo rejects symlinked entries in resources.Get for security reasons (CVE-2026-50135), so module mounts are now the correct approach.

Add the following to your hugo.yaml to mount the katex dist directory into assets/vendor/katex:

hugo.yaml
module:
  mounts:
    - source: assets
      target: assets
    - source: static
      target: static
    - source: node_modules/katex/dist
      target: assets/vendor/katex

Important: When you define module.mounts, all default mounts are replaced — so you must explicitly re-mount assets and static as shown above.

Now, in your hugo.yaml, you can reference the mounted files like this:

hugo.yaml
params:
  custom_css:
    - 'css/techoverflow.css'
    - 'css/kicad.css'
    - 'vendor/katex/katex.min.css' # KaTeX CSS, mounted from node_modules
  custom_js:
    - 'js/kicad.js'
    - 'js/algolia.js'
    - 'vendor/katex/katex.min.js' # KaTeX JS, mounted from node_modules

Important: This is not a post about how to configure KaTeX for Hugo (more steps are required for this!)! It’s just about how to include JS/CSS from the node_modules folder in Hugo.

Hugo will not automatically copy the assets from the assets folder to the public folder, so you need to make sure that your build process includes these files. This means you need to use resources.Get somewhere in your theme to include the files.

include_katex_assets.html
<link rel="stylesheet" href="{{ (resources.Get "vendor/katex/katex.min.css").RelPermalink }}" />
<script defer src="{{ (resources.Get "vendor/katex/katex.min.js").RelPermalink }}"></script>

Check out similar posts by category: Hugo