Can't figure out the very basics of content structure ↔︎ generated

I really can’t figure out the very basics of content structure :left_right_arrow:︎ generated.
I’ve used other static-site generators for years and recently decided to try Hugo for a new project.

Essentially it is a collection of documents (mainly markdown) that lives in some file directories.
I’d like to have a corresponding file structure generated.

However, I’ve now spent several days on this, carefully reading every part of the Hugo documentation website, and in the end, I’ve exhausted all ideas.

The following graphic summarizes my problem:

If I rename content/windows/panels/index.md to content/windows/panels/_index.md then the public/windows/dialogs.html document disappears (no longer being generated), but! the property-panels document suddenly is now generated.

If I instead rename content/windows/panels/index.md to content/windows/panels/foo.md then both public/windows/panels/foo.html and public/windows/panels/property-panels.html is generated, but now I’m missing public/windows/panels/index.html

This seems to be a bug, or possibly an overly-complex set of undocumented rules of how content is interpreted.

I’d expect Hugo to do the most obvious thing out of the box — to mirror the content file tree (generate an identical tree of .html files.)

The reason we suggest showing the project code in Requesting Help is because without seeing the contents of your files, we can only guess the issue. For instance, most people missing output have draft: true. I’m not saying that’s your issue, just that is our experience, so please meet us in the middle. :slight_smile:

I can’t quite tell where dialogs.md is in the hierarchy, from the screenshot. Is it at the same level as panels? Which layout templates are you using?

If you can’t share that specific project, we recommend making a smaller, shareable project that reproduces the issue.

1 Like

It does. Where it might get confusing is when you throw some Page Bundles in the mix.

You mention what Hugo generates, but (unless I missed it) not the actual target structure you want generated.

I second the request for project code – makes it much easier to help :slight_smile:

I’m unable to attach anything but images. I’ve got a zip file with a minimal repro that I can send you somehow. I’m surprised this forum doesn’t allow attaching zip files.

Note that this is not an open-source project, so I can’t share a github repo or antything like that. I’ve re-created a minimal repro, however.

Here’s the ZIP on Dropbox.
https://www.dropbox.com/s/xatx7w1gviixpkz/hugo-test.zip?dl=1

(Note to future readers: This link will be dead past December 2018)

If I just use “index.md” (without the “_” prefix), the issue remains:

(My understanding from reading the documentation is that a “page bundle” is a directory with a “_index.*” file in it.)

Specifically, a branch bundle. Renaming it to an index.* (without the _ ) turns the dir into a leaf bundle. There are differences as to how each of these bundles treats content files (eg .md) that reside in its directory.

Consider the pairs of content<=> public directories below:

Assuming fresh Hugo site, no weird configs, no unusual front matter, url not set in front matter, draft: false

Scenario 1

No *index.md = no page bundles.

content/lorem
├── four
│   ├── hello.md
│   └── world.md
├── one.md
├── three.md
└── two.md


public
├── lorem
│   ├── index.html
│   ├── four
│   │   ├── hello
│   │   │   └── index.html
│   │   └── world
│   │       └── index.html
│   ├── one
│   │   └── index.html
│   ├── three
│   │   └── index.html
│   └── two
│       └── index.html

Scenario 2

content/lorem and content/lorem/four have _index.md: both are branch bundles.

content/lorem
├── four
│   ├── hello.md
│   ├── _index.md
│   └── world.md
├── _index.md
├── one.md
├── three.md
└── two.md

public
├── lorem
│   ├── four
│   │   ├── index.html        # notice
│   │   ├── hello
│   │   │   └── index.html
│   │   └── world
│   │       └── index.html
│   ├── index.html
│   ├── one
│   │   └── index.html
│   ├── three
│   │   └── index.html
│   └── two
│       └── index.html

Scenario 3

content/lorem/four has index.md = leaf bundle
content/lorem has _index.md = branch bundle

content/lorem
├── four
│   ├── hello.md
│   ├── index.md
│   └── world.md
├── _index.md
├── one.md
├── three.md
└── two.md

public
├── lorem
│   ├── index.html
│   ├── four
│   │   └── index.html        # notice
│   ├── one
│   │   └── index.html
│   ├── three
│   │   └── index.html
│   └── two
│       └── index.html
...

The reason the sub-pages (hello, world) under lorem/four ‘disappeared’ is because it is now a leaf bundle. As per the docs, (see the table comparing leaf v branch) content from non-index page files in leaf bundles are accessed only as page resources

I still don’t know what structure you want to end up with, so I can’t answer your specific use case.

5 Likes

Thank you, this is very helpful!
It seems that we should simply avoid using sections in this case.

So, we added a naming convention around these bundles (section pages and page bundles, also known as branch and leaf bundles), which made sense when we did it. I still does, but it is the number one question from people instinctingly creating these folders with index.md and some other content files and is surprised when the other files isn’t published.

I would say that in almost everyone of those cases I have seen, what you want is the “_index” variant (a section, or a branch bundle if you want):

content
└── windows
    └── panels
        ├── _index.md
        └── property-panels.md

One important remark here:

  • The “_index.md” is there to provdide a title + content etc.
  • But it also marks the bottom-most section. So, in the above example I have left out the “_index.md” on /windows (it will then get a default title), but I still get a navigational section tree (windows > panels).
