Hugo config editor

Most of the time you’re in Emet to write. Occasionally you need to change the site title, flip buildDrafts, add a menu entry or tweak a section’s fields, and for that you’d normally open the repository in a text editor. The config editor saves you the trip: it edits hugo.toml (or whatever your site calls it) and Emet’s own admin/site.yaml and admin/cms.yaml from inside the CMS.

Click the gear icon (Settings) in the header to open it. It takes over the main area until you close it, with three tabs: Hugo Config, Site Config and CMS Config. Each tab has its own Save and Discard buttons and an amber dot when it has unsaved changes. Closing with unsaved changes anywhere asks you to confirm.

The Hugo Config tab#

What it finds#

Emet looks in the site root for hugo.toml, hugo.yaml, hugo.yml, hugo.json, config.toml, config.yaml, config.yml and config.json, in that order, and uses the first one it finds. If there’s none, it looks for a config/ directory with environment subfolders like config/_default/ and config/production/.

Note that a site can have both. Hugo merges a root hugo.toml with config/_default/ and the environment folder, and so do Emet’s preview and its raw HTML check. The editor doesn’t: it shows and saves the root file only, so anything set under config/ is invisible here and left alone on save. If your site is laid out like that, edit the config/ files by hand.

With a split config you get an environment dropdown next to the title, with Default first. Picking an environment shows _default merged with that environment’s files, following Hugo’s rules: files named hugo.* or config.* merge at the top level, and a file named after a key (params.yaml, menus.yaml) is merged under that key. If the site has no config at all, the tab says so and suggests hugo new site.

Visual and raw modes#

The Visual mode is a form built from whatever’s in the file. There are no predefined fields: Emet reads each key’s value, picks a control to match (a toggle for booleans, a number input, a text input or a textarea for long strings, nested editors for lists and objects) and sorts the keys into collapsible sections. Supported settings explains which keys land in which section, and which ones the visual mode doesn’t show at all.

The Raw mode is a CodeMirror editor showing the config as text in its own format, TOML, YAML or JSON, with syntax highlighting. Switching from raw back to visual requires the text to parse; if it doesn’t, you’ll see “Invalid config format. Fix errors before switching to visual mode.” and stay in raw mode.

Raw mode isn’t the original file text. Emet parses the file on load and regenerates the text from the parsed data, so comments and formatting are already gone by the time you see it. Which brings us to saving.

Saving#

Save writes the config back and commits it (“Update Hugo config”, or “Update Hugo config (production)” for a split config) on GitHub-hosted sites, or writes straight to disk in local dev and the desktop app. On GitHub the file’s SHA is checked, so if someone else changed the file since you opened it the save fails rather than overwriting their change.

A few things to know before you rely on it:

  • Comments don’t survive. The file is regenerated from data on every save, in both modes. If your Hugo config is heavily commented, edit it by hand instead.
  • Split configs keep their split. On save, each top-level key goes back to the file it came from: params into params.yaml, menu into menus.yaml and so on for any key with a file named after it, and everything else into the environment’s main file (config/production/hugo.yaml, say). Those files are regenerated, so the same caveat about comments applies, but you don’t end up with everything flattened into one file. Named files can be .yaml, .yml, .toml or .json.
  • Environments only hold their differences. Saving a non-default environment writes only the keys that differ from _default. Set an override back to the _default value and it’s removed from the environment’s file (a section file like config/production/params.yaml is left empty rather than deleted). If the environment has no hugo.* or config.* file yet, one is created in the environment’s format.

There’s no validation beyond “does it parse”. Emet won’t tell you that baseURL isn’t a URL; Hugo will.

Warning
Changing the Hugo config can break your build. Emet commits straight to your working branch, so a typo in hugo.toml goes live on the next deploy unless you’re using the publication workflow. For anything more than a one-line change, raw mode and a careful read before saving is the sensible approach.

The Site Config and CMS Config tabs#

These edit admin/site.yaml and admin/cms.yaml (or wherever config_path points) and work the same way, with a couple of differences. They load when you first click the tab rather than up front. Visual mode groups the top-level keys into sections (Site, Content, Content Sections, Shortcodes, Media, Languages, Preview, Publishing and Integrations for site.yaml; Editor, AI, SEO and Preview for cms.yaml), with an Other Settings section for anything it doesn’t recognise. That currently includes some newer keys, like production_branch, working_branch and languages_layout in site.yaml and review in cms.yaml. Keys that aren’t in the file don’t appear, so for adding a whole new block, raw mode is quicker.

Raw mode here is the actual file text, so comments survive as long as you save from raw mode. Saving from visual mode regenerates the YAML and loses them.

If there’s no cms.yaml yet, the tab offers a Create cms.yaml button that starts you off with a two-line file. site.yaml has to exist already; the setup wizard makes one.

Saves commit as “Update site config” or “Update CMS config”. After a save you’ll see “Saved. Reload the page for changes to take effect.”, which is literal: Emet reads its configuration once at startup and doesn’t re-read it until you reload.

Where next?#