Desktop app

The desktop app is the same Emet, wrapped in Electron and pointed at a folder on your disk instead of a repository on GitHub. You open a Hugo site, edit it, and the files change on disk; there’s no sign-in, no commits and no network involved. It also runs Hugo’s own dev server for you, which is the main reason to use it.

When you’d want it#

The web version previews your content by rendering Markdown with your site’s CSS, which is a decent approximation but only that. If you have Hugo installed, the desktop app can instead start hugo server against the folder you’ve opened and show the real rendered page in the preview pane, drafts and future-dated posts included. Save a file and Hugo rebuilds it. See Local Hugo server.

The other reason is simply that you’d rather work on a local checkout. Writes go straight to disk, so there’s nothing to push and nothing to wait for, and you commit whenever you like with your usual Git tooling.

That said, it’s worth being clear about what the desktop app doesn’t do:

  • It doesn’t talk to GitHub at all. There’s no sync, no pull requests and no Sync with Production button; that’s all the web version’s job.
  • It doesn’t watch the folder. If you edit a file in another program while Emet has it open, Emet won’t notice until you reload (View > Reload) or reopen the site. The plumbing for watching is in the main process, but nothing in the UI uses it yet.
  • It doesn’t generate configuration. The folder you open needs an admin/site.yaml already (and, at the moment, an admin/cms.yaml too; see Installation). Run the web dev server against the site once, or write the files by hand, before opening it here.

Opening a site#

On launch you get a splash screen with an Open Hugo Site button and, once you’ve opened a few, a list of recent sites. File > Open Hugo Site… (Cmd+O on a Mac, Ctrl+O elsewhere) does the same from the menu. Pick the folder that contains your Hugo config, and Emet reads admin/site.yaml and admin/cms.yaml from it and opens the editor.

You can skip the splash screen by setting HUGO_ROOT before launching: the app opens that site straight away. This is how npm run dev:desktop is normally run during development.

Everything from the web version is here apart from the GitHub-specific parts: sections, entries, data files, archetypes, the visual and Markdown editors, shortcodes, the SEO panel, AI assistance if you’ve configured a provider and the Hugo config editor.

How it’s put together#

Electron apps have a Node.js main process and a browser-like renderer, and the two talk over IPC. In Emet:

  • src/main/ is the main process. It creates the window, builds the menu, owns the Hugo server process and handles filesystem requests from the renderer.
  • src/preload/ is the bridge. It exposes a typed window.electronAPI object to the renderer using Electron’s context bridge, and that object is the only way the renderer can reach the filesystem.
  • The renderer is the normal React app from src/. It checks for window.electronAPI on startup; if it’s there, it uses the Electron content backend instead of GitHub or the local dev server.

The channel names and payload types shared by all three live in src/shared/ipc-types.ts.

The renderer runs with context isolation on, Node integration off and the sandbox enabled, so a bug in the editor can’t reach your filesystem directly. Every filesystem request is checked against the folder you opened, and anything outside it is refused. Links opened in your browser from the app are limited to http: and https: URLs.

Where next?#