Hugo Templating Tricks of the Version 0.54 Variety

So, you use Micro.blog to generate your static site. You totally embraced Hugo templating, even rolled your own custom theme for @manton’s server to push all your content through whenever your static site regenerates. Now you’re looking to refactor your bits and pieces into plugins, perhaps considering plugin creation when pondering the insertion of new functionality. Wait … just me? F$&k it … play along.

Soooo, you’re totally aware that for any plugins installed by a user via the Micro.blog design interface, three things are true:

  1. Any CSS stylesheets properly specified by installed plugins shall be made available to your custom theme via $.Site.Params.plugin\_css. Hence, the responsible theme oughta fetch these references to link within the page head along with the theme’s stylesheets.
  2. Any static Javascript files properly specified by installed plugins shall be made available to your custom theme via $.Site.Params.plugin\_js. Hence, the responsible theme oughta inject these scripts so that any installed plugins may properly function. We all agree these scripts oughta wait for the page to load before running. This makes just before the close of body (perhaps after a footer) the logical point of injection for these scripts.
  3. Any Hugo partials required by installed plugins shall be made available to your custom them via $.Site.Params.plugin\_html. Hence, the responsible theme oughta call these partials (passing $) so that installed plugins can generate the HTML they require to function. The logical point of injection for the HTML generated by these Hugo templates is … wait … the whole page is HTML … how do we know where the plugin’s HTML is meant to be injected? I mean, usually we’re dealing with meta, which makes anywhere in the page head perfectly appropriate. What about everything else?

“Like what?,” you ask.

Well, okay, say you stumbled across Twitter conversion tracking and were like … f$&k it … let’s see what happens. You’re already set on plugin creation. This means you’ll want to parameterize the non-cookie-cutter bits of the script Twitter tosses at you:

Easy-peasy … @manton prepared for just such an occasion … so long as the plugin does an adequate job declaring these parameters in its plugin.json file,

our plugin may receive directly from its installer the values the installer wishes to set for these parameters.

Boom! How ya like me know?

So, let’s just finish looking at Twitter’s (finger-air-quote-voice) “installation instructions” and we’ll be all set. Plugin done … b$tches.

Wait. Does that say place the code snippet down at the bottom of our page where we inject all our static Javascript? WTF? What happens if I don’t? I mean, if the plugin didn’t require configuration upon installation, we would have simply created a static file in the first place. We require the partial to receive the proper parameter values. This means we land in plugins\_html, which gets dumped into the page head. F$&k it … debugging is a b$tch so let’s just find a way to make it work.

So, we’ve settled on the code for our Twitter Analytics plugin, and, if you looked closely at its configuration above, you may have noticed how we made this sh$t happen. When our custom theme asking for $.Site.Params.plugin\_html, all we are dealing with is a list of the values provided by all installed plugins in the includes array that end with html. They only need to point to proper Hugo template files should you wish your site to properly compile. What if we encoded our preferred plugin generated html location within this include value and made our theme smart enough to look for it?

Say we have a partial just for handling plugin-related injection into our page head, something kinda like:

Then, when we do want to invoke the plugin partial … say somewhere below-footerish … all we need is something like:

Cool beans. I wonder what all we are meant to do with this Twitter universal web tag. Wait … what’s this about a (finger-air-quote-voice-redux) “Google Tag Manager?”

F$&k it … we’re building plugins this morning … let’s do this thing. We already extracted and refactored into plugins for Plausible Analytics and Google Analytics. We just doubled the size of our list of possible injection sites for our custom theme. Easy-f$&kin’-peasy.

Okay, Google … WTF do you need from me?

Let’s see, a script. Saw that sh$t comin’. Looks like all we need to parameterize is some “container ID” value.

Alrighty then. Looks like we have one more thing Google wants us to inject, and it reuses the same parameter. We oughta be good to go.

Let’s just double-check where these bits go and … okay … so the first one goes…

F$&k me. We need this code to be up higher than our regular page head injected code? F$&k you Google. I’m almost afraid to look at where the other bit…

Oh, come on! Immediately after we open the page body, huh? F$&k it … I’m invested … let’s make the sh$t work … again.

So … what we need is for our custom theme to handle additional injection locations. We best just make an official list somewhere of what our theme will actually parse and handle … config.json oughta work. So … blah, blah, blah … supported\_plugin\_html\_prefixes

We’ll make sure our plugin declares its includes using the same prefix (with a dot separator):

Let’s grab that iframe nonsense meant to go (finger-air-quote-voice-of-reader’s-choice) “just after the opening tag for the page body” and make sure our theme injects it. How about in the partial we have for generating the navigation header for all our pages?

Alright, now let’s prioritize the injection of that other MF at the top of the page head by calling this little partial just after the opening tag for the page head:

So close now. We just need to make sure we aren’t injecting these prefixed files where we inject the regular old files. Let’s replace the code we had filtering out “BELOW_FOOTER” with code that filters out all the prefixes our theme supports:

Then you have yourself a plugin for Google Tag Manager and your custom theme totally supports it (I think … y’all know this sh$t doesn’t hold my attention long enough to poke and prod this sh$t).