[SOLVED] How to do sub-directories under sections content organization?

I am trying to figure out how this works. I don’t fully understand the function of _index.html and how it relates to a list template and all that.

Would someone be kind enough to explain this?

I find most of my time in Hugo is spent trying to figure out elementary things and for people who really are terrible in English, it would be a great help if the documentation actual included samples. It assumes people understand a lot of things beforehand, and maybe I don’t. Golang is cool. This template syntax still eludes me, haha. :smiley:

Over half the day once, spent just on trying to figure how to combine if, where, and range together in this confusing template language. That was a blast! LOL.

Anyway, thanks. If it wasn’t for copious amounts of Cannabis consumption, I’d have lost my mind already. :smiley:

I wanted to have multiple authors on my site, one author per article, or multiple authors per article, all sorted out in their physical directories on disk, like, site.com/authors/hash-borgir/ is /content/authors/hash-borgir/

or /content/coding/web/hugo/tutorials/ (something ridiculously long), and you want to have it generate an index file at each depth level, /coding/index.html, /coding/web/index.html, /coding/web/hugo/index.html, /coding/web/hugo/tutorials/index.html

Does that make sense?

@Hash_Borgir

Have you read this?

https://hugodocs.info/content-management/organization/#index-pages-index-md

I am not understanding the purpose of this _index.md file even though it is clearly stated in there.

List template can already get .Params (from page front matter).

I don’t understand the point or purpose for how or why this would be useful to my situation as you suggested. :slightly_smiling:

yes, from the pages being listed, but what about if you want to include content or metadata for the list page itself…

That’s why it’s _index.md…because it’s where you set the content and front matter specific to, for example, yoursite.com/posts/index.html (a list of all your posts). What if you want to put content above the lists of posts:

{{define "main"}}
{{.Content}}
<ul class="my-posts">
    {{ range .Data.Pages }}
    <li>{{.Title}}</li>
    {{ end }}
{{end}}

In the above example, {{.Content}} would pull from the content/posts/_index.md.

1 Like

Interesting.

So I would create

/content/authors/hash-borgir/ | /joe-shmoe/ - section directory under /content
/layouts/section/authors.html - list template to go along with this section

/content/authors/_index.md - would have the following content:

+++ some_frontmatter_for_authors_section_list = "something" +++

And /layouts/section/authors.html would then be able to have access to this frontmatter variable? If so, how would this be referenced? .Data.Pages.Params?

EDIT: Since I see you use .Content, I’m guessing it would just be available like normal Page nodes?

Have I understood this correctly? Can you provide further example?

I can’t answer this in the way you’ve asked it because you’re treating authors like regular content pages, and you said you created these as taxonomies, correct?

[taxonomies]
    author="authors"
    tag = "tags"
    category = "categories"

I defined authors taxonomy, otherwise (If I comment out the author=authors taxonomy) site.com/authors/hash-borgir/ or site.com/authors/joe-shmoe/ are 404, and site.com/authors works.

(Side note: It seems that when you define taxonomies, you have to define all of them in config.toml. You can’t just say
[taxonomies] author="authors"
because then /tags/ and /categories/ stop to function. Just something I wanted to note, as one should be able to just define taxonomies apart from the default Hugo ones, or does defining [taxonomies] in config.toml override the default ones?)

authors is definitely a section, as it is under /content/ and has subdirectories under it for author organization, but it’s also defined as a taxonomy, otherwise multiple authors under the authors section don’t work.

What if it’s not authors, what is it’s any arbitrary section with subdirectories under it for an organization? What if it was site.com/animals/dog and site.com/animals/cat , and animals is a section, but you also want it as a taxonomy?

Because it seems that when site.com/anything/ (/content/anything/) is not defined as a taxonomy, the subdirectory organization fails to render.

I read the docs on an organization since a few months ago, and again for the past few days. :slightly_smiling:

So, authors is a section, as well a taxonomy (site.com/authors), under which there are TERMS (sub-directories), which I define in front-matter of articles as authors="hash-borgir".

The front matter of all articles contains

author="hash" <-- this maps to .Site.Params.authors.hash authors="hash-borigr" <- this maps to the /content/hash-borgir/ subdirectory on filesystem

