Building_with_Hugo
2023-03-06 - Web Development - Hugo
As much as I started to enjoy playing around and styling with html/css, it did, at times, become slightly annoying to quickly document progress on projects [which is hard enough to do as it is sometimes]. This was especially true when trying to structure the site to reference identical posts on multiple pages [ie. on the tots page as well on the associated hobby page]. A solution that I have been mulling from the beginning is a static site generator.
What I was looking for was an environment that was extensible enough to eliminate redundant code while also malleable enough to execute the initial vision I had for the website [i know, surprising this website had any vision at all given the look]. Static site generators enable this by, essentially, copying identical html across multiple pages through templates. This maintains the benefits of a static site while addressing one of it’s biggest drawbacks. After some research [googling “best static site generator”], Hugo seemed to check the boxes I had in mind and also looked relatively simple to implement [which is something a lazy person like me really values].
After installing on a local machine with apt install hugo
[change apt to your respective package manager], a new site can be created with Hugo with the command hugo new site site_name
which creates a directory with Hugo’s default file structure. The main directories that I use are content, layouts, and static. Content is where the actual content of a post is stored [basically the actual meat of the website], layouts is where templates and other code snippets are defined [where hugo pulls the skeleton html to generate posts and lists], and static is where things that are referenced by templates and posts are stored [like images and style sheets].
New content posts can be created with hugo new section_name/post.md
which creates a new file under content/section_name/post.md. For example this post was created with hugo new web_development /building_with_hugo.md
. Section landing pages can be created by adding a _index.md file under the section directory with hugo new section_name/_index.md
[these will call the list template, if you don’t know what that means, read on!].
Hugo posts are written in Markdown which, basically, is a way to define the format of text through some pretty straightforward syntax [trust me, it’s really easy to pick up]. If Markdown’s default behavior is not cutting it for you, it can also be redefined under /layouts/_defaults/_markup.
However, sometimes Markdown doesn’t have all the functionality that html would allow. In these cases shortcodes can be used to inject html into a content page by calling the shortcode with {{< $name_of_shortcode $arg0 $arg1 $arg2 >}}
. For example, I have a shortcode to format an image correctly in a post under /layouts/shortcodes/image_sc.html.
<img class="resize" src="{{ .Get 0 }}" alt="{{ .Get 1 }}" />
<figcaption>{{ .Get 2 }}</figcaption>
I can utilize this in a post with {{< image_sc "path_to_image" "alt_text" "caption" >}}
. Path_to_image will be passed into {{ .Get 0 }}
[given its the first argument], alt_text to {{ .Get 1 }}
, and caption to {{ .Get 2}}
. Shortcodes are a great way to deal with those edge cases when Markdown just doesn’t quite cut it.
Now on to templates. Templates are also placed under the /layouts directory. The two main templates that I’ve used are single.html and list.html [here it is!] under the _default folder. Single.html is used for individual posts while list.html is used for section landing pages which list the individual posts [shocker] in the section. Single pages are hosted at website.com/section/post.md [ie xavishobbies.org/web_development/building_with_hugo ] while list templates will are hosted at website.com/section. [ie xavishobbies.org/web_development ]. These templates are written in normal html but can do fancy things with specified functions and variables. Here is my very simple single template.
{{ define "main" }}
<div class="tots_post">
<h3 class="entry_heading">{{ .Title }}</h3>
<h5 class="tots_date_category"> {{ .Lastmod.Format "2006-01-02" }} - {{ .Description }}</h5>
<p>{{ .Content }}</p>
</div>
{{ end }}
This just inputs the post title at {{ .Title }}
and content at the {{ .Content }}
[pretty straightforward huh?].
And here is a quick example of a list template that is referenced in the Hugo documentation. It loops through all the posts in a section and displays the title of each post as a link to the full post.
// <!-- Ranges through content/posts/*.md -->
{{ range .Pages }}
<li>
<a href="{{.Permalink}}">{{.Date.Format "2006-01-02"}} | {{.Title}}</a>
</li>
{{ end }}
It uses range
to loop through all content .Pages
, and create a list item, <li>
, with a reference, <a href=
, to the single content page, {{.Permalink}}
, with the date, {{.Date.Format "2006-01-02"}}
, and the title, {{.Title}}
.
Hugo also uses partials, which are templates that can be called by other templates such as single and list and are saved under /layouts/partials. For example, I use a partial to handle my footer which I call from both my single.html and list.html with {{- partial "footer.html" . -}}
.
<footer> <a href="{{ .Site.BaseURL }}/index.html">Home</a> </footer>
Again, the whole point is to eliminate redundant code wherever I can without creating a boring cookie cutter site.
Then again some pages need to be completely unique. Things like the main website landing page, 404 page, and other special content can be written completely in html and placed under the layouts directory. These special pages will supersede any previously defined templates.
Hugo also lets you take a look at your site locally, before pushing it to a live site, with the hugo server
command. This starts an instance of website at localhost:1313.
Just throw that into the browser of your choice and take a gander. What’s also super cool is that Hugo detects changes and auto generates the site every time it does. This lets you actively see the changes you are making [or for me, shows me how my formatting is wrong, AGAIN].
That’s pretty much everything that I used to build this site. Hope it wasn’t too much of an info overload!