It's the little things in different browsers

Boxes in front of checkboxes
Labarum: Extra content in items
I hate it when a developer focuses so much on one browser (usually chrome) and doesn't test it in another browser. So, I feel like a hypocrit when I found out that my site renders the little box in front of the checkboxes[^checkboxes]. The funny thing is that I had originally seen this as an issue and had commented the code out.

The I thought I would keep it as a comment until I could figure it out and deploy it as a point update.

article ul > li::marker {
	/* content: "\2751"; */
}

The problem is that chrome doesn’t care that I had the individual line commented out and was attempting to put it there even though I told it not too.

I moved the comment to outside the item and I’ll let the broswer handle markers until I get a better understanding of how to target the different items.

Creating Labarum (Part 6): A Splash of Color

Labarum part6 light mode

I’m wrapping up this series. I’ve been playing with this theme for more than a year. Rarely consistent and not always forward progress but rewarding. I’m at a point where I’m very happy with how the theme looks.

This is what it looks like in dark mode.

Labarum part6 dark mode

Colo(u)rs

I wanted to use the Nord color scheme at the beginning of this project, but decided to use “basic” colors to simplify the design. I eventually grew to love the look of the page as the content was the star.

Later I found that some of the elements on the page don’t work well for those who are color blind and the starkness of having an all white background made me rethink whether the site would do well with long pieces.

I first came across the Nord color palette when I met Jessica Smith online using the micro.blog service.

Fonts

I did not want to use online fonts.

True, they can look really nice but I didn’t want to use bandwidth on something that could slow down the site or cannot guarantee to work in the coming years. In addition, there are privacy concerns when it comes to web fonts that I didn’t want to contribute to.

After a significant amount of time looking for accessible fonts that are all the major OSes, I went with Verdana for my main text font and Garamond for headers.

Figures

I decided that I wanted the items in a figure to take have the same effect as the articles but take the main background so that it would have a stacking effect.

Labarum figures light mode

Here are some pictures of what the figures looks like in dark mode.

Labarum figures dark mode

Tables

I typically don’t use tables in my writing, but I thought I should add a little bit of styling in case someone else feels the need.

Labarum table light mode

Here it is in and dark mode.

Labarum table dark mode

Tasks lists

This was the hardest part to solve because most of the Hugo themes do not address tasks lists. To be clear, these are static lists created by the writer and not something a reader is expected to interact with.

Labarum task list light mode

Dark mode for the task list.

Labarum table dark mode

Most themes will have something like the following code to remove the markers that show up in an unordered list.

/* task list and its checkboxes */
article ul > li:has(> input[type="checkbox"]) {
    list-style: none;
    margin-inline-start: -1rem;
}

article ul > li:has(> input[type="checkbox"])::before {
    content: "\200B"; /* accessibilty for Safari [developer.mozilla.org/en-US/doc...](https://developer.mozilla.org/en-US/docs/Web/CSS/list-style) */
}

Eventually, I found a wonderful example in the Hugo Relearn theme that was written about on Modern CSS applied it to what I had.

Reflection

I’m happy with the theme.

There are still somethings that I want to improve upon and I invite you all to comment and help me make it better in the future. I’ve also made a post on my test blog that should have a lot of examples of the theme in action.

Creating Labarum (Part 5): Schema and Open Graph

Websites are read by more than just human eyes. Browsers, search engines, screen readers, and more take the information being served to them about a site and use it for different purposes. I wanted to make sure that my site could be parsed properly so that it can be reached to everyone who wants it. The web has several technologies designed for this purpose that do not add too much more work to incorporate them. I focused on Schema and OpenGraph meta1 tags in the <head> element to achieve this. An excellent resource for learning about it can be found at HTML Head.

Preface

Hugo offers ways of doing this by having your template reference some internal templates. For example, the very popular template Ananke uses the following code to utilize these templates.

{{- template "_internal/opengraph.html" . -}}
{{- template "_internal/schema.html" . -}}
{{- template "_internal/twitter_cards.html" . -}}

