Continuing the discussion from Making a website: home on the web:
I realized that having tule
as a complete theme would make all these other steps a lot easier on myself. We will be doing that in this thread.
Continuing the discussion from Making a website: home on the web:
I realized that having tule
as a complete theme would make all these other steps a lot easier on myself. We will be doing that in this thread.
Here’s my thinking for a 1.0 release: the minimal of minimal yet complete set of templates to produce output for any valid content. On the lookup order doc it has this note:
Tip: The examples below looks long and complex. That is the flexibility talking. Most Hugo sites contain just a handful of templates:
├── _default │ ├── baseof.html │ ├── list.html │ └── single.html └── index.html
So we’ll start there. Let’s see what each of those templates is about, and then we’ll poke around and see if there are any nice-to-haves beyond these.
Good to know:
The homepage template is the only required template for building a site and therefore useful when bootstrapping a new site and template. It is also the only required template if you are developing a single-page website.
So index.html
is the only required template. If you ever watch the hugo server
console while linking through your site, you’ll see if you hit a piece of content that doesn’t have a template. If you wanted a single page website, you could get by with something like:
├── config.yaml
├── content
│ └── _index.md
└── layouts
└── index.html
A complete site. Note: demo a tiny single page site.
The sample index.html
template in the docs:
{{ define "main" }}
<main aria-role="main">
<header class="homepage-header">
<h1>{{.Title}}</h1>
{{ with .Params.subtitle }}
<span class="subtitle">{{.}}</span>
{{ end }}
</header>
<div class="homepage-content">
<!-- Note that the content for index.html, as a sort of list page, will pull from content/_index.md -->
{{.Content}}
</div>
<div>
<!-- Note that .Pages is the same as .Site.RegularPages on the homepage template. -->
{{ range first 10 .Pages }}
{{ .Render "summary"}}
{{ end }}
</div>
</main>
{{ end }}
Currently tule
’s index.html
is:
{{ define "main" }}
<header>
<h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
{{ end }}
They are actually very similiar, mine is just simplified and excluding a couple of features.
Similarities:
main
blockheader
element for title.Content
from content/index.md
Differences:
div
elementsThere’s the thing about including the main
element, but that’s a breakout discussion.
For tule
’s purpose, it works. New site’s always have weird page situations going on: folks want to control the look and feel and number and dates of the content showing up on the front page, and this is not the theme for that.
One possible improvement I can think of is rendering the home page even if content/index.md
doesn’t exist. I’ve seen other themes with instructions for getting the theme started, and that is a good idea.
Ha! I was testing how it looks without content/index.md
, and it just loads the title from config
, and otherwise just shows a blank page. I’m fine with that behavior.
For tule
the current baseof.html
is:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ block "title" .}}{{- .Title -}}{{ end }}</title>
<link href="{{ "css/style.css" | absURL }}" rel="stylesheet" type="text/css">
</head>
<body>
<main>
{{- block "main" . -}}
<header>
<h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
{{ end }}
</main>
</body>
</html>
I like my elements to be lowercase, so I chose the one of 2048 doctypes that matched my preference.
html
has lang="en"
set as I primarily build sites in English. I imagine a more robust theme uses multilingual features to set lang
.
The head
has those two meta
elements that are important, and no more. Note: expand on these elements.
title
is the first block I define, as it may change depending on the template. For instance, I may want to elaborate on the paginated pages. Honestly, it’s a bit overkill for tule
me thinks.
The link
passes the path to absURL
, which was a tip I picked up on the forums.
The body
and nested document structure is very simple: main
element, sensible header, and .Content
as default, and able to be overridden in other templates.
I should note here that other templates in fact only override the “main” block, but just copy the same code. For instance, layouts/_default/single.html
:
{{ define "main" }}
<header>
<h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
{{ end }}
Same for list.html
at the moment. Not particular DRY, but I’ve found that the other templates won’t render unless they exist and define blocks. I take advantage of the baseof.html
values being default, but for “main” I can safely remove it.
Another missing feature might be a footer. Here’s an interesting place to take advantage of baseof defaults, as I can create a sensible footer, with an easy way to hook into the templates for customizing.
Let’s make those changes and see how it looks.
I removed the “main” block defaults:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ block "title" .}}{{- .Title -}}{{ end }}</title>
<link href="{{ "css/style.css" | absURL }}" rel="stylesheet" type="text/css">
</head>
<body>
<main>
{{- block "main" . -}}
{{ end }}
</main>
</body>
</html>
15 lines chrome. Not bad!
I had added a footer
element, with a “footer” block, but I couldn’t come up with anything. Not gonna force it!
Something I’ve come to see in creating this theme is that once you have a base, spinning up per-project “themes” makes sense. That means when I need a footer, the project will have a footer (it was four lines, keeping it clean).
Okay, unless I’m missing something big, that’s good enough for the tule
baseof.html
template.
A list page template is a template used to render multiple pieces of content in a single HTML page. The exception to this rule is the homepage, which is still a list but has its own dedicated template.
There’s another useful note:
Since section lists and taxonomy lists (N.B., not taxonomy terms lists) are both lists with regards to their templates, both have the same terminating default of
_default/list.html
orthemes/<THEME>/layouts/_default/list.html
in their lookup order. In addition, both section lists and taxonomy lists have their own default list templates in_default
.
Meaning this template will get used in a lot of instances.
I’ve thought about what I want to include in list.html
for tule
. I’d like to keep it simple for now, so I’m going to skip pagination. For now. I might add it, or make it another layer that goes on top of tule
(tule-pagination
).
For my purposes I just want to list some content, to ensure it is working.
range
of content for that listCurrently, list.html
is:
{{ define "main" }}
<header>
<h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
{{ end }}
Boom, two out of three already done! We just need to throw in a range for content and we can call it a day. The list template page is basically one long string of examples of how to group and sort and group/sort content in a variety of ways. I will keep it simple for our first go, just range through the content with default sorting, and return a title.
Oh! The first example is so close to what I want in the end, I’ll just copy over the new bits and so:
{{ define "main" }}
<header>
<h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
</li>
{{ end }}
</ul>
{{ end }}
I removed the date from the listings, as we don’t actually need that for tule
; that can be added back in, with other markup and content, such as article
elements rather than list items, and showing a .Summary
beneath the title links.
This is just about done, but I want to add one more item: limit the range
to 200 entries.
{{ range first 200 .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
</li>
{{ end }}
tule
isn’t meant to render list pages for huge repositories of content, but on the off chance I forget that and try to, I won’t kill the build server; it will only list the first 200 pieces of content for any given list page, meaning 200 list item with anchors in them, which probably isn’t that large of a page.
Okay, list.html
is done (https://allthe.codes/maiki/tule/commit/d74f93ad8b3c7ea222a596b477c4eeb36bbf2acb).
Returning to tule
, I wonder where I want to go from here. Recently I’d been using so many “page builders”, I thought I might create a sub-module for tule
that provides options for things like menus and header layouts… but then maybe it could just be config options in the core theme.
I need to decide: do I want tule
to be easy to read and modify, or complex enough to meet lots of use cases?