Importing content is always the bane of moving systems.
Now one of the things Hugo has is a cool command called $ hugo import jekyll – and yes, it does exactly what you think it does. This was interesting to me since I wondered if I could switch my library from Jekyll to Hugo and yes, yes I can.
The site I have on Jekyll has a few more posts than the first one I built on Hugo. This one has around 1500 pages. Excited, I ran the command:
Importing... Congratulations! 0 posts imported!
That’s not right. I spent a few hours trying to run it in various permutations, but I was never able to get it to run right. Thankfully, I didn’t need to since I could just copy my content over. There was no translation needed, as I was already using yaml headers in my .md files so that actually was a pretty painless transition.
The theme on the other hand… Well. I had a complex site with data files and weird junk being thrown around. That was just learning how to translate for-loops for ranges, with some where clauses tossed in.
Was it hard? Yes. But that’s not what you’re really asking.
Was it worth it?
Excuse me while I whip this out:
Change detected, rebuilding site 2015-12-11 21:42 -0800 0 draft content 0 future content 1479 pages created 0 paginator pages created 16 categories created 66 tags created in 4611 ms
Yes. The site builds faster, which is a win. It also creates tags and categories that can automatically cross link. I can make ‘sections’ without having to define them in my config file, just by making folders. I can spin up templates quickly. I have a little more redundancy than I’d like, but as I master GoLang, this becomes less and less.
Build time ranges from 11737 ms to 2116 ms. Milliseconds. They were into the minutes with Jekyll, even though Jekyll 3 was notably faster than version 2. It was still taking me about 2 minutes to rebuild the Jekyll site, even with incremental builds working. Plus I had to build and rsync every time, in addition to Git pushing. Now I just Git and done.
Oh and JSON works remotely out of the box. I just have to get better at my range calls now.
What’s Different?
Making a ‘static front page’ with Hugo is harder. In fact there’s still an open trac ticket on it. I was able to use an idea I already had, a custom post param called “type” for tagging ‘index’ posts in the news pages so I didn’t get a list of my indexes when I wanted to list all news from 2002. I leveraged that and tagged my primary index ‘mainindex’ and put a quick check in my index.html in my theme:
{{ range .Data.Pages }}
{{if eq .Type "mainindex" }}
{{ partial "content.html" . }}
{{end}}
{{ end }}
Instead of doing a normal loop where, like a blog it shows me posts in reverse order, it just showed that specific content.
But…
If there’s a file in that Section with the type of ‘Index’ then it shows that. Of course… While index.md doesn’t get used in the main content folder, it does in Sections. If I have a file named index.md in a section, that makes index.html like I expected. Since I still wanted lists in the majority of cases, I tweaked the content of my default list file (list.html) so that I could always show a ‘main’ file:
{{ range .Data.Pages.ByTitle }}
{{ if eq .Type "index" }}
{{ .Content }}
{{ end }}
{{ end }}
<ul>
{{ range .Data.Pages.ByTitle }}
{{ if ne .Type "index" }}
<li><a href="{{ .Permalink }}">{{ .Title }}</a></li>
{{ end }}
{{ end }}
</ul>
Then I renamed all the index.md files in the Sections to main.md but this created another issue. Now I had two URLs that worked. I could have put this into the template for the section to avoid this, but I want to separate content and theme as much as humanly possible. WordPress habits. For now, I’ve left this alone. If someone is clever enough to go to a non-linked, non-sitemaped page instead of the index, I think my SEO will live. It’s more than I wanted to play around with loops.
Speaking of the loops and lists, getting a list of a ‘sub section’ is not currently possible either. Rather, they do work, but there’s no default templates for sub-sections. This was a small problem since I structured my site like this:
.
└── content
├── news
| ├── index.md // /news/
| ├── 2001
| | ├── loch-ness.md // /news/2001/loch-ness/
| | └── monster.md // /news/2001/monster/
| └── 2002
| ├── nessie.md // /news/2002/nessie/
| └── spock.md // /news/2002/spock/
└── posts
Now, I don’t need a custom template for each sub-section, but I did want to use my custom list template for each sub-section. To work around this, I made a template in /layout/section/news.html that had this:
{{ range .Data.Pages.ByTitle }}
{{ if and (eq .Type "index") (ne .Params.topic "index") }}
{{ .Content }}
{{ end }}
{{ end }}
I know this is weird. The Type of index means “I am the main index file of the section” while the topic index means “I am an indexing file and not a normal news article. This gives me my main index of /news/ giving me a custom content page with information like I wanted, using the main.md format I use in all sections.
Then in each sub-section, I use a very simple index.md file:
---
title: News Articles (1992)
author: Mika Epstein
layout: news
topic: index
date: 1992-01-01
permalink: /news/1992/
categories: ["News"]
tags: ["1992"]
---
{{< news >}}
That weird bit in the content is a shortcode ala Hugo, which calls the file /layouts/shortcode/news.html that has this:
{{ $date := $.Page.Date.Format "2006" }}
<table class="infobox">
<thead><tr>
<th>Date</th>
<th>Source</th>
</tr></thead>
<tbody>
{{ range where $.Page.Site.Pages.ByDate "Section" "news" }}
{{ $thisdate := .Date.Format "2006" }}
{{ if and (eq $date $thisdate) (ne .Params.topic "index") }}
<tr>
<td>{{ .Date.Format "01 January" }}</td>
<td><a href="{{ .Permalink }}">{{ .Title }}</a></td>
</tr>
{{ end }}
{{ end }}
</tbody>
</table>
That spits out a table of all the pages in that section by date.
What’s Next?
It took a lot to get here, or so it may seem. This took me two nights to work out. That’s it. So now I have to figure out the next steps that have vexed me:
- How do I properly mimic a for-loop with range?
- Can I make a responsive gallery out of Hugo?
- Can I power a Hugo site with WordPress JSON?
And that’s a whole ‘nother story.



I will note: If this process freaks you out, remember to never make changes like this without a backup. If it’s still super spooky, you may not be ready for Multisite yet. I would consider this to be a good litmus test, though, for a wanna-be-multisite-master. You’re going to need to be able to do these things to get there.