At the beginning of this process, I found that including this would cause the site not to render on Micro.blog. That issue has since been resolved, but I kept with my code for my understanding and further customization.

The good thing about all of this is that Ananke has a link directly over the templates so that you can review the code yourself.

It can be found here: Embedded Templates

Another key difference is that the templates also have logic for a featured image. In most of my usage, I don’t have images and don’t know how to specify an image as featured in markdown. I’ll have to reevaluate this at a later date.

Heading Home

When creating a template for blog, you should be aware that not all tags that you would have for your articles apply to your main page.

I used a flag that Hugo provides to create a section in the header for the home page to keep tags that a specific t the landing page.

{{- if .IsHome -}}

For the individual articles, I’ll be checking the title property in to determine logic on what tags that will be used.

{{ if isset .Params "title" }}

When you read the article, you will see different times that I specified something and may think that I could have been more clever by writing it in a way where I don’t have to repeat myself. I did this for a few reasons.

  1. I’m learning how Hugo works with templates
  2. I find that clever code can be difficult to debug and understand (You can thank me later, future me)

Getting a head of the page

I wanted to start off with the <head> elements that Micro.blog uses before checking to see if there were other things that I needed to add for the website.

I like to look at the Marfa’s head partial because it’s the theme that Manton uses.

{{ "<!-- Micro.blog Values -->" | safeHTML }}
<link rel="shortcut icon" 
	href="https://micro.blog/{{ .Site.Author.username }}/favicon.png"
	type="image/x-icon" />
<link rel="me" href="https://micro.blog/{{ .Site.Author.username }}" />
<link rel="authorization_endpoint" href="https://micro.blog/indieauth/auth" />
<link rel="token_endpoint" href="https://micro.blog/indieauth/token" />
<link rel="micropub" href="https://micro.blog/micropub" />
<link rel="microsub" href="https://micro.blog/microsub" />
<link rel="webmention" href="https://micro.blog/webmention" />
<link rel="subscribe" href="https://micro.blog/users/follow" />
<link rel="canonical" href="{{ .Permalink }}" />	

A lot of the these values are specific to how Micro.blog and the open web respond to the site in general. Blogging software such as MarsEdit, will use this information to connect to your blog for editing. Webmentions are a way for different systems to communicate to regarding if the source content has been referenced somewhere else.

{{ if .RSSLink -}}
<link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" />
      <link href="{{ "podcast.xml" | absURL }}" rel="alternate" type="application/rss+xml" title="Podcast" />
      <link rel="alternate" type="application/json" title="{{ .Site.Title }}" href="{{ "feed.json" | absURL }}" />
      <link rel="EditURI" type="application/rsd+xml" href="{{ "rsd.xml" | absURL }}" />
    {{ end -}}

These allow for newsreaders and podcast aggregators to get the information needed to get information about updates. One cool thing is the use of a JSON feed that Manton helped build.

I also found a website dedicated to explaining a lot of the different tags that can be found in the <head> element.

Open examples

The first set of tags that I looked at were ones related to OpenGraph tags. These where the ones that a supported in social media (facebook, twitter, slack, etc.) and operating systems that I was using at the beginning of the project.

OpenGraph tags behave the same way as <title> and other tags in a web page. In fact, for some services, if an OpenGraph tag is not there, it will default to other tags in the head. For example, title or description. I decided to define the values for the tag to make sure that the site is compliant2.

The key difference between OpenGraph tags and the standard tags that you see in the <head> element of a website is that they are defined as <meta> tags. A tag would have a property and content definition that would follow a pattern shown below.

<meta property="PropertyName" content="PropertyString" />

In the examples that I have seen, they often duplicate some of the information that is already there. In most cases, you would see:

<title>Some Title</title>
<meta property="og:title"
  content="Some Title" />

This makes it fairly effortless to get most of the tags together with only a few complications with dates, images, and whether to support twitters extensions.

Dates

A long time ago, some smart people decided that there should be an international standard for representing dates. As of this writing, Hugo doesn’t automatically format the date to this standard.

{{ $iso8601 := "2006-01-02T15:04:05Z07:00" }}