1 Like

We tried disabling sections and renamed all _index.md to index.md but now nothing is generated.

Here’s doing the same with the sample project: (link to source above/earlier message)

Hugo claims to generate 10 pages, but only one file is actually produced:

[images in separate post as this forum limits me to just one image per post for some reason]

@bep Re using sections, it totally makes sense in theory, but seems limiting and confusing (from hidden rules) in practice. Also, the distinction between a “section” and a file directory is totally unclear to me. I.e. “/foo/bar/” can be thought of as “section foo with subsection bar”, “/foo/bar/baz/” as “section foo with subsection bar with subsection baz”, and so on. A fundamental principle of the file system.

As it is now, it seems we have two options:

  1. Change our site strucutre to only use two levels of hierarchy (since it seems anything beyond that, content starts to disappear)
  2. Switch to a different tool (or write one ourselves) that supports deeper file structures.

Again, all I want is this:

¯\_(ツ)_/¯

image 1:

image 2:
47

Let me put it this way:

content
└── windows
    └── panels
        ├── index.md
        └── property-panels.md

The the panels folder will produce 1 (one) page (assuming no URL set in front matter and default permalink setup) at http://example.com/windows/panels/index.html.

If you want the property-panels.md to also produce an URL, you have 3 choices:

  1. Rename index.md => “_index.md”
  2. Rename “index.md” = “myindex.md” and set “url: /panels” in front matter
  3. Remove index.md and you would get http://example.com/windows/property-panels/index.html

I wrote the above quickly, but it should be correct. My main point is this: You can disagree about how Hugo works, but it will not change behaviour if you hit it hard with a hammer.

This:

content
├── about.md
├── animals
│   ├── _index.md                # note _index.md
│   ├── land
│   │   ├── cat.md
│   │   ├── horse.md
│   │   ├── _index.md            # note _index.md
│   │   └── picture.png
│   └── sea
│       ├── dolphin.md
│       ├── fish.md
│       └── _index.md            # note _index.md
└── _index.md                    # note _index.md

will generate the output you describe.

public
├── about
│   └── index.html
├── animals
│   ├── index.html
│   ├── land
│   │   ├── cat
│   │   │   └── index.html
│   │   ├── horse
│   │   │   └── index.html
│   │   ├── index.html
│   │   └── picture.png
│   └── sea
│       ├── dolphin
│       │   └── index.html
│       ├── fish
│       │   └── index.html
│       └── index.html
├── index.html
└── sitemap.xml

You can have as many subsections as you want, I don’t see why you should be limited to just two. Adding content/animals/insects for example:

content
├── animals
│   ├── insects
│   │   ├── beetles
│   │   │   ├── _index.md
│   │   │   ├── ladybugs.md
│   │   │   └── scarab_beetles.md
│   │   ├── _index.md
│   │   └── lepidoptera
│   │       ├── butterflies
│   │       │   ├── _index.md
│   │       │   ├── skippers.md
│   │       │   └── swallowtails.md
│   │       ├── _index.md
│   │       └── moths
│   │           └── index.md
...

Gets you this:

public
├── animals
│   ├── insects
│   │   ├── beetles
│   │   │   ├── index.html
│   │   │   ├── ladybugs
│   │   │   │   └── index.html
│   │   │   └── scarab_beetles
│   │   │       └── index.html
│   │   ├── index.html
│   │   └── lepidoptera
│   │       ├── butterflies
│   │       │   ├── index.html
│   │       │   ├── skippers
│   │       │   │   └── index.html
│   │       │   └── swallowtails
│   │       │       └── index.html
│   │       ├── index.html
│   │       └── moths
│   │           └── index.html
...

Going back to your original code sample. As above:

content
├── _index.md
└── windows
    ├── dialogs.md
    ├── _index.md
    └── panels
        ├── _index.md
        └── property-panels.md

generated this for me:

public
├── index.html
├── sitemap.xml
└── windows
    ├── dialogs
    │   └── index.html
    ├── index.html
    └── panels
        ├── index.html
        └── property-panels
            └── index.html

PS: I have been assuming, but should probably have confirmed first: what version of Hugo are you using? hugo version should tell you this. I am on 0.49.2/extended

Oh, I see! So never use index.*, always use _index.*

Thank you for your help and patience everyone.

1 Like

You can use both variants in your project but you need to understand the implications which come with them. Since Hugo 0.32 everything in /content is basically regarded as page bundle and with that the distinction between index.md and _index.md got way more important. Refer to the documentation posted above to learn more.
Basically with an _index.md hugo basically performs like in earlier versions so every file gets their own structure. If you name it as index.md however it changes the behavior. The index-file is now basically regarded as the main content file, every other piece of content (including other .md files) is now regarded as resource to that content which you can refer to with the relevant shortcodes and also use in your templates with the Page.Resources function
Just think of the two types of bundles as following:

  • Leaf bundle: Single page (e.g. blog post or anything else), uses index.md
  • Branch bundle: Section, taxonomy list, can contain other bundles, pages in there will be published normally, uses _index.md

This post is a summary of the information written above by the others but I felt it was necessary to make it clear again that both index.* and _index.* can be used but it’s important to know when to use which one of them.

4 Likes