A visual editor for Hugo layouts, not just front matter
The Hugo tools you have already found edit front matter and Markdown. This one edits layouts/_default/baseof.html and the partials under it — the template source, in your repo, with your Go template expressions left alone. Pro, early access, opt-in.
Is there a visual editor for Hugo that edits my templates?
Most tools that promise visual editing for Hugo are content editors: they give you a form over your front matter and Markdown, and the layout stays a developer's job. Editing the template itself needs something else — a browser session that can match a rendered element back to the layout file that emitted it. PortBay does that against your running hugo server: click an element, change its text, classes or attributes, and the change is written into layouts/. Hugo puts a real limit on this and it is worth knowing up front. Text that came from a Go template expression is not in the layout file, so those edits are refused rather than guessed; static markup in your layouts and content files is what edits. Page title and description go to that route's own front matter. Pro, early access, opt-in.
Verified against the product, 2026-09-05.
A Hugo site and its layouts
PortBay runs your Hugo site at its own .test URL with trusted HTTPS and dispatches board cards into it. The visual editor edits that same running site in your real browser — one live page, not a multi-frame design canvas.
Your first Hugo layout edit
Four steps, no dependency added to the site. Hugo needs no plugin here because there is no plugin that would help — see the section below for what that costs and what it does not.
- Install PortBay and add your Hugo site
- Turn the visual editor on
- Open Edit in browser
- Edit the template, or edit the page's front matter
Install PortBay and add your Hugo site
Homebrew installs the app and the bundled portbay CLI. PortBay recognises a Hugo site from a hugo.toml, hugo.yaml or hugo.json at the root, or from the very Hugo-specific archetypes/ directory — stat checks only, no directory walk — then serves it at its own .test hostname over trusted HTTPS.
brew tap portbay-app/portbay && brew install --cask portbayTurn the visual editor on
It ships to Pro under early access and is off by default. Sign in to Pro, then flip the Early Access toggle. The open-source build does not include the editor at all — it is not compiled in.
Settings › Account › Early AccessOpen Edit in browser
The project's Visual editing section has one button. It opens your normal browser at your normal .test URL with the edit bar docked at the top, booting in Preview mode where the site behaves exactly as it does now. Navigate to the page you want the ordinary way, then switch to Edit.
https://mysite.test/about/Edit the template, or edit the page's front matter
Two different targets share one bar. Element edits — text, classes, attributes — go into your layouts. The Page settings panel writes the title and description into the front matter of that route's own content file, not into the layout, because a value written into baseof.html would apply to every page and a value written into the generated output would vanish on the next build.
What Hugo lets you change, and what it doesn't
The limit here is Go templates, not the editor. Anything Hugo computed at render time is not in your file, so there is nothing in the file to rewrite.
PortBay refuses the interpolated cases rather than guessing at them, and it never writes into public/ — patching build output looks like it worked until the next hugo build erases it.
<!-- layouts/_default/baseof.html --><!doctype html><html> <head> <title>{{ .Title }}</title> <!-- interpolated: not editable here. The words came from the page's front matter, so the Page settings panel writes them there instead. --> </head> <body> <header class="masthead"> <a class="brand" href="/">Acme Boats</a> <!-- literal text and a literal class: both edit --> </header> {{ block "main" . }}{{ end }} <footer class="foot"> <p>Built in one shed since {{ .Site.Params.founded }}.</p> <!-- "Built in one shed since " edits. The year does not — it is an expression, and rewriting the expression is not the edit you asked for. --> </footer> </body></html>
The pieces underneath
Visual editor
Click an element on your running site in your own browser and edit its text, classes and styles straight into the source file, across 21 stacks.
Explore →HTTPS + .test domains
https://name.test per project: mkcert certificates, managed local DNS and a bundled Caddy edge, with expiry and reissue in view.
Explore →Asked before downloading
CloudCannon, TinaCMS and Decap edit content. They give an author a form over front matter and Markdown, which is genuinely useful and not what this is. PortBay edits the template: the element you click in the browser is located in layouts/, and the bytes that change are in your own .html file, in your repo, in your next commit. If your problem is that a marketing colleague needs to write posts, a content CMS is the better answer. If your problem is that changing the masthead means a build-refresh-squint loop, this is.
By a hugo.toml, hugo.yaml or hugo.json at the project root, or by the presence of an archetypes/ directory, which is specific enough to Hugo to be a reliable marker on its own. It is stat checks rather than a directory walk, so it costs nothing on a large site. The same helper is what tells PortBay to skip your generated public/ directory when writing, so the two can never disagree about what counts as a Hugo project.
Anything that came out of a Go template expression. Text inside {{ }} is computed at render time and is not present in the layout file as words, so PortBay refuses that edit instead of rewriting your expression into a string literal — which would silently break the page for every other route that uses the same layout. Static markup in your layouts, partials and content files is what edits, and that covers most of what you actually want to nudge visually.
Into the front matter of that route's own content file — content/about.md for /about/, resolved from the route rather than guessed. Not into baseof.html, because a title written there would apply to every page on the site, and not into the rendered HTML, because that lives in the generated output directory and would be erased by the next build. One caveat specific to Hugo: its singular image key has no reader, so that one field is refused rather than written.
Yes. The markup is stored under that page's own portbay_head_code and portbay_body_code front-matter keys, and PortBay installs a small render hook in the project once so the base template prints them into the real head and before the closing body tag. It is per-page rather than site-wide, and it is stored in your content file, so it survives in git like everything else here.
Never. Build output directories are excluded on purpose — public/ for Hugo, along with dist, build, out and the rest — because a change written there looks like it worked and disappears on the next build. PortBay treats that as fake persistence and refuses rather than producing an edit you would only discover was lost later.
No. It is a PortBay Pro feature, still in early access behind an opt-in toggle in Settings, and it is not compiled into the open-source build. It refuses to run while the site is shared over a public tunnel, and the edit bar works only on local .test hosts. Serving your Hugo site on a real .test domain with trusted HTTPS is in the free app.

Give your projects and your agents a real local home.
Download for macOSFree & open source · macOS 11+ on Apple Silicon · Pro from $10/mo