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 --save katexHugo 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_modulesinto theassetsfolder was a common workaround. However, starting with v0.162.0, Hugo rejects symlinked entries inresources.Getfor 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:
module:
mounts:
- source: assets
target: assets
- source: static
target: static
- source: node_modules/katex/dist
target: assets/vendor/katexImportant: When you define
module.mounts, all default mounts are replaced — so you must explicitly re-mountassetsandstaticas shown above.
Now, in your hugo.yaml, you can reference the mounted files like this:
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_modulesImportant: 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.
<link rel="stylesheet" href="{{ (resources.Get "vendor/katex/katex.min.css").RelPermalink }}" />
<script defer src="{{ (resources.Get "vendor/katex/katex.min.js").RelPermalink }}"></script>