This is the only way I have been able to get multiple authors to work as subdirectories.

This way I can have each of the authors articles in their own named directory.

author=“hash” contains a variable named “name” whose value is “Hash Borgir” which is what authors=“hash-borgir” (name turned into slug) maps to the directory name.

This quoted part I don’t understand how Hugo is doing.

type="article" author="hash" authors="hash-borgir" featured="true"

{{$author := index .Site.Params.authors (.Params.author)}}

I grab the author from page front matter, which is “hash”, which then is used to index .Site.Params.authors array, which has hash or many other authors. It finds the author which is defined in front matter, from the config toml list, and then from there, I can display author profile bits, like name, twitter, email, bio, etc. etc.

<h4>Author: <a href="{{.Site.BaseURL}}authors/{{$author.name |urlize}}">{{$author.display_name}}</a></h4>

I’m just now trying to figure out how _index.html relates to my configuration. :slightly_smiling:

It seems that if I create/layout/section/authors.html and /content/authors/_index.html, that I should be able to render a custom list page at site.com/authors.

What if I wanted to make a custom list page for each author (/content/authors/hash-borgir/)

Would I then create /content/authors/hash-borgir/_index.md and /layouts/section/authors/hash-borgir/list.html?

Basically, “authors” is a section and a taxonomy, and all of the authors themselves are taxonomy terms.

/content/news/ - where all the articles by author=hash reside.

/content/authors/someone-else/ - subdirectories under /author/ for each author, to hold their articles.

/content/authors/hash-borgir/ does not physically exist on file system but is a taxonomy and term.

site.com/authors/ is now a taxonomy.

site.com/authors/hash-borgir/ (/content/news/) is a taxonomy term for taxonomy “authors”

site.com/authors/ (/content/authors/) is a taxonomy, and site.com/authors/someone-else/ (/content/authors/someone-else/) is the TERM under this taxonomy.

site.com/news/ is a section where all my news articles live, written by me for the main site.
all the articles in this section are written by authors=hash-borgir, so site.com/authors/ taxonomy shows the TERM “hash-borgir”.

Does this make sense?

I hope this makes sense.

What are the new upcoming Author features you were talking about?

Probably one of these: #3088 and #1850

I don’t follow this. I would recommend the following:

  1. Make authors a section OR
  2. Make authors a taxonomy

But don’t mix the two. You don’t really need to anymore with _index.md. Maybe it’s best to ask why you want to put yourself as a taxonomy term but have everyone as content files in a section.

This doesn’t really make sense.

But don’t worry; I’m sure we can figure out an easier way for you to manage this :smile:

With enough Cannabis, anything is possible.

I just learned a lot more. :slightly_smiling:

 stoned@stoned-desktop:~/media/websites/psychedelicsdaily.com/content$ find .
.
./contact.md
./news
./news/authors
./news/authors/hash-borgir
./news/authors/hash-borgir/Psychedelics-Are-Deeply-Linked-With-The-Human-Condition.md
./news/authors/hash-borgir/Doctors-Are-Using-Psychedelics-To-Treat-Mental-Illness.md
./news/authors/hash-borgir/MDMA-Assisted-Psychotherapy-Explained-by-Rick-Dublin.md
./news/authors/guest-writer
./news/authors/guest-writer/Test.md

OR

stoned@stoned-desktop:~/media/websites/psychedelicsdaily.com/content$ find .
.
./contact.md
./news
./news/authors
./news/authors/hash
./news/authors/hash/Psychedelics-Are-Deeply-Linked-With-The-Human-Condition.md
./news/authors/hash/Doctors-Are-Using-Psychedelics-To-Treat-Mental-Illness.md
./news/authors/hash/MDMA-Assisted-Psychotherapy-Explained-by-Rick-Dublin.md
./news/authors/guest
./news/authors/guest/Test.md

So I have learned that under my SECTION, I can organize the folders in any manner I want, and it they are rendered at site.com/SECTION/article-slug-here (even if the physical location is /content/SECTION/some-dir/ or /content/SECTION/some-dir/some-other-dir/even-deeper-nesting/and-even-deeper/nesting/here/). Which is beautiful! Just what I wanted. I can now organize my author’s articles in /news/ SECTION.

