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.