If you “compile from source”, have a go at it and tell me what you think …
This commit adds support for a configuration directory (default config). The different pieces in this puzzle are:
A new --environment (or -e) flag. This can also be set with the HUGO_ENVIRONMENT OS environment variable. The value for environment defaults to production when running hugo and development when running hugo server. You can set it to any value you want (e.g. hugo server -e "Sensible Environment"), but as it is used to load configuration from the file system, the letter case may be important. You can get this value in your templates with {{ hugo.Environment }}.
A new --configDir flag (defaults to config below your project). This can also be set with HUGO_CONFIGDIR OS environment variable.
If the configDir exists, the configuration files will be read and merged on top of each other from left to right; the right-most value will win on duplicates.
Given the example tree below:
If environment is production, the left-most config.toml would be the one directly below the project (this can now be omitted if you want), and then _default/config.toml and finally production/config.toml. And since these will be merged, you can just provide the environment specific configuration setting in you production config, e.g. enableGitInfo = true. The order within the directories will be lexical (config.toml and then params.toml).
Some configuration maps support the language code in the filename (e.g. menus.en.toml): menus (menu also works) and params.
Also note that the only folders with “a meaning” in the above listing is the top level directories below config. The menus sub folder is just added for better organization.
We use TOML in the example above, but Hugo also supports JSON and YAML as configuration formats. These can be mixed.
An observation I made while using the -e flag with one of my build pipelines: if the environment is set with hugo -e it can’t be accessed with getenv "HUGO_ENVIRONMENT". So the docs should make it clear that getenv can only access system environment variables and not the internal one.
Something else worth mentioning in the docs, as a “gotcha”. Say I have basic config dir like this
config
└───_default
config.toml
params.toml
With config.toml like
[params]
param1 = "Number 1"
And params.toml like
[params]
param2 = "Number 2"
When you loop through all params
{{ range $key, $value := .Site.Params }}
{{ $key }} = {{ $value }}
{{ end }}
Output is
param1 = Number 1
params = map[param2:Number 2]
It wasn’t obvious to me at first, but I realized I was inadvertently nesting params, since the 2nd TOML params map was being added to the 1st params map. So after tweaking params.toml to be
Sure, but I hope it is clear why it behaves like this. I think it would have been a bigger gotcha if you had to repeat the root key inside the params file. That would have been totally different from, say, how /data works.