This line defines a string that we can use to later format dates in other parts of the template.

{{- with .PublishDate }}
<meta property="article:published_time" {{ .Format $iso8601 | printf "content=%q" | safeHTMLAttr }} />
{{ end }}

Then when a page is rendered we can see the time and in which time zone.

<meta property="article:published_time" content="2023-03-23T16:50:58-07:00" />

Images

For the home page, we assume that the user wants to use their favicon for their image property.

<meta property="og:image" content="https://micro.blog/{{ .Site.Author.username }}/favicon.png" />

This works fine for home pages, but we want to provide more information for the articles that may have it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{{- with .Params.images -}}
{{ "<!-- .Params.images -->" | safeHTML }}
<meta name="twitter:card" content="summary_large_image" />
{{- range first 6 . }}
<meta property="og:image" content="{{ . | absURL }}" />
<meta itemprop="image" content="{{ . | absURL }}" />
{{- end -}}
{{- else -}}
{{ "<!-- $.Site.Params.images -->" | safeHTML }}
<meta property="og:image" content="https://micro.blog/{{ .Site.Author.username }}/favicon.png" />
<meta itemprop="image" content="https://micro.blog/{{ .Site.Author.username }}/favicon.png" />
<meta name="twitter:card" content="summary" />
{{- end -}}

The first line checks that images exist in the article.

Line 2 creates a comment in the rendered HTML.

Line 3 is specific to twitter makes the images bigger in the timeline.

Line 4 sets up loop over an array. The key words first 6 limits the loop and the . specifies the array as being the images defined in .Param.images.

Line 5 creates the line of html for that particular image we are on in the loop.

Line 8 starts our logic when there are no images attached to the article and defaults to giving the user profile picture.

Other media

Modern sites can also have audio and visual components as well.

{{- with .Params.audio }}{{ range . }}<meta property="og:audio" content="{{ . }}" />{{ end }}{{ end }}

The line looks at all the audio in the article and then adds the following property.

<meta property="og:audio" content="https://micro.blog/pages/downloads/661/1841919/750047.mp3" />

You can also do the same looping code to go over any video that you might have.

{{- with .Params.videos }}{{- range . }}
<meta property="og:video" content="{{ . | absURL }}" />
{{ end }}{{ end }}

And it will render correctly.

<meta property="og:video" content="https://mandarismoore.com/uploads/2021/793e8ba1bb.mp4" />

At the moment, I don’t have an examples of a system processing this information, but I’m happy knowing that it’s there.

The Twitter Question

As I was working on this, Twitter was acquired by Elon Musk. There were numerous layoffs and I honestly don’t know if I should put in the time to make sure that I support the twitter specific extensions to the OpenGraph specs. Ultimately, I added them in case someone uses this theme and shares the links on Twitter.

Micro.blog allows a user to add their twitter name and I used that to populate both twitter:site and twitter:creator.

1
2
3
4
5
{{ with .Site.Params.twitter_username }}
<link rel="me" href="https://twitter.com/{{ . }}" />
<meta name="twitter:site" content="@{{ . }}" />
<meta name="twitter:creator" content="@{{ . }}" />
{{ end }}

If the user doesn’t have a twitter username, this code will not be included during the rendering of the website.

Scheming

The key difference between OpenGraph and Schema tags is that they use different tags to represent the same information.

A schema meta tag will usually look like the following.

<meta itemprop="PropertyName" content="PropertyString" />

This is basically the same idea but implemented by different groups. When I first learned of Schema tags, I was told that it was used by search engines to parse information. When I attempted to verify this, half the tools used to check have been shutdown or made reference to using OpenGraph.

Still, I wanted to include them as the logic was already completed during my implementation of OpenGraph tags.

In addition to the meta tags, you will see the schema tags in the article itself.

For example, in the <span> tags of the article footers for the different dates and categories.

<span itemprop="articleSection">{{ $Category }}</span>

Currently, I’ve mixed in all the schema tags with the OpenGraph tags to make sure that I have parity between the two where it makes sense.

Evaluating

