As of the writing of this post, it is quite difficult to find this blog … and by ‘difficult’ I mean you’re not gonna find it without the URL or a link. Obviously I want a bit more than that if I’m writing a blog. After all, if I only wanted to share all of this with my closest friends then I could already do that via Discord and the like.

So!

Search Engine Optimization (SEO) to the rescue! Time to add in those annoying but somewhat crucial details that the brainless robots used by search engines need to actually grok what a website is and what it contains. Maybe in time they’ll be smart enough, but we’re nowhere near that point just yet.

Adding Descriptions … the lazy way

So I noticed that I was missing some important meta tags, the first of which was the all-important description. So, let’s see how the m10c theme handles these.

 9<meta name="author" content="{{ .Site.Params.author | default "John Doe" }}" />
10<meta name="description" content="{{ if .IsHome }}{{ .Site.Params.description }}{{ else }}{{ .Description }}{{ end }}" />
11{{ $style := resources.Get "css/main.scss" | resources.ExecuteAsTemplate "css/main.scss" . | resources.ToCSS | resources.Minify | resources.Fingerprint -}}

Now let’s break down the logic so we can actually read it!

{{ if .IsHome }}
    {{ .Site.Params.description }}
{{ else }}
    {{ .Description }}
{{ end }}

So all this does is add an exception for the homepage. It does nothing for your blog posts, or any other posts, mind you. Now I don’t know about y’all, but I really can’t be bothered to write a tailor made description for every post. I mean from time to time, sure, I may want something specific, but the rest of the time what’s wrong with the summary I have shown on my homepage?

So lets fix that!

 9<meta name="author" content="{{ .Site.Params.author | default "John Doe" }}" />
10<meta name="description" content="{{ if .IsHome }}{{ .Site.Params.description }}{{ else if not .Description }}{{ .Summary | safeHTML | truncate 156 }}{{ else }}{{ .Description }}{{ end }}" />
11{{ $style := resources.Get "css/main.scss" | resources.ExecuteAsTemplate "css/main.scss" . | resources.ToCSS | resources.Minify | resources.Fingerprint -}}

Okay, this is even worse. Let’s break this one down as well.

{{ if .IsHome }}
    {{ .Site.Params.description }}
{{ else if not .Description }}
    {{ .Summary | safeHTML | truncate 156 }}
{{ else }}
    {{ .Description }}
{{ end }}

Here we just threw in one more conditional. If there isn’t a manually added .Description it’ll display the .Summary instead. And you’ll notice the addition of a few more things there for the automatic one. The first will make sure HTML tags are treated properly the the following function, with the latter doing exactly what it says as apparently the optimal length for this property (according to Google or somesuch) is 160. I set it to 156 so if it does truncate it’ll still have enough room for the ellipsis. I didn’t bother adding that for the manually specified ones as I figure if I’m putting them in there manually then I’m doing it right.

And there we go. SEO-ready descriptions for the lazy.

Adding Keywords … the lazy way

Next, on to keywords. These are also important, almost moreso than the all-important description, as the search engines use these keywords to help find your content. Add a keyword, say, for ’tacos’, and that’ll raise the chances that someone searching on Google or Bing (or whatever other search engine you use … but let’s face it, you’re probably just using Google) will find your page.

So, just like above, I went looking for how my theme handles keywords … and found it doesn’t add them at all! Not even if you manually specify it on your blog post! Now that just won’t do! And, as before, I wanted to do it as lazily as possible, so if I don’t specify them it’ll just borrow my tags. After all if those are good enough to find content on my site then it can be just as good to find it off my site. YMMV.

So, time to get creating … and sorry in advance, this one was a total bear to get working. Like, the way Hugo handles ‘Taxonomies’ … yeah, I’ve nothing flattering to say there. But, hey, I got it working, so feel free to steal this … I mean borrow, but w/e.

