Entries

An entry is a Hugo content file: frontmatter on top, Markdown underneath. Emet reads the frontmatter into a form, hands the body to the editor, and on save writes the whole thing back as the same kind of file you’d have written by hand. If you open the file in a text editor afterwards, it should look like you did.

Which folders show up, and which fields each entry has, comes from the sections block of admin/site.yaml. See Sections for the config; this page is about what you do with them.

The entry list#

Pick a section in the sidebar and you get its entries, with _index.md pinned to the top and everything else sorted by date, newest first, falling back to title for entries without a date. A section’s sort setting can change that to title order, or oldest first (see Sections).

On GitHub-hosted sites, you’ll see filenames first and titles and dates a moment later. Fetching every file in full just to list it would be slow, so Emet shows you what it has and fills in the rest in the background.

Above the list there’s a search box (fuzzy, on titles; Ctrl+F jumps to it when you’re not in an editor) and a status filter with All, Draft, Scheduled and Published. An entry is a draft if its frontmatter says draft: true, regardless of date; a non-draft entry with a future date is scheduled; everything else is published. The filter survives drilling into subfolders but resets when you change section or language.

On a multilingual site the filter menu has a second group for translations: Missing in for each other language, Untranslated anywhere (with three or more languages) and Translation outdated. Under the list header, a line like DE 9/12 · FR 12/12 says how complete each language is for the entries you’re looking at, and clicking a language applies its Missing in filter. Keeping translations up to date covers both.

Entries with unsaved changes get a blue Unsaved badge. If you use the publication workflow, entries that differ from the production branch get an orange left border, so you can see at a glance what’s still waiting to go live. With entry review turned on, cards also show the entry’s review state, including Changed since approval for approved entries that have been edited since.

Each card shows the title with the date underneath. If the date isn’t the most useful thing to see there, set list.subtitle on the section to show the file’s path, its slug or any frontmatter field instead (see Sections). A field value is followed by the date.

Each entry card has a More actions menu with Translate (on multilingual sites), Duplicate, View on site (needs site.url) and Delete. A section with create: false loses Duplicate, and one with delete: false loses Delete, in bulk as well as one at a time. The checkbox icon in the list header turns on selection mode, which is how you get to bulk actions.

Recent entries#

Most of the time you want the thing you were working on yesterday. Pick Recent at the top of the section picker (it’s also what the sidebar shows before you’ve chosen a section) and you get the last fifteen entries you opened or saved on this site, newest first. The list is yours alone: it’s kept in your browser and survives a reload.

On GitHub-hosted sites there’s a second tab, Changed. It reads the last fifteen commits that touched content on your branch and lists the entries they changed, with who committed and when, which is handy for seeing what a colleague did this morning.

Searching every section#

Ctrl+K (or the magnifying glass in the header) opens a search across every section. With nothing typed it shows up to eight recent entries. As you type, it matches titles fuzzily, grouped by section, and then body text under In content, with a snippet around the first hit. Each result opens the entry, and has a View on site icon when site.url is set.

The catch is that Emet can only search what it has already seen. Sections you’ve browsed are complete; the rest are listed by filename when the search opens, and body text is only searchable for files Emet has fetched. The footer tells you how many that is (“X of Y entries searchable by content”), and Index all N entries fetches the rest, subfolders included. Nothing fans out across the repository until you ask for it.

Ctrl+K does nothing while your cursor is in an editor, where it’s the link shortcut.

Subfolders#

Hugo lets you nest content as deep as you like, and so does Emet. Subfolders inside a section appear as folder cards; click one to drill in, and use the breadcrumbs at the top of the list to get back out. If a subfolder is itself a declared section in site.yaml, clicking it switches to that section instead.

The folder icon in the header creates a new subfolder. You give it a title and a slug, and Emet writes a <slug>/_index.md with that title and today’s date, which is what Hugo needs to treat the folder as a section.

Creating an entry#

Click the + button in the list header. The modal asks for a title and shows the filename it’s going to use, which is the title slugified. You can edit the filename directly if you don’t like the result; whatever you type gets slugified too, so you can’t end up with spaces or capitals in it.

If the section has a slug pattern, the full filename is shown underneath. The pattern can use {{slug}}, {{year}}, {{month}} and {{day}}:

sections:
  blog:
    folder: content/blog
    slug: "{{year}}/{{slug}}"   # 2026/my-first-post.md

New entries start from the section’s archetype if it has one, and otherwise from a minimal frontmatter of title, date and draft: true. Either way the title is what you typed, the date is now and the entry is a draft, even if the archetype says otherwise.

Set create: false on a section to take the button away.

Editing an entry#

Opening an entry gives you a column with the frontmatter form at the top and the body editor below it. The frontmatter panel collapses (click Fields) and resizes (drag its bottom edge), and in focus mode it disappears along with everything else that isn’t the body.