For open graph testing, I created a page on the test version of my site using the two following tools.

https://opengraphr.com/open-graph-debugger

https://www.opengraph.xyz/

Schema

I used https://validator.schema.org to test Schema.

Accessibility

I used https://wave.webaim.org to test for accessibility. I did get some alerts with the design because I had some video and audio tags but no transcripts. Another issue is the contrast that I used for the Permalinks on dates. I’ll work on that in a future release.

twitter

The twitter official validator is https://cards-dev.twitter.com/validator. NOTE Removed as of mid 2022. You have to post the link in the composer window of a tweet to see what it will look like.

Opportunities to grow

During the writing of this article, I found numerous ways that I can improve my theme. So much, that I had stopped development because I didn’t want the article and theme to become too separate from each other.

To continue with development without worrying about this, I’ve tagged the version of the code for the time that these steps of the article were created. You can find the link below.

Labarum 1.0.1

In the meantime, I’ll be cleaning up the code so that the Hugo Theme is easier for me to read and that the rendered output as well.

I tested the accessibility of the site, and it did have a decent score, but I’d really like to improve the fonts and colors.

You are welcome to follow this site or the Labarum category to see updates when this is updated. And you can always contact me here or via email!

Creating Labarum Part 1: Design and initialization

Creating Labarum Part 2: Creating the individual posts

Creating Labarum Part 3: Implementing post footer

Creating Labarum Part 4: Initiating the Index


  1. I don’t like the fact that Facebook changed it’s name to meta. ↩︎

  2. Meaning that all the tags are valid html tags. ↩︎

Simple Audio

Please ignore this if it is on the main site.

"Ted Lasso" returns for 3rd season -CBS News

Emmy-nominated actor Nick Mohammed joins "CBS Mornings" to discuss the third season of "Ted Lasso" and what we can expect from his character Nate Shelley.

I love this show! I’m really looking forward to the end of this season.

2023.02.28

Link to Original Document

If I’m going to be looking at new jobs, I need to have some way of tracking the jobs that I’ve applied for. I also need to track what house that I’ve look at so that I don’t stress myself out.

This is the document that I was working on at the coffee shop.

FreeformTesting.pdf

One less pool to play in

Swiming Pool

So, I’m sure that everyone who cared already has heard about Twitter’s shutdown of the APIs that third-party applications use. For me, this invokes the myth of Cortez burning the ships. I do not see a way for me to go back to Twitter.

I haven’t deleted or deactivated my account, as I had seen other users. Instead, I have deleted the Tweetbot application from my phone. Tweetbot was actually the reason that the Twitter service has stuck with me so long. The third-party applications were the only way that you could access the Twitter feed using a timeline instead of the curated feed that twitter wanted to give to you in addition to any ads. Tweetbot also allowed you to set up keywords to filter the stream. I used them primarily to block out media spoilers and when someone got a little too chatty about their latest multilevel marketing scheme business.

This, coupled with lists of individuals that I picked and reviewed, made twitter into what some would call an infinity pool for my attention. An infinity pool is defined as something that can endlessly supply you with entertainment/distractions.

Any time that I felt some stress, I could turn to Tweetbot to find something to occupy my mind. A little break before getting back to work. It was pretty easy to develop a dependency. I’m glad I never turned on notifications.

In the middle of last year, I took steps to move away from Twitter and I found the easiest way of doing that was to delete the application from my phone. If I wanted to get back on, I’d have to go through the process of downloading the app and logging in. Sure, not the biggest hurdle, but enough friction to stop me at those times when I needed to focus the most.

Well, now the API has been shutdown.

There’s no point in downloading the application.

And, without the customization that I’m used to, I don’t have as much desire to login.

And why should I log in?

Most of the content makers that I enjoyed are no longer on the service.

From what I hear, the site is filled with ads, and I’m already having enough trouble focusing that I don’t want to introduce more problems.

So.

That’s one less thing to distract me.

On to Ivory…

Creating Labarum (Part 4): Initiating the Index

