Customizing Pages/Understanding how Pages work on Micro.blog

I’m trying to better understand how to customize the content for my Pages on micro.blog. I want to customize a reading page using the data available in the new bookshelves feature.

I’ve tried putting a template in:

layouts/posts/reading.html.html or layouts/posts/reading/single.html but I don’t think the content is picked up in either one. I’ve also tried using a trick I’ve used before, with {{ if (eq .Title "Reading") }} in my layouts/posts/single.html but that also doesn’t seem to get picked up/triggered on the page generated by creating a new page at myurl.com/reading (even though it appears to me that Reading is the page title).

Is there any front matter I can use to determine if I’m on this page? What template does it draw from and is there a way to target that template?

In stock Hugo, I suspect I’d either make this a type (not post) or have this as reading.md not under posts and use a layout like layouts/reading.html that I think would pick that up (and that md file would probably be just front matter).

Pages on Micro.blog have always thrown me off a bit because they seem like posts with custom permalink URLs, but they have been a bit hard to target with anything other than standard post markdown content to be processed by layouts/posts/single.html.

2 Likes

I would like an answer to this, too.

EDIT: Just to add a little bit of extra info: The info provided here about a custom 404 page seems to suggest that if you have a page with the slug /test then a template /layouts/test.html should be applied. Sadly this is not the case for me.

1 Like

Yeah, this is confusing and I think Micro.blog needs some tweaks to make standalone pages work better, like extra post types. I think for now what you want to do is create a file in the theme in the “content” folder, like content/reading.md and then specify the layout in the front matter?

I’ll do some more testing on this. Thanks!

3 Likes

Doesn’t seem to be working:

I have a page called Titles (slug /titles), which is supposed to only show posts that have a title. It looks like this:

I then created a custom template called content/titles.html it has this (test) content:

{{ define "main" }}
<div class="home h-feed">

  <ul class="post-list">
	{{ $paginator := .Paginate (where .Data.Pages.ByDate.Reverse "Type" "post") (index .Site.Params "archive-paginate" | default 25) }}
	{{ range $paginator.Pages  }}
		{{ if .Title }}
      <li class="h-entry">

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


        <a href="{{ .Permalink }}" class="u-url"><span class="post-meta"><time class="dt-published" datetime="{{ .Date.Format "2006-01-02 15:04:05 -0700" }}">{{ .Date.Format "Jan 2, 2006" }}</time></span></a>

        <div class="e-content">
         	{{ .Content }}
        </div>
      </li>
		{{ end }}
    {{ end }}
  </ul>

  <p class="rss-subscribe">subscribe <a href="{{ "feed.xml" | absURL }}">via RSS</a></p>

</div>
{{ end }}

I also tried to put a different string into the front matter: content/titles.html, titles, titles.html but none work for me.

What am I doing wrong?

@manton I still would like to know. I have plans to customize my blog, but I am blocked by not knowing/understanding how pages work. I think I grok Hugo’s templating enough. I just don’t know how to apply a custom template to a page. It’s quite frustrating that I can’t seem to figure it out.

1 Like

Take a look at my public theme and plugin repositories (I spent the last two weeks breaking my theme code into plugins). The trick to controlling page content is the content root level directory. The markdown files in this directory get to contain front matter followed by markdown content. My quest to control category pages led me to discover that for categories there is a default file deal where you can create a file at content/categories/category-name/_index.md. I have a file in my theme at content/categories/inside-the-art/_index.md that looks like this:

---
title: "Inside the Art"
description: "Guided tours through some of the signed art."
aliases: [/inside-the-art/]
menu:
  main:
    name: "Inside the Art"
    title: "Inside the Art"
    identifier: "inside"
    url: "/categories/inside-the-art/"
    weight: 106
---
*Guided tours through some of the signed art.*

Some interesting things can be accomplished with the front matter. The markdown portion becomes available to templates as .Content. The category pages go through layouts/_default/taxonomy.html, so I created a file that looks like this (it grabs the content as an introductory paragraph):

