HUGO

Content depth (migrating from Jekyll)

Hi,

I am investigating migrating an existing website from Jekyll across to Hugo. Note: this isn’t a blog. It’s technical documentation, currently hosted via GitHub pages. The primary reason for this investigation is that the current Jekyll website is just taking too long to generate. This is partially due to the website size (a couple of thousand pages) but also due to the inherent speed of the liquid engine to create things like site navigation and breadcrumbs.

I’m trying to move some content across logically in order to test Hugo. I have not touched the themes yet, for example. I have followed the quickstart and have copied across some markdown pages from the current site. Performance is good (1,000 sample files copied), but I am very much at the start of this journey and I expect a lot of pain when it comes to migrating some of the liquid functionality we have.

Anyway.

The website itself consists of content many levels deep (https://site/A/B/C/D). In my new Hugo structure, I have copied “A/B/C/D” into the content folder. Each of the folders has an index.md file and, optionally, other .md files, along with supporting images and things. This is where things are going wrong. I have made Hugo write the generated files to disk so that I can see what’s going on.

In the generated folder I only see “A/index.html” being generated. “B” (and sub-folders) may be generated, but only if they contain images; it seems that the markdown content isn’t being converted at anything below this top level.

Is this expected? I’m very much a newbie but I can’t see any way to control this.

Regards,

Craig.

Yes.

This is documented. Take a look at some similar Hugo site’s sources … e.g. Linode docs, Let’s encrypt’s site, maybe also Kubernetes. All of them have been ported from something else (two of them from Jekyll) at some point.

This is documented.

Might you be able to point me at it, please? I am still trying to find my way around the documentation website and have obviously missed it.

I’ve taken a quick look at the Linode docs and Let’s encrypt site repositories but without knowing what I am looking for (am I to look at whether they have more than 1 folder deep of content and thus I need to convert my content accordingly, or am I looking at one of the configuration files to find a value that configures this setting?) I am a little lost.

Regards,

Craig.

That was the core of your question above, wasn’t it?

That was the core of your question above, wasn’t it?

Yes and no. I guess I know the answer, but that doesn’t help.

This output may be expected to you, but it wasn’t expected to me, so I need a little hand-holding here.

Let’s take the “Linode docs” site as an example. According to the config.toml document it appears that “/docs” is equivalent to my “/content” folder, so I can see that they do indeed have different depths of documents (e.g. https://github.com/linode/docs/tree/develop/docs/web-servers/apache-tips-and-tricks/apache-configuration-basics, which corresponds to https://www.linode.com/docs/web-servers/apache-tips-and-tricks/apache-configuration-basics/). That’s great news!

But… How?! You mentioned that this is documented. Can you give me a link? Nothing on the configuration documentation jumped out at me, and I’ve spent some time looking at the Linode docs repository but, honestly, I have no idea what I am looking for.

Regards,

Craig.

I suspect you have index.md files where you want _index.md files.

Example 1: index.md in root of a/

Content:

content
└── a
    ├── b
    │   ├── c
    │   │   ├── baz.md
    │   │   └── quez.md
    │   ├── bar.md
    │   └── foo.md
    └── index.md

Command:

hugo --disableKinds=RSS,taxonomy,term,sitemap

Rendered pages:

public
├── a
│   └── index.html
└── index.html

Example 2: _index.md in root of a/

Content:

content
└── a
    ├── b
    │   ├── c
    │   │   ├── baz.md
    │   │   └── quez.md
    │   ├── bar.md
    │   └── foo.md
    └── _index.md

Command:

hugo --disableKinds=RSS,taxonomy,term,sitemap

Rendered pages:

public
├── a
│   ├── b
│   │   ├── bar
│   │   │   └── index.html
│   │   ├── c
│   │   │   ├── baz
│   │   │   │   └── index.html
│   │   │   └── quez
│   │   │       └── index.html
│   │   └── foo
│   │       └── index.html
│   └── index.html
└── index.html

Documentation

Explanation

When you place either index.md or _index.md inside of a directory, you’ve told Hugo that the directory is a Page Bundle, of which there are two types:

Branch Bundles:

  • Indicated by presence of _index.md
  • Rendered as a list page using a list.html template
  • There may be additional content further down the branch

Leaf Bundles:

  • Indicated by presence of index.md (no underscore)
  • Rendered as a content page using a single.html template
  • This is the leaf at the end of a branch; content below this file in the directory structure will not be rendered
2 Likes

Thank you Joe for taking the time to explain this fully. I looked through the Page Bundles content but I must admit that I didn’t understand this nuance; the samples show having “*.md” pages further down the hierarchy, but I hadn’t noticed that the file in the parent folder was “_index.md”.

I didn’t find anything that explicitly referred to this behaviour (“index.md stops content in child folders”); a small recommendation from a newbie would be to add something to the documentation; perhaps in the section that talks about “Index Pages”. When I originally read this content I understood that it is used to control the template used, but I didn’t understand this side-effect (in my case I don’t necessarily need to use a different template).

Honestly: your “explanation” section posted here could be lifted directly onto the documentation and this would help newcomers immensely.

Thank you again, Joe. I understand my mistake and can move forward.

Regards,

Craig.

Your use of the term “nuance” is quite charitable. :laughing:

Merriam-Webster defines “nuance” as:

a subtle distinction or variation

The syntax variation is subtle, but the effect is anything but subtle. If you have the inclination, please create a documentation issue or pull request:

I would be willing to bet USD $20 that this “nuance” has, on at least one occasion, stymied the majority of Hugo site builders.

Can we agree that the difference between “index.md” and “_index.md” is subtle, even if the effect is anything but? :wink:

What made me miss this is that the current section of documentation that differentiates between these focuses on the fact that this alters the used template. In my specific situation I may not want/need the extra bits that the list template uses, so I would have been happy with them all using the “single” template. Thus, in my eyes, this was not something I needed to focus on as part of my initial learning.

I’ll try and create a documentation issue later today, but I certainly don’t feel that I understand this well enough to create a pull request with a proposed explanation.

My struggles have moved onwards. Currently we use Jekyll so our markdown has some kramdown bits in it (e.g. “{:.note}” after a paragraph to add a style so that we can customise how it’s shown). At the moment I don’t see an easy solution to this. It may well be that this is a blocker for us, although I truly would have liked to have seen what performance improvements I could have gotten by migrating the navigational logic across to Hugo.

I haven’t given up, but the list of stuff to change is getting longer. :slight_smile:

Thank you again Joe.

Regards,

Craig.

Issue created: https://github.com/gohugoio/hugoDocs/issues/1164

As an aside - and I know that the docs repo is not the place to raise this - I am not yet completely taken with the requirement to use “_index.md” in the parent folders. I understand the concept of using this to drive the template but, honestly, I personally feel that it is a little awkward. I guess this is down to the fact that I have typically used front matter for these things.

I know that I just need to engage with the naming convention better. I’ll try.

Regards,

Craig.

1 Like

You only need to include _index.md if you wish to provide content or front matter values when rendering a list page.

Yes, I understand that. In my case - and I guess that it’s not a unique one - I don’t want the default content in the parent folders to simply be a list of the child content. So, in that case, I am required to use that naming convention.

It’s just one that I find a little awkward and need to engage with further.

It tripped me up which is arguably the sole reason why I’m frustrated with it. :wink:

Regards,

Craig.

The Hugo equivalent would be shortcodes. Here’s an example of wrapping text in <span> and adding a warning class:

Markdown:

{{< foo "warning" >}}This _word_ is emphasized.{{< /foo >}}

layouts/shortcodes/foo.html

{{- $inner := .Inner -}}
{{- with .Get 0 -}}
  <span class="{{ . }}">{{ $inner | $.Page.RenderString }}</span>
{{- else -}}
  {{ errorf "The '%s' shortcode requires one positional attribute, a CSS class. See %s" .Name .Position }}
{{- end -}}

Rendered HTML:

<span class="warning">This <em>word</em> is emphasized.</span>
1 Like

Interesting. I had read a little on shortcodes but having a practical example related to this is really useful, thank you.

It’s much more verbose than the kramdown version but it is at least something that I could manually apply to the affected pages. Of course we’re using more than just this example, but I should be able to create a small number.

Thank you again Joe.

Regards,

Craig.

1 Like

This subtle issue also tripped me up.

The issue I have with the current implementation is that, if you accidentally use ‘content/foo/index.md’ where you intended a ‘content/foo/_index.md’, modifying ‘content/foo/bar.md’ will cause the hugo server you have running to just say ‘yep, I see that change and I made a new page’ which is arguably a lie. Best case would be to issue a warning with this link so that you know what you did wrong.

Eleventy aka 11ty is your friend :grinning: