Right, the static/ directory. This one is beautifully simple, which is why so many of you will get it wrong. I’m not here to judge; I’ve done it myself. Here’s the deal: anything you put in here gets copied exactly as-is directly into your final public/ folder when you run hugo. No processing. No minification. No finger-wagging from Hugo’s templating engine. It’s a straight, verbatim file copy.

Think of it as the VIP backstage pass for your files. They bypass the whole bouncer-and-velvet-rope system (Hugo’s processing pipeline) and get dropped right into the middle of the party.

What Actually Belongs Here?

This is for the raw assets of your site. The usual suspects include:

  • Images, icons, and favicons that aren’t managed by the page bundles (we’ll get to those later). Your site logo, social media share images, that sort of thing.
  • Downloadable files: PDFs, ZIP archives, .epub files. If a user should click a link and their browser should prompt them to download it, it probably lives here.
  • Robots.txt and sitemap.xml: Yes, you can generate these with Hugo, but sometimes you just want a simple, static file. Plop it in static/ and you’re done.
  • JavaScript libraries you’re including manually. For example, if you just want to drop a jquery.min.js in and be done with it.
  • Custom CSS or font files if you’re not processing them through Hugo Pipes or a postcss pipeline.

Here’s a super common and perfectly valid structure within static/:

static/
├── images/
│   ├── logo.svg
│   └── favicon.ico
├── downloads/
│   └── my-whitepaper.pdf
├── js/
│   └── custom-analytics.js
└── css/
    └── legacy-ie-fixes.css

When you build, this becomes:

public/
├── images/ # <- copied from static/
│   ├── logo.svg
│   └── favicon.ico
├── downloads/ # <- copied from static/
│   └── my-whitepaper.pdf
... # and so on

The Pathing Trap and How to Avoid It

This is the big one. The most common “oh for crying out loud” moment. Let’s say you have a file at static/images/hero.jpg.

How do you reference it in your template? Not from the root of your project. You reference it from the root of the final website.

Wrong (you will get a 404):

<!-- This looks right from your project's perspective, but Hugo doesn't care. -->
<img src="/static/images/hero.jpg" alt="My hero">

Right (the only way that works):

<!-- Think like the browser. The 'static' directory name is GONE. -->
<img src="/images/hero.jpg" alt="My real hero">

See what happened? The static/ part of the path is stripped during the copy. The file lands at public/images/hero.jpg, so that’s the path you use. This trips up absolutely everyone at least once. Consider it a rite of passage.

Static vs. Assets: Which One, You Fool?

Ah, the existential Hugo question. You also have an assets/ directory. What’s the difference? It’s a question of processing.

  • Use assets/ for files you want Hugo to process or fingerprint. Think Sass files you want compiled to CSS, or JavaScript you want to minify and bundle using Hugo Pipes. Hugo gets its hands on these files.
  • Use static/ for files you want to remain completely untouched. They are perfect and pristine and shall not be defiled by any build step.

If you’re just dumping a pre-minified JS library into the site, static/ is your friend. If you’re writing custom SCSS, that goes in assets/ so Hugo can work its magic.

A Quick Word on Performance (Because I Care)

Just because you can dump 500MB of high-res photos directly into static/ doesn’t mean you should. Remember, these files are copied wholesale on every build. If you have a ton of large, raw assets, your build times will suffer. For a large media site, this is where you’d offload those files to a CDN or a dedicated asset server and not use static/ for them at all. Use this directory for necessities, not your entire digital archive. Your future self, waiting for that build to finish, will thank you.