To the right, optionally, is the preview pane, and beyond that a panel with SEO, AI, Comments and Review tabs, depending on what’s enabled. On a multilingual site, opening a translation side by side puts the source entry in a column on the left.

The frontmatter form#

Fields come from the section config, rendered according to their type; see Fields for all of them. A few things live in the panel that aren’t in your config:

  • URL settings: a Slug field (Hugo’s slug, empty by default, meaning the filename is used), an Aliases list, and the Filename. Editing the filename renames the file on your next save, which changes the page URL and, on multilingual sites, detaches the entry from its translations. Aliases are validated against Hugo’s rules, and an invalid one blocks saving until you fix it. Section index files can’t be renamed.
  • Inherited values: if an ancestor _index.md sets a value through Hugo’s cascade, the field shows it as inherited with an Override button. On a section’s own _index.md there’s a cascade editor for setting those values.
  • Extra keys: any frontmatter key that isn’t in the section config is still shown, with a type guessed from its value, and there’s an Add field row at the bottom for adding new ones. Emet never drops keys it doesn’t know about.

What happens to your frontmatter#

With YAML frontmatter, Emet edits the text rather than regenerating it. Comments, blank lines, key order, block or inline ([a, b]) style and the quote style of the values you change all survive a save, so the diff shows the fields you changed and nothing else. A few things don’t survive: indentation is reset to two spaces, anchors on changed values are lost, and a key you remove and add back goes to the end.

TOML frontmatter is still regenerated from the parsed values on every save, so comments and formatting in a +++ block are lost.

The draft field doesn’t appear in the form. It’s handled by the toggle in the panel header instead.

Draft, published, scheduled#

The Draft / Publish toggle in the panel header sets draft in the frontmatter. Clicking Publish on a draft asks you to confirm and offers to set the date to now, which is usually what you want for a post you’ve just finished. If the date is in the future the button reads Schedule instead, and the entry shows as scheduled until that time passes.

Note that scheduling only works if your site is rebuilt after the date arrives, which is your CI’s job, not Emet’s. If you’re using the publication workflow and a scheduled entry hasn’t reached the production branch yet, the panel says so.

Saving#

Ctrl+S (Cmd+S on a Mac), the save icon in the panel header, or :w if you’re in Vim mode. On GitHub-hosted sites every save is a commit to your branch; the commit message gets a [skip ci] suffix for drafts, so your site doesn’t rebuild for content nobody can see yet. Scheduled entries get a normal commit, since Hugo will build them as soon as their date arrives. See Sync for the details of that.

Unsaved edits live in your browser’s local storage, so a refresh or an accidental tab close doesn’t lose them. Navigating away from a dirty entry inside Emet prompts you first. There’s also a Discard link next to the save icon.

Conflicts#

Two people editing the same page is the classic way to lose work: you open a post, a colleague fixes a typo in it and commits, and your save quietly puts the typo back. Emet tries hard not to let that happen.

On GitHub-hosted sites, whenever you open an entry or come back to it (at most every five minutes, and again after you pull remote changes), Emet checks it against GitHub. If you have no unsaved edits and the file has moved on, it just loads the newer version. If you do have edits, a banner appears above the editor: “This file was changed on GitHub after you opened it. Your edits are safe, but saving would overwrite those changes.” Saving is blocked until you click Review changes and decide what to do. Changes that only affect formatting, like comments or key order in the frontmatter, don’t count.

If the change lands between that check and your save, GitHub rejects the save and you get the same dialog, titled “Save rejected: file changed on GitHub” rather than “This file changed on GitHub”. It lists their recent commits, and has two diff tabs, Their changes and Your changes, each compared with the version you started from. Then you choose:

  • Load their version (discard my edits) replaces your copy with what’s on GitHub now.
  • Apply my “‹field›” change to their version appears when all you changed was frontmatter. It takes their file, body and all, and sets just the field or fields you edited, which is usually what you want when you were only fixing a date or a tag.
  • Overwrite their changes with mine commits your copy over theirs. It asks again first, spelling out how many of their lines you’re about to erase, and the commit happens straight away. If the file was deleted on GitHub, this button reads Re-create the file with my copy instead.

Unsaved edits that come back from a previous session (see above) get a stricter version of the check. The banner says “Restored from your previous session – checking GitHub for newer changes…”, and saving waits until the check has finished. If it can’t reach GitHub, the banner turns red, saving stays paused and there’s a Retry button. Entries you’d opened but not edited are simply dropped from the restore after 24 hours.

Duplicating and deleting#

Duplicate in the card menu asks for a new title and creates a copy. Index pages can’t be duplicated.

Delete asks for confirmation first. The file is removed from your repository in a commit, so it’s recoverable from Git history, but it’s gone from the site on the next build. On GitHub-hosted sites a single delete is queued and pushed by the next sync, which means it can take up to half a minute to reach GitHub.

Where next?#