The site:
MovableType 2.64 on a 500MHz Pentium 3 with 256MB of RAM
- 3,419 blog comments
- 2,790 blog entries
- 1,804 Amazon-hosted images
- 596 linkblog entries
- 263 quotes
- 130 locally-hosted images
- 82 now-playing microblog entries
- 36 blogroll linkblog entries
- 12 project linkblog entries
- 9 misc external image links
Things I don’t like about Hugo
-
Inconsistent, incomplete, misleading, and/or outsourced documentation.
-
Enhancement: replace “how to do this in Go” links with “how to do
this in Hugo” pages. (ex:.Date.Format
) -
Enhancement: extensive one-line code examples:
- does section $s exist; retrieve/search its pages
- does an article with title $t exist (opt: in section $s); retrieve it
- does taxonomy $ta exist; retrieve/search its terms
- does term $te exist in taxonomy $ta; retrieve/search its pages
- essentially, when I want to count the number of pages in a specific taxonomy term referenced in the article’s front matter, don’t show me how to count all terms in every taxonomy, show me how to construct the very-non-obvious
(index $.Site.Taxonomies.comments .Params.entry).Count
-
Enhancement: replace “how to do this in Go” links with “how to do
-
Speaking of inconsistent and incomplete,
index
is documented athugodocs.info/functions
, but not gohugo.io/templates/functions/. -
No idea which examples work correctly in the current release, which are new, which are deprecated, which don’t do what you’d expect.
-
Enhancement: in addition to
min_version
intheme.toml
, add
tested_versions=[]
-
Enhancement: in addition to
-
Bug: setting
watch=false
doesn’t work inconfig.toml
forhugo server
(Mac v0.19), which would make the “too many open files” issue less annoying. (note: actual open-file count for my site according tolsof
: 9,017) -
Pluralization adds complexity without benefit. Seriously, when is it “tag” vs. “tags”, etc? As far as I can tell, the singular is always used in paths (
layouts/taxonomy/tag.html
, etc), and the plural is always used in templates, but I don’t know if that’s correct and complete.- How do this work with i18n?
- Where does the use of
inflect
inpluralizeListTitles
come into all of this? - Dumb: section “Elsewhere” title is “Elsewheres”
- Dumber: section “Recently spotted” title is “Recently spotteds”
-
Enhancement:
pluralizeListTitles=false
should be default
-
Speaking of which, “You can use the go-i18n tools to manage your translations” is a great example of outsourcing documentation in a way that is completely useless.
-
Stumbling across
preserveTaxonomyNames
, good. Finding out that it preserves case (the obvious way to make a category named “TV” or “SF” look right), better. Discovering that it leaves " " in the URLS as well, bad. Breaking.Next.URL
, etc in$.Paginator
? Priceless.- Enhancement: store the original form of the taxonomy term so you can have both a sanitized version for the URL and the user’s preferred display form (.Name and .Display). If the tagging was inconsistent, that’s the user’s problem.
- How did I do it instead? I created a set of key/value pairs in the data directory (
wtf="WTF"
) and substituted them in (<> and ul/li deleted to avoid markdown confusion…):{{ range $key, $value := .Site.Taxonomies.categories }} {{ index $.Site.Data.casefix $key | default ($key | humanize) }} {end}}
-
Poorly-explained template search path with no debug output.
- Enhancement: debug flag on “hugo server” that embeds HTML comments showing what kind of page it thinks it’s rendering, and every place it looked for a template before finding one.
-
Internal pagination template does not scale at all.
-
Enhancement: partials/pagination.html
This automatically got styled nicely by Bootstrap’s example Blog theme, by the way.
-
Enhancement: partials/pagination.html
-
WTF is up with twenty different context-dependent .ByWhatever and
.GroupByWhatever functions?- Is .ByFoo just syntactic sugar for using the
sort
function? - How do I put “if section $s1, by-date-ascending, else if $s2, alphabetical” into a template? Or better yet, in /data so I can just set:
[hotnews] key=".Date" order="desc" [quotes] key=".Author" order="asc" [special] key=".Params.mysortkey" order="asc"
- Is .ByFoo just syntactic sugar for using the
-
I’m still not sure what I did that made
hugo
dump a meaningless stack trace. Probably an attempt to use the only debugging tool that’s available,{{ printf "%#v" . }}
, which sometimes returns something useful, but usually just fills the page with noise.- Enhancement: pretty-printing the above printf debug statement like Perl’s Data::Dumper would be a start.
-
Still trying to figure out if I can have:
- auto-generated monthly archive pages with prev/next-month navigation links, and the ability to link N most recent months in sidebar.
-
Workaround: use a script to fill a section with small content files, and then put something like this in
layout/archive/single.html
{{ month := .Params.month }} {{ range .Site.Sections.post.Pages.GroupByDate “2006-01” }}
{{ if eq .Key $month }}
{{ range .Pages.ByDate }}
{{ partial “article-summary.html” . }}
{{end}}
{{end}}
{{end}}
-
Workaround: use a script to fill a section with small content files, and then put something like this in
- prev/next-in-section/taxonomy-term navigation links.
-
Enhancement: virtual sections whose pages are defined by an expression in the theme config (the obvious location would be the front matter of
theme/mytheme/content/mysection/_index.md
, but content pages don’t work in themes).
- auto-generated monthly archive pages with prev/next-month navigation links, and the ability to link N most recent months in sidebar.
-
In other words, between the issues with documentation, examples, etc, I still don’t know if Hugo today can generate all of the types of static content that MovableType could in 2003, or if so, how to do it.
-
No standards in themes; once you’re past the mockup stage, you really can’t switch. Theme A mixes all sections in
index.html
with no visual differentiation, theme B just shows “post”, theme C calls it “posts” instead, theme D only works if you add specific entries toconfig.toml
that theme E uses for something else, etc, etc. -
No way to identify CJK content so it can be treated differently. For instance, I want to italicize a list of song titles, unless they include kanji, etc. The Go regexp library doesn’t seem to support Unicode blocks, so the best I could come up with quickly was to only italicize 7-bit ASCII titles:
{{ $count_cjk := findRE "[^\000-\177]" .Title }} {{ if ge (len $count_cjk) 1 }} {{ .Title | safeHTML }} {{else}} <i>{{ .Title | safeHTML }}</i> {{end}}
Late additions…
- I forgot to mention one of the first things I had to work around: the useless auto-stripped
.Summary
. I had to append<!--more-->
to every blog entry and comment that I converted from the MT blog, and add it toarchetypes/default.md
to make sure I never forget to add it.-
Enhancement: add a flag to disable auto-summarization and just return
.Content
if the user didn’t manually insert<!--more-->
.
-
Enhancement: add a flag to disable auto-summarization and just return
- The SmartyPants implementation has some odd behaviors I’ll have to try to reproduce sometime, but the most obvious problem I ran into is that you often have to apply it manually:
{{ .Title | markdownify }}
Things that are cool about Hugo
- Those thousands of pages rebuild in about 15 seconds. Of course, that’s comparing to a Pentium III running MovableType, so it may not be that impressive.
- Aliases so I can trivially preserve 14-year-old permalinks.
- /data has all sorts of uses for extending functionality.
- When your site is too big for testing with LiveRebuild:
hugo server --contentDir samplecontent --theme newversion
- Can completely suppress a page type by creating a zero-length template file, if you can figure out what its name should be (generates a long string of warnings if you use
-v
, but it works perfectly and speeds up rebuild time):-
layouts/$section/single.html
(no single pages) -
layouts/section/$section.html
(no list page; with above, only visible by taxonomy)
-
- Speaking of which, my script
wikiblog.sh
(link in reply, since new users can’t include more than two) creates a bunch of content entries with random author, categories, date, tags, and text from wikipedia (converted to Markdown with pandoc), and can also optionally assign a batch of entries to a series. - It’s kind of hilarious to set
paginate=2
and hear my fans spin up. - Despite the problems listed above, it only took about two hours to get to a functional site and (unstyled) theme from scratch. Another three hours and I had pagination and all the side/microblogs working, and had figured out how to attach the old comments to their entries.
- Once I had a working ugly site, it took about fifteen minutes to convert the example blog style from the Bootstrap distro into templates. And that’s counting the time it took to figure out how to use Bootstrap.