{{- /* Template for category pages */}}
{{- define "stylesheets" }}
<link rel="stylesheet" href="/assets/css/dark-nav.css">
<link rel="stylesheet" href="/assets/css/list.css">
{{- end }}

{{- define "main" }}

<section id="wrapper">

{{- /* Display any content provided for the category */}}
<div class="category-content">{{ .Content }}</div>

{{- /* Generate the pinned/remaining collections.  */}}
{{- $pinned := .Site.Taxonomies.categories.Get "pinned" }}
{{- $all_pinned_pages := $pinned.Pages }}
{{- $pages := where .Data.Pages.ByDate.Reverse "Type" "post" }}
{{- $pinned_pages := $all_pinned_pages | intersect $pages }}
{{- $remaining_pages := $pages | symdiff $pinned_pages }}
{{- $pages_dict := dict "pinned" $pinned_pages "remaining" $remaining_pages }}

{{- /* Display the list of posts. */}}
<ul id="post-list">

{{- /* Handle pagination. */}}
{{- if .Site.Params.paginate_categories }}
  {{- $paginator := .Paginate $remaining_pages }}
  {{- if not $paginator.HasPrev }}
    {{- range $pinned_pages }}
      {{- partial "truncated-post-item.html" . }}
    {{- end }}
  {{- end }}
  {{- range $paginator.Pages }}
    {{- partial "truncated-post-item.html" . }}
  {{- end }}
{{- else }}
  {{- range $pinned_pages }}
    {{- partial "truncated-post-item.html" . }}
  {{- end }}
  {{- range $remaining_pages }}
    {{- partial "truncated-post-item.html" . }}
  {{- end }}
{{- end }}
</ul>

{{- if .Site.Params.paginate_categories }}
  {{ partial "pagination" . }}
{{- end }}

</section>

{{- end }}

The end result: On the Mind of Moondeer - Inside the Art

You can create entirely independent pages by sticking the markdown file directly under content. I have a file at content/about.md that looks like this:

---
title: "About"
description: "Just a touch of the biographical."
type: about
menu:
  main:
    name: "About"
    title: "About"
    identifier: "about"
    url: "/about/"
    weight: 120
---

Setting the type value to about causes Hugo to look for a template located at layouts/about/single.html. Mine looks like this:

{{- /* Template for the about page */}}
{{- define "stylesheets" }}
<link rel="stylesheet" href="/assets/css/dark-nav.css">
<link rel="stylesheet" href="/assets/css/about.css">
{{- end }}

{{- define "main" }}
<section id="wrapper">
{{- partial "profile.html" . }}

<div id="wrapper"><p>
What? Y’all want something not constructed as a Trumpian dig for an itty bitty Twitter bio box?</p>

<p>
<img src="https://moondeer.blog/uploads/2021/f5130a1cf3.jpg" /></p>

<p>
Fine. Let me think on it (and yes, my father had to remind me that I was born at Northside and not Grady).
</p>

<p>I suppose the very least I could do is point you at sh$t I have already composed that just might elucidate some of my what-the-f$&kedness.</p>

<p>Take, for example, the conundrum of how one collects two undergraduate degrees and manages to go absolutely nowhere in life. Reading something like <a href="https://moondeer.blog/2021/02/21/on-fking-up.html">this</a> would probably go a long way with regard to cracking that particular nut.</p>

<p>Farther back, huh? Figuring childhood trauma, I presume. Not even a little bit. Life was a g@dd@mn cakewalk. </p>

<p><img src="https://moondeer.blog/uploads/2021/649b8f887e.jpg" width="3024" height="4032" alt="" /></p>

<p>Soccer all-star from age four, stuck into an accelerated learning program when I was in third grade after the score I put up on my Iowa Test of Basic Knowledge (within which the sneaky buggers hide an IQ test), and making friends was effortless. For f$&k’s sake, they decided to give me a senior superlative on account of my appearance.</p>