Now, I’m organizing everything in the news section and created authors as a taxonomy

Every article front matter contains:

+++
author = "guest"
authors = "guest-writer-sample"
...
...
+++

Where this author (.Params.author) maps to .Site.Params.authors.[$author] as this is used to fetch the author

And where this authors (.Params.authors) is my taxonomy. So now, all articles show up under /news/, and guest author’s articles will be listed under /authors/guest-writer-sample/ or whatever authors=""

So far, so good. Smoke more Cannabis, and now we type more.

Now, I have this. I am defining author= and authors= in front matter of articles. One is used to pull profile data from .Site.Params.authors and the other is a taxonomy.

I wonder how I can make it so that I just have to specify .Params.author (which maps to .Site.Params.authors array, in which there is a key(array) called .Params.author which has all the author profile data as follows:

[params.authors.guest]
    name = "Guest Writer"
    first_name          = "Guest"
    lst_name         = "Writer"
    display_name        = "Guest H. Writer"

    bio = "Guest profile has no bio."
    short_bio     = "Guest profile short bio."
    long_bio      = "Guest profile long bio is very long and boring."

    location = "Colorado, USA"
    email = "guest@guest.com"

    image = "/images/authors/Guest/Manbrown2.png"


    website         = ""
    github          = ""
    facebook        = ""
    twitter         = ""
    googleplus      = ""
    pinterest       = ""
    instagram       = ""
    youtube         = ""
    linkedin        = ""
    skype           = ""

How can I make it so that when Hugo creates a taxonomy for authors, it takes the .Site.Params.authors.guest.name and uses that as my taxonomy name, so I don’t have to specify authors= taxonomy.

This way, I can specify author=“guest” in my front matter, just this, and not authors=“guest-writer-taxonomy-here”, and whatever the value for author=“guest”'s name is from .Site.Params.authors.guest.name, that value is used as the taxonomy name.

So for user .Site.Params.authors.guest, if the .Site.Params.authors.guest.name defined in config.toml is “donkeys are fun”, I want this to be my taxonomy name.

If this is not possible, that’s fine.

I hope this makes more sense. :slightly_smiling:

EDIT: I no longer have /content/authors SECTION any longer, becuase now I understand more the organization. The documentation still lacks in areas where my English sucks, and I hope to be able to contribue to the docs so that they are more explanatory.

EDIT: I no longer have to fix my RSS feeds, b/c the whole confusion w/ SECTION and taxonomy is fixed. One last thing I have to do is clean the duplicated code inside my default list template.

Currently the contents are as follows:

{{ $baseurl := .Site.BaseURL }}

<!DOCTYPE html>
<html lang="en">

  {{ partial "head.html" . }}

  <body>

    <div id="all">

        <header>

          {{ partial "nav.html" . }}

        </header>

        {{ partial "breadcrumbs.html" . }}

        <div id="content">
            <div class="container">
                <div class="row">
                    <!-- *** LEFT COLUMN *** -->

                    <div class="col-md-9" id="blog-listing-medium">
{{ if ne .Kind "taxonomy" }}
{{ $paginator := .Paginate (where .Site.Pages "Type" "article") }}
{{ range $paginator.Pages }}

                        <section class="post shadow box">
                            <div class="row">
                                <div class="col-md-4">
                                  <div class="image shadow">
                                      <a href="{{ .Permalink }}">
                                          {{ if .Params.banner }}
                                          <img src="{{ .Site.BaseURL}}{{ .Params.banner }}" class="img-responsive" alt="">
                                          {{ else }}
                                          <img src="{{ .Site.BaseURL}}img/placeholder.png" class="img-responsive" alt="">
                                          {{ end }}
                                      </a>
                                  </div>
                                </div>
                                {{$author := index .Site.Params.authors (.Params.author) }}
                                <div class="col-md-8 post-meta">
                                    <h2><a href="{{ .Permalink }}">{{ .Title }}</a></h2>
                                    <div class="clearfix">
                                        <p class="author-category">
                                          {{ if isset .Params "author" }}
                                          <a class="" href="{{$baseurl}}authors/{{ .Params.authors | urlize }}/"><i class="fa fa-user" aria-hidden="true"></i>{{$author.display_name}}</a>
                                          {{ end }}

                                        {{ range $index, $tag := .Params.tags }}
                                        <a class="" href="{{$baseurl}}tags/{{ $tag | urlize }}/"><i class="fa fa-hashtag" aria-hidden="true"></i>{{ $tag }}</a>,
                                        {{ end }}

                                          {{ if isset .Params "categories" }}
                                          {{ if gt (len .Params.categories) 0 }}
                                          <a href="{{ $.Site.BaseURL }}categories/{{ index .Params.categories 0 | urlize | lower }}"><i class="fa fa-folder" aria-hidden="true"></i>{{ index .Params.categories 0 }}</a>
                                          {{ end }}
                                          {{ end }}

                                        </p>
                                        <p class="date-comments">
                                            <a href="{{ .Permalink }}"><i class="fa fa-clock-o"></i> {{ .Date.Format .Site.Params.date_format }}</a>
                                        </p>
                                    </div>
                                    <p class="intro">{{ slicestr .Summary 0 200 | markdownify}}...</p>
                                    <p class="read-more"><a href="{{ .Permalink }}" class="btn btn-template-main shadow"><i class="fa fa-list-alt" aria-hidden="true"></i> {{ i18n "continueReading" }}</a>
                                    </p>
                                </div>
                            </div>
                        </section>
                        {{ end }}
{{ else }}
{{ $paginator := .Paginate .Data.Pages}}
{{ range $paginator.Pages }}

                        <section class="post shadow">
                            <div class="row">
                                <div class="col-md-4">
                                  <div class="image shadow">
                                      <a href="{{ .Permalink }}">
                                          {{ if .Params.banner }}
                                          <img src="{{ .Site.BaseURL}}{{ .Params.banner }}" class="img-responsive" alt="">
                                          {{ else }}
                                          <img src="{{ .Site.BaseURL}}img/placeholder.png" class="img-responsive" alt="">
                                          {{ end }}
                                      </a>
                                  </div>
                                </div>
                                {{$author := index .Site.Params.authors (.Params.author) }}
                                <div class="col-md-8 post-meta">
                                    <h2><a href="{{ .Permalink }}">{{ .Title }}</a></h2>
                                    <div class="clearfix">
                                        <p class="author-category">
                                          {{ if isset .Params "author" }}
                                          <a class="" href="{{$baseurl}}authors/{{ .Params.authors | urlize }}/"><i class="fa fa-user" aria-hidden="true"></i>{{$author.display_name}}</a>
                                          {{ end }}

                                        {{ range $index, $tag := .Params.tags }}
                                        <a class="" href="{{$baseurl}}tags/{{ $tag | urlize }}/"><i class="fa fa-hashtag" aria-hidden="true"></i>{{ $tag }}</a>,
                                        {{ end }}

                                          {{ if isset .Params "categories" }}
                                          {{ if gt (len .Params.categories) 0 }}
                                          <a href="{{ $.Site.BaseURL }}categories/{{ index .Params.categories 0 | urlize | lower }}"><i class="fa fa-folder" aria-hidden="true"></i>{{ index .Params.categories 0 }}</a>
                                          {{ end }}
                                          {{ end }}

                                        </p>
                                        <p class="date-comments">
                                            <a href="{{ .Permalink }}"><i class="fa fa-clock-o"></i> {{ .Date.Format .Site.Params.date_format }}</a>
                                        </p>
                                    </div>
                                    <p class="intro">{{ slicestr .Summary 0 200 | markdownify}}...</p>
                                    <p class="read-more"><a href="{{ .Permalink }}" class="btn btn-template-main shadow"><i class="fa fa-list-alt" aria-hidden="true"></i> {{ i18n "continueReading" }}</a>
                                    </p>
                                </div>
                            </div>
                        </section>
                        {{ end }}
{{ end }}
                        <ul class="pager">
                            {{ if .Paginator.HasPrev }}
                            <li class="previous"><a href="{{ .Site.BaseURL }}{{ .Paginator.Prev.URL }}">&larr; Newer</a></li>
                            {{ else }}
                            <li class="previous disabled"><a href="#">&larr; Newer</a></li>
                            {{ end }}

                            {{ if .Paginator.HasNext }}
                            <li class="next"><a href="{{ .Site.BaseURL }}{{ .Paginator.Next.URL }}">Older &rarr;</a></li>
                            {{ else }}
                            <li class="next disabled"><a href="#">Older &rarr;</a></li>
                            {{ end }}
                        </ul>
                    </div>
                    <!-- /.col-md-9 -->

                    <!-- *** LEFT COLUMN END *** -->

                    <!-- *** RIGHT COLUMN ***
       _________________________________________________________ -->

                    <div class="col-md-3">

                        <!-- *** MENUS AND WIDGETS *** -->

                        {{ partial "sidebar.html" . }}

                        <!-- *** MENUS AND FILTERS END *** -->

                    </div>
                    <!-- /.col-md-3 -->

                    <!-- *** RIGHT COLUMN END *** -->

                </div>
                <!-- /.row -->
            </div>
            <!-- /.container -->
        </div>
        <!-- /#content -->

        {{ partial "footer.html" . }}

    </div>
    <!-- /#all -->

    {{ partial "scripts.html" . }}

  </body>
</html>

So as you can see,

{{ if ne .Kind "taxonomy" }}
{{ $paginator := .Paginate (where .Site.Pages "Type" "article") }}
{{ range $paginator.Pages }}
{{ else }}
{{ $paginator := .Paginate .Data.Pages}}
{{ range $paginator.Pages }}
{{ end }}

What I was doing was this: If the page being rendered is not a taxonomy, fetch all the articles with front matter type=“article”, else just fetch all the pages for this node, whatever it maybe.

The reason I was doing this, is because if you remember I had two sections, /news/ and /authors/ - and the template I used hash /content/contact.md which is a single page.

If call .Site.Pages to get all the pages from the site, contact.md (which no front matter) is also rendered and breaks the rendering of the site. The reason why I used .Site.Pages was to grab all the pages from both/all sections. I realized this was also fetching content/contact.md so I decided to put type=article in every front matter, and decided to filter by that type, so contact.md won’t show up and break the site.

Well, this was well and good, until I went to site.com/taxonomy/ and nothing was listed. So I learned, I’d have to get the .Data.Pages for this node, so I had to duplicate the list template code, and depending on whether it was a taxonomy page or not, either display the type filtered articles, or all the Pages for that node/section etc.

Now that I understand a lot more, I can de-dupe my code, and in the list template, only show .Data.Pages, which would then fetch all the pages from /news/ (the only section on the site so far).

(As I need to add more sections, what would be the right way to fetch pages from ALL sections, MINUS the /contents/contact.md (which does not belong to any section). I could create a section called /contact/ and put the contact.md page there, and then pull .Site.Pages (and give contact.md front matter like the rest of the articles).

Anyway, the more Cannabis I consume, the smarter I become. :smile:

Thank you for your support and time.

I’m glad you are getting it, and yes, the sections are pretty handy once we get used to them.

I’m saying this just to prevent you further confusion down the road, but this is not a taxonomy. Taxonomies are different and have a specific meaning in Hugo:

https://hugodocs.info/content-management/taxonomies/

I think I failed to elaborate correctly.

Front matter:
+++
authors=“guest-writer”
+++

config.toml
[taxonomies]
author=“authors”

And now “authors” is a taxonomy. And pages are rendered at site.com/authors/whatever-value-I-specified-for-authors-frontmatter-variable (which is essentially .Params.authors)

Example:
authors=“guest-writer” -> site.com/authors/guest-writer/
authors=“guest-writer-sample” -> site.com/authors/guest-writer-sample/

1 Like

Glad you got it worked out @Hash_Borgir. Please let me know if you have any suggestions on how to improve the docs. Cheers!

1 Like

I made an edit on my previous post, asking a question. Not sure if you saw that.

What would be the right way to fetch pages from ALL sections, MINUS the /contents/contact.md (which does not belong to any section)?

{{ range where .Site.RegularPages "Section" "!=" "" }}
All your code here...
{{ end }}

Assuming that contact.md is the only content file you have at the root…

{{ $posts := .Paginate (where .Pages "Section" "!=" "") }}

I see. I was having trouble w/ the comparison operators. I didn’t know that they had to be quoted as well. Thanks! :slightly_smiling:

1 Like