In the beginning of this series, we started off with an index page that was just a static page with one line that stated you were on the index page. When it comes to implementing this, I looked at the Hugo Themes Free as well as the theme gallery that Micro.blog provides.

Ultimately, I went with a simple structure that took advantage of the simplicity that I had in the Pure theme and the fact that we had already extracted the logic for articles into the partials.

{{- range ( .Paginate (where .Site.RegularPages "Type" "post")).Pages }}
{{ partial "article.html" . }}
{{ end }}

After that, we remove all the static <article> tags that we placed into our index to see how it renders. This looks ok, but the design that I have in mind calls for pagination1(being able to go to older posts).

Paging the index

I admit that I went down a rabbit hole of different examples of how to create the navigation that you see at the bottom of the page. A lot of the examples that I came across where hard coded or I couldn’t understand.

Ultimately, I went with the example that I had from my previous theme. I took the code and placed it into a file name partial\site-navigation.html so that I can track it later.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{{ "<!-- Site Pagination -->" | safeHTML }}
{{ $paginator := .Paginate (where .Data.Pages.ByDate.Reverse "Type" "post") (index .Site.Params "archive-paginate" | default 10) }}
<nav class="pagination">
	{{- if $paginator.HasPrev -}}
	<p class="nav_prev">
		<a href="{{ $paginator.Prev.URL }}" title="Previous Page" rel="prev">
		← Newer Posts
		</a>
	</p>
	{{- end }}

	{{ if $paginator.HasNext -}}
	<p class="nav_next">
		<a href="{{ $paginator.Next.URL }}" title="Next Page" rel="next">
		Older Posts →
		</a>
	</p>
	{{- end }}
</nav>

On the first line, I’m adding a line that will show up in the final output of the generated site so I can see where Hugo is inserting the code.

The second line calls the default paginator to go over all the posts that the site has by whatever parameter that is given. If none is given, it will use 10.

Line 3 defines our semantic element for the navigation and give it a class for styling it later.

Line 4-10 tests to see if there is a previous page and then creates a link to the page when it exists.

Line 12-18 tests to see if there is a next page and creates everything that’s needed.

The navigation was another thing that I spent a lot of time looking into, but ultimately went with a simple ordered list of items.

The initial design did not have a link to the home page because I thought that anyone how came across the page would only be interested in that page and not the additional content, but after having to go to the address bar multiple times to navigate between the different pages, I decided to add it as the first item.

I placed this into a separate file called site-nav.html like I did for pagination for better tracking.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{{ "<!-- site-nav.html -->" | safeHTML }}
<nav>
	<menu>
		{{ if ne .IsHome true }}
		<li><a href="{{ .Site.BaseURL }}" title="{{ .Site.Title }}">Home</a></li>
		{{ end }}
		{{- range .Site.Menus.main }} 
		<li><a href="{{ .URL | relLangURL | safeURL }}">{{ .Name }}</a></li>
		{{ end -}}
		<li><a href="{{ "feed.xml" | absURL }}" rel="feed" type="application/rss+xml" title="{{ $.Site.Title }}">RSS</a></li>
	</menu>
</nav>

On line 3, I used the <menu> semantic tag to give it some more meaning. It definitely felt that it took some time to On line 3, I used the <menu> semantic tag to give it some more meaning. It definitely felt that it took some time to get a consensus on whether I needed to add a <ul> or <ol> to make the syntax valid.

Line 4 does a test to see if the generated page is the home page. This is working to an extent, but fails when moving to the second index page.

Line 7 sorts through the different menu items. I had an issue trying to understand how Hugo puts together a menu on my local copy and what was being used in Micro.blog.

Line 10 gives a direct link to the RSS feed for the site. The RSS feed is inherited from the base blank theme that underlies of Micro.blog.

The next segment of this tutorial will be focused on the schema tags followed by accessibility and then a grab bag of different things.

Please let me know if you have any questions about the design so that I can make this better. I think I might put this all together in one LARGE post at the end.


  1. I’ve come across a couple sites that only have the index and then has the user search or go through an archive to find older material. The argument being that most users only want to read your most current entries or have something specific that they are looking for.

    I’m going to go with what I feel is a classic approach and revisit this later. ↩︎