<p><img src="https://moondeer.blog/uploads/2021/e26af155c2.jpg" width="4032" height="3024" alt="" /></p>

<p>What went wrong? Well it turns out that socially isolating myself for 18 years was a bad f$&king idea (the jury is still out as to whether attempting to reconnect <a href="https://moondeer.blog/2021/02/27/so-long-twitter.html">via social media</a> was an equally bad idea).</p>

<p>Living in social isolation certainly makes <a href="https://moondeer.blog/2021/03/02/on-pet-loss.html">pet loss</a> more difficult. I have noticed; however, that there are a few perks to life on the other side of an existential crisis (I am headed into existential crisis numero deus so Imma keep those perks to myself for the time being).</p>

<p>There was a week not long ago where I truly thought I might be able to make the kinds of connections I have been searching for since jumping into social media last year. After 20 years, I remembered I was meant to write … and to have <a href="https://moondeer.blog/2021/02/24/on-dragons.html">big ideas</a>. The problem seems to be the having of the ideas in isolation. </p>

<p>The frustration of being unable to connect keeps a fire lit in the corner of my mind … tended by that piece of me wanting to say f$&k it … let’s just disappear … into the wild</p>

<p><img src="https://moondeer.blog/uploads/2021/93f6402abd.jpg" /></p>

<p>So there’s a rough sketch for ya. No doubt I will comeback later and overhaul the f$&k out of this little sh$t show.</p>
</div>
</section>
{{- end }}

The end result: On the Mind of Moondeer - About

I use the same pattern to create new pages in plugin-category-cloud, plugin-bookshelves, and plugin-gallery

3 Likes

Thank you so much for your helpful post! I tried it out and it seems to work, sadly for my use case, namely having another list-page for a filtered down list of my blog’s content, I couldn’t get it to work.

1 Like

@jsonbecker was on the write track with category manipulation. Here is an example of how you can have category inclusion dictate content. You should be able to adapt the logic (and set operations) to generate a post list filtered for a particular page’s purpose.

What we’ll be looking at is my taxonomy template (which generates category list pages). You would want to fetch all post pages and then perform your set operations.

What the following template does is filter the page list for the generated page’s category into a group of pages that have also had a ‘pinned’ category applied and a group of pages that have not. The ‘pinned’ posts are displayed (if and only if this is the first page with regard to pagination) and then the group of remaining posts is displayed with pagination.

{{/* Template for category pages */}}
{{ define "main" }}
{{ partial "comment.html" "_default/taxonomy.html#main" }}
{{/* Display any content provided for the category */}}
<div class="category-content">{{ .Content }}</div>

{{/* Generate the pinned/remaining collections.  */}}
{{ $pinned := .Site.Taxonomies.categories.Get "pinned" }}
{{ $all_pinned_pages := $pinned.Pages }}
{{ $pages := where .Data.Pages.ByDate.Reverse "Type" "post" }}
{{ $pinned_pages := $all_pinned_pages | intersect $pages }}
{{ $remaining_pages := $pages | symdiff $pinned_pages }}

{{/* Reset the slice of pages and handle pagination */}}
{{ $pages = slice }}
{{ $paginate := site.Params.paginate_categories }}


{{ if $paginate }}

  {{ $paginator := .Paginate $remaining_pages }}
  
  {{/* Empty the pinned pages if this isn't the first page. */}}  
  {{ if $paginator.HasPrev }}{{ $pinned_pages = slice }}{{ end }}
  
  {{/* Just generate for this page */}}
  {{ $pages = $paginator.Pages }}
  
{{ else }}

  {{/* Generate it all */}}
  {{ $pages = $remaining_pages }}

{{ end }}

{{ with $pinned_pages }}{{ partial "post-list.html" . }}{{ end }}

{{ with $pages }}{{ partial "post-list.html" . }}{{ end }}

{{ if $paginate }}{{ partial "navigation/pagination" . }}{{ end }}

{{ end }}

Update: Hah, didn’t realize I had already included this template code, but at least this time I gave it some context as applied to the solution you’re trying to create.