Hugo mixed content ideas

I’m looking to build a reference site on my location’s LAN based on Hugo as a publishing mechanism for markdown reference riles (how to access the printer/download drivers, upcoming events at our facility, etc). I would also like to include files like layout drawings, powerpoint presentations, etc. Basically things that won’t encessary be published as HTML but should be available for download or if someone clones the repository.

According to Directory structure | Hugo, the static directory seems to be where I should keep those things…unless I am using page bundles. Which a theme might do. The guide does not give a new best practice for the following kind of scenario

– my-site
— content
---- reference
----- (notes about the facility and links or transcludes from drawio and pptx - links are OK for now)
----- facility-map.drawio (which I would like to both display in the .md but more importantly have available for download)
----- facility-newsletter.pptx (not my content, just need to ahve the latest version here and link to it for download).

I don’t see any clear hugo guidance and the themes I’ve looked at seem to have different ways of doing this which don’t look compatible (create a new directory, customize the config.toml file, etc). Is there a best-practice way I should do this?

There’s no direct relationship between page bundles and the static directory. You can use both at the same time or not. If you want to provide files to download for others, putting them somewhere under static should be ok (and simpler, too, if you want to link to them from different documents). So, perhaps putting reference with all its content under static might be a good idea.

1 Like

My thoughts…

  1. Every file that you reference from content should be a page resource or a global resource. This provides a flexible foundation for future capabilities, and helps to avoid common problems with resolution of markdown link and image destinations.
  2. Use link and image render hooks to properly resolve markdown link and image destinations.

Project structure

├── branding/
│   ├── logo-400x100.png    <-- global resource
│   ├── logomark-60x60.png  <-- global resource
│   └── style-guide.docx    <-- global resource
└── videos/
    ├── changing-paper-on-hp-designjet-t830.mp4  <-- global resource
    └── using-the-epson-projection-system.webm   <-- global resource
├── references/
│   ├── facility-map/
│   │   ├── aerial-photo.jpg             <-- page resource
│   │   ├── facility-map-diagram.drawio  <-- page resource
│   │   ├── facility-newsletter.pptx     <-- page resource
│   │   └──
│   └──

If a resource will only be referenced from one page, place it within the page bundle. If a resource will be referenced from two or more pages, make it a global resource by placing it somewhere within the assets directory.

Link and image render hooks

This article explains why these are important, and provides examples of each.


This is an example of what I have described above:

git clone --single-branch -b hugo-forum-topic-47801 hugo-forum-topic-47801
cd hugo-forum-topic-47801
hugo server

What’s the advantage of using asset over static for non-image files? I can see that images are better placed in assets because one might want to transform them (responsive images, webp, whatever). But why place global files that are never modified in assets?

Lots of reasons:

  1. Avoid problems with link resolution as described in the article referenced above. Once you have captured a file as a resource (page, global, or remote) you can use its Permalink or RelPermalink method.

  2. Easily get file content. Once you have captured a file as a resource (page, global, or remote) you can use its Content method. This includes unmarshaling data files. There is almost never a good reason to use os.ReadFile or os.ReadDir.

  3. Easily get media type. Once you have captured a file as a resource (page, global, or remote) you can access its MediaType object. Think of audio/video elements, icons next to download links, etc.

  4. Etc.

Use the static directory for files unrelated to content (i.e., files to which you will not link, and just want dumped to the public directory when you build your site):

  • favicon.ico
  • robots.txt
  • site ownership verification files
  • etc.

I can add a couple more:

  1. They can be transformed (e.g. minified, fingerprinted, image processing etc.)
  2. They are Go objects so Hugo has more knowledge about them (it’s not just a file copy)

The last bullet will be more evident in a soon to be released version of Hugo (working on the last parts now): Partial rebuilds when running the server. The current version has a very coarse grained approach to this, which works mostly great, but there are some surprises. In the next Hugo we can tell that if assets/js/lib/myfuncs.js changes, we can quickly determine all other resources (resources and pages) that’s using this resource either directly or indirectly and do a rebuild/rerender. We will still do a “fast render” (render on demand), but we will have much stronger confidence about getting everything refreshed.


Thanks, and I could just test this myself, just looking for the right pattern to start with. So I could put in the static folder and it would be rendered as part of the public site?

Thanks for this! I am going to try this model out.

No. It would be copied. If you want to render it, it must be part of your content hierarchy. Loosely spoken.

I was more wondering about documents like PDFs, PowerPoints, Word-Docs and code samples. Those don’t need to be minified, fingerprinted or image processed. Nor do they need to be Go objects – they just need to be linked to like a favicon or a logo image so that the user can download them. Of course, they can be put in assets and handled by a link render hook. But does that have any advantages over a simple MD link in these cases (again: I’m not referring to images, CSS or other data that needs to be processed before it’s put in public).

There are not as many reasons for files which don’t need processing, but there are still two which come to (my) mind immediately.

Joe Mooring already mentionend them:

  • You can let your hook check for their existence and rule out typos in their path. You can print a warning about broken links as soon as possible: at build time!
  • You can determine their file type and change the styling of the link or add some icon etc…
1 Like

Right. That are use cases.

  • Some may want to fingerprint PDFs etc. for cache busting
  • Some may also want to list/filter/sort their PDFs etc.

… but you don’t have to.

site configuration

baseURL = ''


├── favicon.ico
├── non-disclosure-agreement.pdf
└── robots.txt


[Link to NDA](/non-disclosure-agreement.pdf)

And everything works great.

Now change the site configuration:

baseURL = ''

I just broke every markdown link and image that target the static directory.

This is not an edge case. In addition to sites intentionally served from a subdirectory, sites without custom domains hosted on GitHub Pages and GitLab Pages are also served from subdirectories.

On this forum, I have typed the phrase “you are serving your site from a subdirectory” in 14 topics. That does not include all the variations of that phrase, posts from other users, issues mistakenly created on GitHub, etc.


Maybe a practical example can further drive home the great suggestions already presented.

I recently moved my professional website from a virtual server to Cloudflare Pages.

Cloudflare accepts the redirect configuration from a file in the root of the site named _redirects. So I had to migrate my historically grown nginx redirect configuration based on try_files.

One of the caveats is that Cloudflare executes redirect rules from /_redirects even if a matching file actually exists. This implies that I needed to ensure that none of the hugo-generated URIs appeared in /_redirects.

This worked fine for all my regular pages, but did not work for my publication PDFs, because I had placed them in static long before page bundles existed. By moving those PDFs into a page bundle, their URIs became known to Hugo and I could keep them out of _redirects (the version incorporating this change is not yet on GitHub).

Having gone through this migration last week, I can tell you that I wish I had abandoned static for resources I want to link to in my Hugo pages sooner.


This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.