Eleventy layouts, edited whatever the template language
Eleventy lets one site mix Nunjucks, Liquid, Markdown and plain HTML. PortBay does not parse any of them — it matches the element you clicked back to the markup in your own file and rewrites it there. Pro, early access, opt-in.
How do I edit an Eleventy (11ty) site visually?
Eleventy is unusual among static site generators in letting one project mix template languages — Nunjucks, Liquid, Markdown and plain HTML side by side — which is exactly what defeats a visual editor built around parsing one template grammar. Matching the rendered markup back to the file that emitted it sidesteps the problem, because your own HTML looks the same in every one of those languages. That is how PortBay does it: click an element in your running site, retype it, and the change is written into the .njk, .liquid or .html file that holds that markup. Template expressions are refused rather than rewritten, and a page's title and description go into that page's own front matter instead of the shared layout. Structural edits — moving or wrapping an element — are refused too. Pro, early access, opt-in.
Verified against the product, 2026-09-05.
An Eleventy site, four languages deep
PortBay serves your Eleventy 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 Eleventy layout edit
Four steps. Nothing is added to package.json — Eleventy runs on the markup-matching lane, which needs no plugin because there is no dev-server seam a plugin could use.
- Install PortBay and add your Eleventy site
- Turn the visual editor on
- Open Edit in browser
- Change the layout, or change the page's front matter
Install PortBay and add your Eleventy site
Homebrew installs the app and the bundled portbay CLI. PortBay recognises Eleventy by its config file — .eleventy.js, eleventy.config.js, eleventy.config.cjs or eleventy.config.mjs — then serves the site 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 a page, then switch to Edit.
https://mysite.test/about/Change the layout, or change the page's front matter
Element edits go into whichever template file holds that markup — a layout in _includes, a partial, or the page itself. The Page settings panel writes title and description into the front matter of the content file behind that route, because a title written into the shared base layout would apply to every page that uses it. Tailwind design tokens are editable independently of all this: renaming one rewrites every class that references it across your templates in a single save.
Why the template language doesn't matter here
Eleventy's whole personality is that a project can mix languages. An editor that parses Nunjucks would then work on half your files. Matching markup instead works on all of them, at the cost of the precision tier.
The trade is explicit: no source coordinates means no structural editing and no moving elements around. What you get instead is a lane that behaves identically across every template language your site happens to contain.
{# _includes/base.njk — Nunjucks #}<!doctype html><html> <head> <title>{{ title }}</title> {# expression: written to the page's front matter, not here #} </head> <body> <header class="masthead"> <a class="brand" href="/">Acme Boats</a> {# literal markup: text, class and href all edit here #} </header> {{ content | safe }} </body></html> {% comment %} _includes/card.liquid — same site, other language {% endcomment %}<article class="card"> <h2 class="card-title">{{ item.name }}</h2> <p class="card-body">Built to order.</p> <!-- "Built to order." and every class here edit exactly the same way as the Nunjucks file above. Nothing in the editor knows or cares which language this is. --></article> ---# content/about.md — the page that names its layouttitle: "About us"layout: base.njk---
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 →Agent dev environment
Stack detection, runtimes, HTTPS, databases and mail, provisioned per project — the running app your agents verify their work against.
Explore →Asked before downloading
By its config file, and the list is exact: .eleventy.js, eleventy.config.js, eleventy.config.cjs or eleventy.config.mjs at the project root. A TypeScript config is not in that list, so a project using one is not detected as Eleventy today — worth knowing rather than discovering. Everything downstream, including which lane the project gets and where a page title is written, follows from that detection.
No, and that is the point of this lane on Eleventy specifically. PortBay locates the element you clicked by matching its markup in your source rather than by parsing a template grammar, so a Nunjucks layout, a Liquid include and a plain HTML page in the same project all behave identically. An editor built around one grammar would work on part of a mixed site and silently skip the rest.
Eleventy template expressions and tags are left alone. A value printed by an expression is not present in the file as words, so rewriting it would mean turning your template logic into a literal and changing every page that renders through it. PortBay refuses those edits and, where the value has a real home, points at it — a page title belongs in that page's front matter, so that is where the Page settings panel writes it.
Yes. What matters is which file contains the markup, not what role Eleventy assigns that file. If the element you clicked came from an include, the include is what changes; if it came from the base layout, the layout changes; if it was written inline in the page, the page changes. Anything that resolves to more than one place is put to you before it writes, rather than being applied to the first match.
No. Structural edits are refused on this lane rather than guessed at, because without a source coordinate there is no way to be certain which occurrence of a piece of markup you meant, and a wrong structural change to a shared layout breaks every page using it. Text, class and attribute edits, plus page settings, all write — that is proven against a real Eleventy fixture in PortBay's cross-stack test, which edits _includes/base.njk and reads the changed bytes back off disk.
Into that page's own portbay_head_code and portbay_body_code front-matter keys. PortBay installs one small include in the project 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 lives in your content file, so it is part of the same commit as the rest of your change.
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 Eleventy 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