Creating Labarum (Part 3): Implementing post footer

In my initial design, I had footer that would show the categories, tags, date published, and date modified. All of these values are things, I had seen in previous sites and I could easily get to this information. I thought it would be 15-20 minutes to get this information. The fact that I felt that the footer deserves it’s own discussion should let you know that it ultimately wasn’t.

Start!

The first thing I did was move my current static footer from my example into it’s own template file partials/article-footer.html. I’m going to spare you the boring details of how I searched and searched through examples of what I thought it should look like versus what Hugo provides. A lot the issues that I ran into was whether I was using tag, tags, category, or categories. Do I write the code I write have to parse a comma separate list or an array?

My mental model originally had it so that a post could have one category and multiple tags.

Tag to multiple categories

Unfortunately, after a couple hours I realized that a lot of this was moot because I was going to send this template to Micro.blog and I didn’t know what they used.

Getting more information about Micro.blog

The ultimate goal for this theme is that I’d use it on the Micro.blog service. Although Micro.blog uses Hugo, it has a significant amount of customization that I do not know about. Honestly, I do not want to know exactly how it is put together, but I do want to know what it is sending to the theme to get rendered.

So, this is the point in the process where I deploy all the changes that I’ve made to GitHub and then use the instructions on how to set up with a custom theme.

I took some information from the  Hugo page on debugging a theme and then placed that in a <detail> item nested in the  footer. This made the article.html template pretty long, so I decided to make the footer into its own file (article-footer.html) for easier management.

Ultimately, this allows me to see if Micro.blog supports tags or categories and whether it’s stores in a string or array. I’m going to include the code in this post below.

{{ "<!-- Debugging Details --> " | safeHTML }}
	<details>
		<summary>Debug</summary>
		<h1>Site Properties</h1>
		<pre>
		{{ printf "%#v \n" $.Site  }}
		</pre>

		<h1>site.Params Properties</h1>
		<pre>
		{{ printf "%#v" site.Params }}
		</pre>

		<h1>Permalink</h1>
		<pre>
		{{ printf "%#v \n" .Permalink }}
		</pre>
		
		<h1>Params</h1>
		<pre>
		{{ printf "%s" $.Params }}
		</pre>

		<h2>All variables scoped to the current context</h2>
		<pre>
		{{ printf "%#v" . }}	
		</pre>
	</details>

After that, I’ll set the display of the debug information to hidden in the CSS.

article footer details {
    display: none;
}

I then deploy it to the test blog to see what is going on, I can see that categories is used in templates and is stored in an array.

Opening and closing of detail/summary debug information

If we parse through the debug information, we can find the information about whether Micro.blog uses tags or categories.

Categories defined on a specific post

Categories and Tags

As you have seen, I spend a lot more time of what the different elements make up the different pages. From here, I borrowed1 some code from the internet and rewrote it so that I can hopefully remember what it does in the future.

{{ with .Param "categories" }}
	Categories:

	{{ range $CategoryArray, $Category := (. | sort) }}
		{{ if gt $CategoryArray 0 }}
			<span></span>
		{{ end }}
		<a href="/categories/{{ $Category | urlize }}">{{ $Category }}</a>
	{{ end }}
	
{{ end }}

I also included code for tags that I saw in another example to future proof the theme in case we add tags later on with Micro.blog.

{{- with .Param "tags" }}
{{ with $.Param "categories"}}
<br />
{{ end }}
	Tags: <span itemprop="keywords">
  	{{ range $index, $tag := (. | sort) }} 
  		{{ with $.Site.GetPage (printf "/%s/%s" "tags" $tag) }}
  			<a href="{{ .Permalink }}" class="tag">{{ $tag | urlize }}</a>
  		{{ end }}
	{{ end }}
	</span>
{{- end }}

I didn’t do much with this portion because we don’t use them with Micro.blog, and I’ve got a lot of other things to get working before coming back to this.

Remember the time

Another piece of information that we can get from the debug output is date information from the post. We actually get three different dates: date, publishdate, and lastmod.

