/config dir support added, please take it for a spin

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).

├── _default
│   ├── config.toml
│   ├── languages.toml
│   ├── menus
│   │   ├── menus.en.toml
│   │   └── menus.zh.toml
│   └── params.toml
├── development
│   └── params.toml
└── production
    ├── config.toml
    └── 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.

Haven’t had a chance to test yet, but I think you grab it this way

Yep, that’s what he said, and it works that way. All I was saying is: Watch out, folks might mix things up if the docs aren’t clear about it :slight_smile:

I see what you mean now :+1:

Something else worth mentioning in the docs, as a “gotcha”. Say I have basic config dir like this


With config.toml like

  param1 = "Number 1"

And params.toml like

  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

param2 = "Number 2"

Output is good now

param1 = Number 1
param2 = Number 2

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.

Yep, it’s definitely clear. Just took me a bit to wrap my head around it

1 Like

A post was split to a new topic: Using environment flag with multiple config files

The config files under config/_default cannot be arbitrary files, right?

I was having:

  • /config/_default/config.yaml
  • /config/_default/tagclouds.yaml

But it wasn’t working. When I rename tagclouds.yaml to params.yaml then I get the config, but under the Params key.

I was hoping to split up my config and have the data from tagclouds.yaml under .Site.Params.Tagclouds.

No, they must match a top level config “struct”, e.g. params, menu(s), server, markup.

I have thought about splitting the params … but for your use case, you may consider just dumping your tagn clouds inside /data.

Thx!, Yes maybe it’s better to dump them inside `/data/ indeed.