You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.8 KiB

draft title aliases series series_order date author cover summary showFullContent keywords tags
false Adding Series and Navigation links to Hugo page
Adding Series and Navigation links to Hugo page
blogging-with-quartz
3 2023-03-07 Nick Dumas Extending Quartz's single.html to link between posts. false
quartz
webdev
hugo
quartz
webdev
hugo

What am I Doing?

As I write more posts, I realize I'm writing groups of posts that are narratively linked, to speak. The best example is this series, Blogging with Quartz. There are others, but I'm still working on a system for cross-linking between posts. More on that later.

I also realized that there's simply no way to view anything but the most recent N posts on the index page. I've forgotten what the current value of N is but that's neither here nor there.

Users can't navigate free. The closest they can get is walking the tag graph and hoping that gets them somewhere.

Why does it work?

Quartz is great, looks awesome and uses Hugo which means its super configurable. The templates are powerful and very polarizing.

Why doesn't it work?

Quart's layout seems to be build around organize discovery of notes through hand crafted landing pages. For the blog, I'm not interested in that. I want users to be able to page through my posts backwards and forwards chronologically like any actual blog site.

Quartz has tags but it lacks a way of saying "These posts aren't chronologically adjacent but they form a sequence". It looks like most tools call this a "series" of posts, so that's what I went with.

Making it happen

Chronological Adjacency

Hugo helps us here by providing page variables specifically for this: Next and NextInSection. This partial ends up being really straightforward. It's also got a style, pagination that I'm going to leverage.

    {{partial "prev-next.html" .}}

Just a few if statements and calling .Permalink to get a URL. I chose to use the *InSection variants because I probably will be introducing more content types over time and I may as well fix this beforehand. Below is layouts/partials/prev-next.html

{{ if or .NextInSection .PrevInSection }}
<nav class="pagination">
    {{ if .PrevInSection }}
    <ol>
        <li>
            <a href="{{ .PrevInSection.Permalink }}">
                <span class="button__icon"></span>
                <span class="button__text">{{ .PrevInSection.Title }}</span>
            </a>
        </li>
        {{ end }}
        {{ if .NextInSection }}
        <li>
            <a href="{{ .NextInSection.Permalink }}">
                <span class="button__text">{{ .NextInSection.Title }}</span>
                <span class="button__icon"></span>
            </a>
        </li>
    </ol>
    {{ end }}
</nav>
{{ end }}

There's also a small block of custom CSS, necessary to reset some padding and make the links flow horizontally with a bit of a margin to keep them legible. Shown is a portion of asset/styles/custom.scss.

...
nav.pagination {
                border: 1px solid black;
                ol {
                        padding-inline-start: 0px; 
                }
                li {
                                margin: .25em;
                                display: inline-block;
                }
}
...

{{< figure src="prev-next-links-example.png" alt="Two links pointing to a post published before this one titled 'Ashes to Ashes, Buffs to Buffs', and one published later titled 'Never forget is_alert_recovery'" caption="Pretty snazzy, right?" >}}

Planning for the Future

Tags are cool, but they don't tell a story. My ambition vastly outstrips my talent and so no project I undertake will ever fit in a single post.

To that end, I put this together. I definitely got this from somewhere, but I can't remember where now. Sorry. Another very simple invocation.

    {{partial "series-header.html" . }}

This generates a short list linking to all the other posts in a given series.

{{- if .Params.series -}}
{{- with index (.GetTerms "series") 0 -}}
<div class="post-series notice--info">
        <h3 id="series">This post is part of the <a href="{{ .Permalink }}" style="font-weight: bold">{{ .LinkTitle }}</a> series.</h3>

    {{- end -}}
    {{- $series := where .Site.RegularPages.ByDate ".Params.series" "intersect" .Params.series -}}
    {{- with $series -}}
            <ol>
                {{- range . -}}
                <li>
                    {{- if eq .File.UniqueID $.File.UniqueID -}}
                    <b>{{ .Title }}</b>
                    {{- else -}}
                    <a href="{{ .Permalink }}">{{ .Title }}</a>
                    {{- end -}}
                </li>
                {{- end -}}
            </ol>
    {{- end -}}
</div>

{{- end -}}

notice--info just pulls a color from the base definitions. It ads a little visual pop.

...
.notice--info {
    @include notice(var(--primary));
}
...

{{< figure src="series-insert-example.png" alt="Screenshot of text on a website describing an article and its membership in a series called 'blogging-with-qurtz' " caption="You can even click the name to take you to a list of the rest of the posts in the series">}}

Webdev is tedious

I'd love to be able to test this locally. It only takes approximately thirty seconds from pushing a change to having a fresh build of the site, but that's still hella slow when you're trying to rapidly iterate on CSS and stuff.

I'm really happy with how this looks, though, and I'm excited to keep tweaking things. I've got 30 tabs open with Hugo templates and toolkits that I'm gonna rifle through and try to find inspiration in.