On my local server instance, I played with the different logic for if a date was different than another and learned about how Go did comparisons of dates for about an hour.

Then I found out that Micro.blog use the same time for all three…

Labarum raw date format in debug information

You can then put this information into our template.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<p>Published: 
	<a href="{{ .Permalink }}" class="u-url">
	<time class="dt-publised" itemprop="dateCreated datePublished"
		{{ 
		printf `datetime="%s"` (.Date.Format "2006-01-02T15:04:05Z07:00") 
		| safeHTMLAttr }}>
		{{- .Date.Format (default "January 2, 2006" .Site.Params.date_format) }}
	</time>
	</a>
</p>

On line 2, I create a link to the article because this footer will be used single pages and the index and we don’t know if every post will have a title.

Line 5 makes sure that the date is formatted in ISO 8601 so that it can be parsed properly.

Line 7 shows the date in a more human readable way. I made a mental note to look into how I can make it output “6th” but all the examples that I’ve seen do not show in like that.

I wanted the footer to have two separate sections of information; one for categories and tags and the other for dates.

Footer detail mental model

I used a css grid to make the two sections and made sure that the data I add was grouped in a <p> tags.

article footer {
    display: grid;
    grid-template-columns: 2;
}

article footer p:last-of-type {
    grid-column: 2;
    text-align: right;
}

After doing my testing and getting the debug information, I hid the details in the footer.

article footer details {
    display: none;
}

I plan to cover more css when I discuss accessibility later on in the series.


  1. I took this from Pete Moore’s implementation of Tufte. You can read Moore about it here↩︎

Creating Labarum (Part 2): Creating the individual posts

For this part, we’re going to be setting up the basic page used for our post and make sure that it can be reached from the index page. We’re going to be switching between different files to show the iterative process that I went through in order to see results quickly.

We’re going to edit the single.html to show the content by using the {{ .Content }} tag from Hugo. We also add the {{ .Title }} to the header and link it using the {{ .Permalink }} tag to get the following.

<article class="h-entry">
<header>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
</header>

<section class="e-content post-body">
{{ .Content }}
</section>

It renders to the following:

Simple article header with title

Let’s go back to our index.html to make it link to our post and show it on the main page.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{{ range ( .Paginate (where .Site.RegularPages "Type" "post")).Pages }}

<article>
	<header>
		<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
	</header>
	<section>
		{{ .Content }}
	</section>
	<footer>
		<p>
		Category: <a href="#">Some Category</a><br/>
		Tags: One Two Three
		</p>
	
		<p>Published: Some Date</p>
		</footer>
</article>
	
{{ end }}

The first line in the above code instructs hugo to iterate over all pages marked for the post type. On our local system, this isthe post directory and is in a database when using Micro.blog. The Permalink points to the individual post.

Links between index and post

We can test this by adding more content in the post folder to see what it looks like.

Multiple posts on index

But this highlights, we’re currently writing code in two places: the index.html and the single.html to render our content.

Note the forth line of the code which makes the assumption that we’re using a title for this post.

This is how I envision a post’s composition.

Mental model of post composition

We’d check if a post has a title and from there show a header or not before displaying the content and ultimately the footer.

Abstracting the article from the page

Let’s create partials/article.html and we’ll put all the content that we placed in _default/single.html in it.

<article class="h-entry">
<header>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
</header>

<section class="e-content post-body">
{{ .Content }}
</section>

<footer>
	<p>Category: <a href="#">Some Category</a><br/>
		Tags: One Two Three</p>
	
		<p>Published: Some Time</p>
</footer>
</article>

Then we replace the contents of default/single.html with the following.

{{ define "main" }}
{{ partial "article.html" . }}
{{ end }}

When we render the page and there shouldn’t be any errors at this point.

Let’s add the conditional for the header of the article.

{{ if .Title }}
<header>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
</header>
{{ end }}

Then let’s make a post without a header to test out that this is working without an error in our logs.

Simple article without a header

Next, we can work on the article footer which I’ll make into a separate component in the next installment.