1<meta name="description" content="{{ if .IsHome }}{{ .Site.Params.description }}{{ else if not .Description }}{{ .Summary }}{{ else }}{{ .Description }}{{ end }}" />
2<meta name="keywords" content="{{ .Site.Params.author | default "John Doe" }},{{ if .IsHome }}{{ $data := newScratch }}{{ $data.Set "tags" ( slice "" ) }}{{ range $tag, $null := .Site.Taxonomies.tags }}{{ $data.Add "tags" $tag }}{{ end }}{{ delimit ( after 1 ( $data.Get "tags" ) ) "," }}{{ else if .Page.Keywords }}{{ .Page.Keywords }}{{ else if .Page.Params.Tags }}{{ with .Page.Params.tags }}{{ delimit . "," }}{{ end }}{{ end }}" />
3{{ $style := resources.Get "css/main.scss" | resources.ExecuteAsTemplate "css/main.scss" . | resources.ToCSS | resources.Minify | resources.Fingerprint -}}

Now if you can visually parse that without breaking it down then I congratulate you. Now for the rest of us peons, let’s take a closer look in a more civilized manner. And this one I’ll comment on, line by line, because I had to do some serious BS to get this to work.

{{ .Site.Params.author | default "John Doe" }},         // Let's add our name to everything!  It's all ours, after all

{{ if .IsHome }}                                        // Should be obvs / Main page only
    {{ $data := newScratch }}                           // Creating a temp variable for storing extracting tags
    {{ $data.Set "tags" ( slice "" ) }}                 // Initialize the variable as an array
    {{ range $tag, $null := .Site.Taxonomies.tags }}    // Iterate through the 'map' of tags
        {{ $data.Add "tags" $tag }}                     // Add the tags, one at a time, to the array
    {{ end }}
    {{ delimit ( after 1 ( $data.Get "tags" ) ) "," }}  // Remove the blank item that we needed to force the
                                                        // variable to be an array, then converts the array
                                                        // to a comma separated list

{{ else if .Page.Keywords }}                            // For if we want to manually specify.
    {{ .Page.Keywords }}

{{ else if .Page.Params.Tags }}                         // If none of the above, aka most of the time.  Because lazy.
    {{ with .Page.Params.tags }}                        // Basically shorthand to access this variable as '.'
        {{ delimit . "," }}                             // Convert list to a comma separated list
    {{ end }}
{{ end }}

Whew. That does a lot.

Now if you’re asking why so much work for the homepage, what I wanted to do there was to add a keyword for every single tag on my blog. It might be a bit excessive, but if I could drive people to not just the blog posts (and future articles/guides) but to the main page as well? Yeah, that’s the idea.

As for why it’s so convoluted? Well, that’s because of how Hugo stores tags. They fall within the concept of ‘Taxonomies’, which can also include things like categories or anything user-defined. Now if we access those tags in this manner, what it returns irritatingly has the tag, itself, as the ‘key’ rather than the ‘value’. The value, here, is the list of pages that the tag can be found in.

If any of you know a better or more elegant way to do this, feel free to chime in below. I really do love learning! And elegance!

Hugo and OpenGraph

Thankfully for me, Hugo itself has built-in support for OpenGraph that isn’t half bad, so I can leave most of that lifting up to that built-in template. It seems to mostly take care of itself. The only thing I was missing was a good preview image. Thankfully it seems that Hugo lifts that from the site params, or, in the case of a blog entry, the ‘front matter’ at the top of the blog post … defaulting to the site params if an individual blog post doesn’t contain one.

Now I don’t have any special image for this yet, but I don’t want it to be blank … so for now I’m using using my standard avatar. After all, that’s sorta my only real visual definer at the moment.

Hugo and Twitter

Seems that Hugo has built-in support for Twitter as well, but seeing as I don’t use Twitter, or even have one, I’m not going to even bother touching that.

And with that, the site should be ready to hit the front page … hopefully!

After all, who’s really checking out my GitHub page all that often?
Or Reddit? I haven’t really been posting there much lately, after all.