# Lists of content divided by posts' first letter

**URL:** <https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534>\
**Category:** support\
**Created:** [September 27, 2017, 7:44am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534 "2017-09-27T07:44:29Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![khabaroff](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/khabaroff/32/2512_2.png) [@khabaroff](https://discourse.gohugo.io/u/khabaroff)\
**Post date:** [September 27, 2017, 7:44am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/1 "2017-09-27T07:44:29Z")

</div>

Hey,

I need to make a list of posts divided as this:

A  
— A true Story  
— Another Story  
…

B  
— Become a writer  
— Born Wild  
…

There is no need to add new taxonomy such as “first letter” because I need just to cut first letter. How can I make such nested list?

---

<div class="post-metadata">

**Author:** ![digitalcraftsman](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/digitalcraftsman/32/4142_2.png) [@digitalcraftsman](https://discourse.gohugo.io/u/digitalcraftsman)\
**Post date:** [September 27, 2017, 5:08pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/2 "2017-09-27T17:08:41Z")

</div>

Hello @khabaroff

it took me a while to get the snippet working. I assume that all your content files have a non-empty string as title. Otherwise you might get an error message due to `$firstChar`.

I’ve annotated each step of the template logic so it’s easier understand and to modify the snippet:

```auto
<!-- create a list with all uppercase letters -->
{{ $letters := split "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "" }}

<!-- range all pages sorted by their title -->
{{ range .Data.Pages.ByTitle }}
  <!-- get the first character of each title. Assumes that the title is never empty! -->
  {{ $firstChar := substr .Title 0 1 | upper }}
 
  <!-- in case $firstChar is a letter -->
  {{ if $firstChar | in $letters }}
    <!-- get the current letter -->
    {{ $curLetter := $.Scratch.Get "curLetter" }}
    <!-- if $curLetter isn't set or the letter has changed -->
    {{ if ne $firstChar $curLetter }}
    <!-- update the current letter and print it -->
      {{ $.Scratch.Set "curLetter" $firstChar }}
      <h3>{{ $firstChar }}</h3>
    {{ end }}

   -- {{ .Title }}<br>
  {{ end }}
{{ end }} 

```

At the end it looks like this:

 ![alpha](https://canada1.discourse-cdn.com/flex036/uploads/gohugo/original/2X/d/d9318c3ac667d893879c3b43214fdbac2015ded3.png)

Have fun!

---

<div class="post-metadata">

**Author:** ![rdyar](https://avatars.discourse-cdn.com/v4/letter/r/6bbea6/32.png) [@rdyar](https://discourse.gohugo.io/u/rdyar)\
**Post date:** [September 28, 2017, 12:14am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/3 "2017-09-28T00:14:59Z")

</div>

That is a great example, thanks for the mini tutorial.

I have a question - it looks like you are creating custom variables - with $letters and $firstChar? I don’t see anything in the docs pertaining to what those are, all I found was Scratch. What are the `$letters :=` type things and what is the difference between them and Scratch?

---

<div class="post-metadata">

**Author:** ![FelicianoTech](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/felicianotech/32/22886_2.png) [@FelicianoTech](https://discourse.gohugo.io/u/FelicianoTech)\
**Post date:** [September 28, 2017, 1:08am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/4 "2017-09-28T01:08:37Z")

</div>

@digitalcraftsman Very nice, what a great example. Thanks for taking the time to make it.

> [@rdyar](#):
>
> What are the $letters := type things and what is the difference between them and Scratch?

Correct, that is creating variables. Those variables would only be available within the content of that snippet where as with Scratch, they’d exists throughout the Hugo build (so you could use them in other templates for example).

The variables themselves are a thing of Go Templates: [template package - text/template - Go Packages](https://golang.org/pkg/text/template/#hdr-Variables)

---

<div class="post-metadata">

**Author:** ![rdyar](https://avatars.discourse-cdn.com/v4/letter/r/6bbea6/32.png) [@rdyar](https://discourse.gohugo.io/u/rdyar)\
**Post date:** [September 28, 2017, 1:21am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/5 "2017-09-28T01:21:05Z")

</div>

ok, good to know, I thought Scratch was only within the snippet.

So why then does his example include scratch as well as a regular variable? is there something limiting about the other variable that the whole thing could not be done with it?

Rather than `{{ $.Scratch.Set "curLetter" $firstChar }}` could it be `{{ "curLetter" = $firstChar }}`?

---

<div class="post-metadata">

**Author:** ![FelicianoTech](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/felicianotech/32/22886_2.png) [@FelicianoTech](https://discourse.gohugo.io/u/FelicianoTech)\
**Post date:** [September 28, 2017, 1:30am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/6 "2017-09-28T01:30:33Z")

</div>

Maybe I’m misunderstanding myself.

---

<div class="post-metadata">

**Author:** ![khabaroff](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/khabaroff/32/2512_2.png) [@khabaroff](https://discourse.gohugo.io/u/khabaroff)\
**Post date:** [September 28, 2017, 11:28am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/7 "2017-09-28T11:28:37Z")

</div>

That’s great! Thank you!

The thing is, that .Data.Pages.ByTitle gives 0 results, may be because as i’m searching posts on page template. And .Site.Pages.ByTitle gives tags pages that I don’t need. I did non figured out how to get all posts inside page template ☹

---

<div class="post-metadata">

**Author:** ![digitalcraftsman](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/digitalcraftsman/32/4142_2.png) [@digitalcraftsman](https://discourse.gohugo.io/u/digitalcraftsman)\
**Post date:** [September 28, 2017, 12:09pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/8 "2017-09-28T12:09:56Z")

</div>

> [@rdyar](#):
>
> So why then does his example include scratch as well as a regular variable? is there something limiting about the other variable that the whole thing could not be done with it?

I added the variable `$firstChar` simply for better readability and to keep the code [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) since it’s used in multiple places.

`.Scratch` is used to store the current letter beyond an iteration. An alternative approach would be to use a variable outside the loop, similar to `$letters`. However, as far as I know it’s not possible to reassign a variable in Go templates. Hence I had to use `.Scratch`.

---

<div class="post-metadata">

**Author:** ![digitalcraftsman](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/digitalcraftsman/32/4142_2.png) [@digitalcraftsman](https://discourse.gohugo.io/u/digitalcraftsman)\
**Post date:** [September 28, 2017, 12:13pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/9 "2017-09-28T12:13:06Z")

</div>

> [@khabaroff](#):
>
> And .Site.Pages.ByTitle gives tags pages that I don’t need.

To exclude them you could try to use `.Site.RegularPages` instead.

Do you’ve a repo to share? I guess it’s easier to fix this issue with the actual source files.

---

<div class="post-metadata">

**Author:** ![khabaroff](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/khabaroff/32/2512_2.png) [@khabaroff](https://discourse.gohugo.io/u/khabaroff)\
**Post date:** [September 28, 2017, 12:39pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/10 "2017-09-28T12:39:16Z")

</div>

Got it! Now I need to reuse code to solve this

My post have this structure  
Blondie — Parallel Lines (1978)  
Blackstreet — Blackstreet (1994)  
Big Black — Songs About Fucking (1987)

I cut year string (substr .Title -2 4) but I need to do sort then as something like  
{{ range sort .Site.RegularPages }}{{ substr .Title -2 4 }}  
correct?

Output: [https://khabaroff.com/1000/page/years/](https://khabaroff.com/1000/page/years/)

Here is repo

> <https://github.com/khabaroff/1000/blob/master/themes/hugo-theme-bleak/layouts/page/single.html>

---

<div class="post-metadata">

**Author:** ![rdyar](https://avatars.discourse-cdn.com/v4/letter/r/6bbea6/32.png) [@rdyar](https://discourse.gohugo.io/u/rdyar)\
**Post date:** [September 28, 2017, 5:01pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/11 "2017-09-28T17:01:58Z")

</div>

awesome, thanks for the explanation this has been a very helpful thread for me and I have no interest in the op’s idea, I just try to read everything in the hopes of finding little nuggets like this!

---

<div class="post-metadata">

**Author:** ![digitalcraftsman](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/digitalcraftsman/32/4142_2.png) [@digitalcraftsman](https://discourse.gohugo.io/u/digitalcraftsman)\
**Post date:** [September 30, 2017, 8:18pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/12 "2017-09-30T20:18:15Z")

</div>

In your example you want to sort your content based on the year (in the title) instead of displaying them in alphabetical order, what my snippet does.

I guess it’s easier to add a new front matter parameter , e.g. `year`, that contains the year from the title. This way you can group your content based on a parameter defined in the content.

[Here’s the corresponding example in the docs](https://gohugo.io/templates/lists#by-page-parameter):

```auto
{{ range .Data.Pages.GroupByParam "year" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
    <li>
      <a href="{{ .Permalink }}">{{ .Title }}</a>
    </li>
    {{ end }}
</ul>
{{ end }}

```

---

<div class="post-metadata">

**Author:** ![khabaroff](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/khabaroff/32/2512_2.png) [@khabaroff](https://discourse.gohugo.io/u/khabaroff)\
**Post date:** [September 30, 2017, 9:12pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/13 "2017-09-30T21:12:52Z")

</div>

Thank you,  
I just want to find solution without front matter 🙂

Get substring (1), sort (2) and group (3) (as in your example with alphabet order). First part seemed most tricky, but now I see that the most tricky is first part.

---

<div class="post-metadata">

**Author:** ![digitalcraftsman](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/digitalcraftsman/32/4142_2.png) [@digitalcraftsman](https://discourse.gohugo.io/u/digitalcraftsman)\
**Post date:** [October 1, 2017, 9:16am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/14 "2017-10-01T09:16:40Z")

</div>

Ordering pages based on a substring in the title is indeed tricky. At the moment I’m not sure how this can be done. 🤔

---

<div class="post-metadata">

**Author:** ![khabaroff](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/khabaroff/32/2512_2.png) [@khabaroff](https://discourse.gohugo.io/u/khabaroff)\
**Post date:** [October 2, 2017, 4:11pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/15 "2017-10-02T16:11:54Z")

</div>

Maybe there is a way  
to get all posts as array A  
to make additional array with substrings B  
make an ordered array with years (substrings) C

We search C[0] in B. If we get one, we get B element index i and then we print A[i]. Then go to next B element.

We search C[1] in B. If we get one, we get B element index i and then we print A[i]. Then go to next B element.

That might work, need to learn syntax =)

---

<div class="post-metadata">

**Author:** ![khabaroff](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/khabaroff/32/2512_2.png) [@khabaroff](https://discourse.gohugo.io/u/khabaroff)\
**Post date:** [October 12, 2017, 10:18pm UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/16 "2017-10-12T22:18:01Z")

</div>

Any ideas here? ☹

---

<div class="post-metadata">

**Author:** ![pointyfar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pointyfar/32/5797_2.png) [@pointyfar](https://discourse.gohugo.io/u/pointyfar)\
**Post date:** [October 12, 2020, 1:53am UTC](https://discourse.gohugo.io/t/lists-of-content-divided-by-posts-first-letter/8534/18 "2020-10-12T01:53:49Z")

</div>


