# Why doesn't Hugo use Liquid

**URL:** <https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951>\
**Category:** feature\
**Created:** [August 30, 2018, 3:30pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951 "2018-08-30T15:30:55Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![bristweb](https://avatars.discourse-cdn.com/v4/letter/b/d26b3c/32.png) [@bristweb](https://discourse.gohugo.io/u/bristweb)\
**Post date:** [August 30, 2018, 3:30pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/1 "2018-08-30T15:30:55Z")

</div>

Obviously since Hugo is written in Go language, it’s using [Go Templates](http://golang.org/pkg/html/template/). However, I’m curious about the decision-making on this relative to using Liquid for templating instead.

I’m very fresh to Hugo and SSGs generally, so it may be useful to know some of what I’ve noticed:

1. When I go to Liquid docs, I like what I see and find what I’m looking for quickly. When I go to Go templates page… I’m totally lost. I scroll for a bit, then give up and return to Hugo documentation or Google.
2. When I first saw `{{ block "main" . }}` I thought the period was a typo. I removed the period and wasn’t aware that Hugo failed to regenerate. This took me quite a while to realize that the period was required. While I understand why it has to be there now, it was not intuitive and the error wasn’t readily apparent when I saved the file without the period.
3. A significant number of the themes I took a look at could really use some help with DRY principles. I’m glad there is a decent selection, but once I start diving in I’m surprised to find code that is unnecessarily complex or repetitive. This is somewhat expected in any theme library, but I was really hoping for a better starting point that I could adapt to my own. Maybe have a small handful of “featured” themes? Instead, it looks like I need to start entirely from scratch just to get a well structured theme. I suspect the challenge of the Go Templates may be a factor driving down the quality of the themes.

So this leads to my question… why doesn’t Hugo use Liquid or at least offer it as an option?  
There are [ports](https://github.com/Shopify/liquid/wiki/Ports-of-Liquid-to-other-environments) of Liquid in Go… notably osteele/liquid.

- Perhaps liquid is not as efficient?
- Perhaps liquid is not as robust?
- Perhaps it’s too risky to depend on a third party library?

I’d really appreciate hearing thoughts and reasoning on this. Thank you.

---

<div class="post-metadata">

**Author:** ![alexandros](https://avatars.discourse-cdn.com/v4/letter/a/ecc23a/32.png) [@alexandros](https://discourse.gohugo.io/u/alexandros)\
**Post date:** [August 30, 2018, 4:05pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/2 "2018-08-30T16:05:25Z")

</div>

> [@bristweb](#):
>
> There are [ports](https://github.com/Shopify/liquid/wiki/Ports-of-Liquid-to-other-environments) of Liquid in Go… notably osteele/liquid.

I am not a Go Dev but the Liquid port you linked to above had its latest commit 3 months ago.

The Go html/template package is native to Go and actively maintained by the Go team. Latest commit in the html/template package was in [July](https://github.com/golang/go/commit/c5cb4843e174697dd060b42810b8d20f0998b2e6)

Also Liquid may be a terser templating language than Go templates but what is its performance? There is an [issue](https://github.com/osteele/liquid/issues/32) about adding benchmarks in the Liquid Go port repo that is currently open.

It seems that it is a bit premature to have this discussion about incorporating Liquid templates in Hugo.

---

<div class="post-metadata">

**Author:** ![bristweb](https://avatars.discourse-cdn.com/v4/letter/b/d26b3c/32.png) [@bristweb](https://discourse.gohugo.io/u/bristweb)\
**Post date:** [August 30, 2018, 4:57pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/3 "2018-08-30T16:57:19Z")

</div>

> [@alexandros](#):
>
> Latest commit in the html/template package was in July

Thanks for noticing that. It looks like the last update to Liquid was [may 15](https://github.com/Shopify/liquid/commits/master) and the last update to the Osteele port was [june 5](https://github.com/osteele/liquid/commits/master). So it seems like the port is updating right along with Liquid.

> [@alexandros](#):
>
> Also Liquid may be a terser templating language than Go templates but what is its performance? There is an issue about adding benchmarks in the Liquid Go port repo that is currently open.

Your question on performance is my question too! Good thoughts.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/totallyinformation/32/5668_2.png) [@TotallyInformation](https://discourse.gohugo.io/u/TotallyInformation)\
**Post date:** [August 30, 2018, 8:03pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/4 "2018-08-30T20:03:12Z")

</div>

> [@bristweb](#):
>
> However, I’m curious about the decision-making on this relative to using Liquid for templating instead.

Maybe because Liquid is **HORRIBLE**! 😖 That is one of the major reasons I quickly ditched Jekyll. Of course, their implementation of Liquid is even more horrible than the original. You can see some of my ranting here:

> **[GitHub Pages, Jekyll and Liquid](https://it.knightnet.org.uk/kb/ghjekyll/)**
>
> Hints and tips on using Jekyll for publishing to GitHub Pages. \\
> Note that these articles have been migrated from a Jekyll site and may not render correctly.

---

<div class="post-metadata">

**Author:** ![Jura](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jura/32/13581_2.png) [@Jura](https://discourse.gohugo.io/u/Jura)\
**Post date:** [September 3, 2018, 3:52pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/5 "2018-09-03T15:52:06Z")

</div>

> [@bristweb](#):
>
> When I go to Liquid docs, I like what I see and find what I’m looking for quickly. When I go to Go templates page… I’m totally lost. I scroll for a bit, then give up and return to Hugo documentation or Google.

I think (and hope) that this is irrelevant: Hugo users should not have to read Go documentation to understand Hugo.

Is there something missing from [Hugo’s own template documentation page](https://gohugo.io/templates/introduction/) that you hoped to find in the Go documentation? If we know what’s missing we can add it. 🙂

---

<div class="post-metadata">

**Author:** ![nfriedli](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/nfriedli/32/26027_2.png) [@nfriedli](https://discourse.gohugo.io/u/nfriedli)\
**Post date:** [September 4, 2018, 8:54am UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/6 "2018-09-04T08:54:33Z")

</div>

> When I first saw {{ block “main” . }} I thought the period was a typo. I removed the period and wasn’t aware that Hugo failed to regenerate. This took me quite a while to realize that the period was required. While I understand why it has to be there now, it was not intuitive and the error wasn’t readily apparent when I saved the file without the period.

Juste have a look here to understand the period / dot: [Hugo, the scope, the context and the dot | Regis Philibert](https://regisphilibert.com/blog/2018/02/hugo-the-scope-the-context-and-the-dot/)

---

<div class="post-metadata">

**Author:** ![kaushalmodi](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/kaushalmodi/32/2567_2.png) [@kaushalmodi](https://discourse.gohugo.io/u/kaushalmodi)\
**Post date:** [September 4, 2018, 11:41am UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/7 "2018-09-04T11:41:03Z")

</div>

You should first go through the Go Template Introduction in Hugo docs:

> **[Introduction to Hugo Templating](https://gohugo.io/templates/introduction/)**
>
> Hugo uses Go's \`html/template\` and \`text/template\` libraries as the basis for the templating.

That covers the **dot** too. If you would like more details, refer to the blog post by @regis that @nfriedli linked.

Go Templates are awesome! You’ll start appreciating the **dot** once you get it. 🙂

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/totallyinformation/32/5668_2.png) [@TotallyInformation](https://discourse.gohugo.io/u/TotallyInformation)\
**Post date:** [September 4, 2018, 7:27pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/8 "2018-09-04T19:27:37Z")

</div>

> [@bristweb](#):
>
> A significant number of the themes I took a look at could really use some help with DRY principles. I’m glad there is a decent selection, but once I start diving in I’m surprised to find code that is unnecessarily complex or repetitive. This is somewhat expected in any theme library, but I was really hoping for a better starting point that I could adapt to my own. Maybe have a small handful of “featured” themes? Instead, it looks like I need to start entirely from scratch just to get a well structured theme. I suspect the challenge of the Go Templates may be a factor driving down the quality of the themes.

Well, I know nothing at all about Go. But I can say this. When I first started using Jekyll, it took me a lot longer to get something working than it did in Hugo. In Hugo, I quickly ditched the idea of using someone’s template as none fitted what I wanted (something similar to the Wordpress 2016 theme). Writing a Hugo template from scratch was remarkably straight forwards.

It is true that some of the documentation requires about 5 reads before I understand it. But that is more about documentation style than Hugo utility or ease of use. Of course there are oddities, all frameworks have oddities, but Hugo’s seem a lot less than competitors. But that is only my view of course 🙂

Jekyll’s use of Liquid drove me absolutely up the wall in no time at all and I found it far more complex to use and very inconsistent in places as my ranting blog post will indicate.

With Hugo, I have found very few inconsistencies and I’ve also found it to be very robust overall, another issue with Jekyll.

Not trying to knock Jekyll, I know a lot of people use it. But it wasn’t for me. I looked at and tried a lot of options when searching for alternatives to Wordpress. I’m more of a Node.JS person so my main aim was that and I was very reluctant to try something based on GoLang. Glad I did though, not looked back since. Still always hoping that I never have to learn GoLang though! One bonkers language (JavaScript) is enough for me!!

---

<div class="post-metadata">

**Author:** ![bristweb](https://avatars.discourse-cdn.com/v4/letter/b/d26b3c/32.png) [@bristweb](https://discourse.gohugo.io/u/bristweb)\
**Post date:** [September 4, 2018, 7:56pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/9 "2018-09-04T19:56:19Z")

</div>

Since I really want to use Hugo for speed, I hope my detailing the templating problems will help bring improvements. As a long time front end developer, but a Hugo novice, here’s how it went for me reading Hugo’s Introduction to templating:

> The following is only a primer on Go templates. For an in-depth look into Go templates, check the official Go docs.

Immediately I’m thinking I should be reading the Go website instead of Hugo’s tutorial… but when I visit Go’s site, I read and read and read… then finally come back to Hugo’s site.

> ### Access a Predefined Variable
> 
> {{ foo }}

I really wish there was a normal “hello world” or real example here. It isn’t clear what a “predefined” variable is. Does “predefined” mean a “global”… or something built into GoLang or Hugo… or something simply defined in the build… dunno so I keep going…

> This is how you access a `Page` variable from a template:
> 
> ```auto
> <title>{{ .Title }}</title>
> 
> ```
> 
> Values can also be stored in custom variables and referenced later:
> 
> ```auto
> {{ $address := "123 Main St."}}
> {{ $address }}
> 
> ```

It isn’t clear why one is accessed from dot notation why the `$` was introduced. Why not treat everything as an object? Already I am sensing an inconsistency that will be confusing.

> ### Example 2: Comparing Numbers
> 
> ```auto
> {{ lt 1 2 }}
> 
> ```

Again confused… is this a hint that operators are not available? what about `{{ 1 < 2 }}` instead? Also what does this look like in the context of a web page? Does this statement print `true` or does it evaluate as true for an if statement?

> ## Includes
> 
> To pass along the current context, please remember to include a trailing **dot**.
> 
> ### Partial
> 
> ```auto
> {{ partial "header.html" . }}
> 
> ```
> 
> ### Template
> 
> ```auto
> {{ template "_internal/opengraph.html" . }}
> 
> ```

At this point I’m getting really confused. What is the difference between “include” (which has no example), “partial” and “template” This seems like all the same concept and should use the same notation. I’m now afraid building templates will be very tedious from constant semantic issues.

> ```auto
> {{ range array }}
> {{ . }}
> {{ end }}
> 
> ```

I have no idea what I’m supposed to understand from this block.

> By default, Go Templates remove HTML comments from output.

Why would it do this unexpected behavior? Commenting is already available via `{{/* comments here... */}}`

> Go 1.6 includes the ability to trim the whitespace from either side of a Go tag by including a hyphen ( `-` ) and space immediately beside the corresponding `{{` or `}}` delimiter.

Why in the world would a newline be included that I didn’t request? Immediately I think it should say: "write all your code blocks as `{{- .Title -}}` to avoid random newlines.

> [@kaushalmodi](#):
>
> You should first go through the Go Template Introduction in Hugo docs:
> 
> [Introduction to templating](https://gohugo.io/templates/introduction/)
> 
> That covers the **dot** too. If you would like more details, refer to the blog post by @regis that @nfriedli linked.
> 
> Go Templates are awesome! You’ll start appreciating the **dot** once you get it. 🙂

I’m sure there are good reasons for this and I’ve now read a bunch about it. [Hugo’s documentation is decent too](https://gohugo.io/templates/introduction/#context-aka-the-dot). Unfortunately, this is exactly what I (and probably most front-end devs) don’t want to do. The following simply is not intuitive when I compare it to other systems:

`( .Params "title")`  
vs  
`$title := .Site.Title`  
vs  
`{{.Title}}`  
vs  
`{{ with .Params.title }}{{ . }}{{ end }}`

# summary

Again, the point of all this isn’t to bash Hugo or GoLang. The point is to illustrate how confusing this is for a template developer to get up and running so Hugo can be a bigger success! Parts may be related to GoLang and not specific to Hugo. However, I’m not looking to become a Go developer (I’m not interested in the details). Like most devs; I’m simply wanting to build a front-end effectively and efficiently (read: we are LAZY). The only time I’ve used liquid in the past was on Shopify sites that I’ve built, and it was up and running instantly. I’d love for Hugo to be that easy. If I could choose my template engine in Hugo, I’d rather have one that doesn’t take so much orientation time… even if it cost me a small performance hit in the compilation time.

There are many things that Hugo does well, such as the built in server and livereload.

---

<div class="post-metadata">

**Author:** ![alexandros](https://avatars.discourse-cdn.com/v4/letter/a/ecc23a/32.png) [@alexandros](https://discourse.gohugo.io/u/alexandros)\
**Post date:** [September 4, 2018, 8:40pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/10 "2018-09-04T20:40:58Z")

</div>

> [@bristweb](#):
>
> I’m sure there are good reasons for this and I’ve now read a bunch about it. Unfortunately, this is exactly what I (and probably most front-end devs) don’t want to do. The following simply is not intuitive when I compare it to other systems:
> 
> `( .Params "title")`  
> vs  
> `$title := .Site.Title`  
> vs  
> `{{.Title}}`  
> vs  
> `{{ with .Params.title }}{{ . }}{{ end }}`
> 
> ```auto
> 
> ```

Let me try to explain:

`( .Params "title")` : A front matter parameter called title. The shorthand syntax is `.Params.title`

`$title := .Site.Title` A custom variable that holds the global `.Site.Title` variable typically set in the config of a Hugo project

`.Title` The default `title` variable of any page in Hugo. If not set via a `.Params "title"` in the front matter of a markdown file or via the global `.Site.Title` it will default to the PATH of a page within the hierarchy of a Hugo project.

All of the above seem the same but they’re not quite the same.

Each one has its use case.

---

<div class="post-metadata">

**Author:** ![bristweb](https://avatars.discourse-cdn.com/v4/letter/b/d26b3c/32.png) [@bristweb](https://discourse.gohugo.io/u/bristweb)\
**Post date:** [September 4, 2018, 8:46pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/11 "2018-09-04T20:46:23Z")

</div>

> [@alexandros](#):
>
> All of the above seem the same but they’re not quite the same.

Thank you!

1. I’m still not clear what the difference is between `.Params.title` and `.Title`?
2. Why is “title” capitalized with the .Site object and not with .Params?

---

<div class="post-metadata">

**Author:** ![bep](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bep/32/3332_2.png) [@bep](https://discourse.gohugo.io/u/bep)\
**Post date:** [September 4, 2018, 8:52pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/12 "2018-09-04T20:52:11Z")

</div>

- `.Params` is a map/dictionary with key/values provided by the user
- `.Title` and similar are built-in fields or methods in Hugo. They are capitalized because that is the Go way of exporting fields/methods. Of course, `.Title` will also get its value from the user some how, but in some cases we create some default value or it is a calculated value etc.

---

<div class="post-metadata">

**Author:** ![kaushalmodi](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/kaushalmodi/32/2567_2.png) [@kaushalmodi](https://discourse.gohugo.io/u/kaushalmodi)\
**Post date:** [September 4, 2018, 9:17pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/13 "2018-09-04T21:17:58Z")

</div>

That’s some useful feedback. I have tried to cover most of your addressed points, and have refreshed that “Introduction to Hugo Templating”:

> **[Introduction to Hugo Templating](https://gohugo.io/templates/introduction/)**
>
> Hugo uses Go's \`html/template\` and \`text/template\` libraries as the basis for the templating.

---

<div class="post-metadata">

**Author:** ![bristweb](https://avatars.discourse-cdn.com/v4/letter/b/d26b3c/32.png) [@bristweb](https://discourse.gohugo.io/u/bristweb)\
**Post date:** [September 4, 2018, 9:36pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/14 "2018-09-04T21:36:13Z")

</div>

> [@kaushalmodi](#):
>
> That’s some useful feedback. I have tried to cover most of your addressed points, and have refreshed that “Introduction to Hugo Templating”:
> 
> [Templating | Hugo](https://gohugo.io/templates/introduction/)

MUCH appreciated. [Your commit](https://github.com/gohugoio/hugoDocs/commit/fac3df0433375cca9d9520b09a36eee28bd9cfca) really helps clarify a lot of my questions. I’ll read more on this, but thank you very much for this progress!

---

<div class="post-metadata">

**Author:** ![rdwatters](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/rdwatters/32/2848_2.png) [@rdwatters](https://discourse.gohugo.io/u/rdwatters)\
**Post date:** [September 5, 2018, 10:55pm UTC](https://discourse.gohugo.io/t/why-doesnt-hugo-use-liquid/13951/15 "2018-09-05T22:55:10Z")

</div>

In a way, a lot of @bristweb’s comments about the docs speak to this issue:

> <https://github.com/gohugoio/hugoDocs/issues/389>
