Click a Rails view, change the .html.erb that rendered it
One line in your Gemfile and every element written as markup in your views carries its own file, line and column — through partials, layouts and collection rendering. Click it in the browser, change it, and the edit lands in the .html.erb. Pro, early access, opt-in.
How do I edit Rails ERB templates visually?
Editing an ERB template visually is a mapping problem. The browser sees a rendered heading, and nothing in that HTML says which of your layouts, partials or collection templates produced it. The editors that dominate this category do not solve it — they are rich-text fields for the people using your app, editing content in the database rather than the .html.erb in your repository. Recovering the mapping instead takes a template handler that stamps each element with its own source file, line and column while ERB compiles. PortBay ships one as a gem, portbay-erb-stamper, and edits are then byte-spliced back into that exact file. Coordinates survive partials, the layout, content_for blocks and collection rendering, because every template is stamped in its own source. Measured on served HTML against a zero-stamp control: 18 of 18 coordinates exact on Rails 8.1.3.1 and 7.2.3.
Verified against the product, 2026-09-05.
A Rails app on its own .test domain
PortBay runs your Rails app at its own .test URL with trusted HTTPS and a per-project database, and dispatches board cards into it. The visual editor edits that same running app in your real browser.
Your first ERB edit
Four steps. There is no initializer to paste, no config/application.rb edit, and nothing to clear afterwards.
- Install PortBay and add your Rails project
- Turn the visual editor on
- Add the gem to your development group
- Open Edit in browser and change something
Install PortBay and add your Rails project
Homebrew installs the app and the bundled portbay CLI. Add the project folder and PortBay detects Rails from your Gemfile and config/application.rb, provisions a database, and serves the app 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 AccessAdd the gem to your development group
That is the whole install. The gem carries a Railtie, which Rails loads for every gem in your Gemfile, and the Railtie registers the ERB template handler — so there is no initializer and no application.rb change. Restart the server and stamping is live. Unlike Laravel, there is nothing to clear: Rails compiles ERB in memory and has no on-disk template cache to go stale.
group :development do gem "portbay-erb-stamper" endOpen Edit in browser and change something
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 page stays fully interactive. Switch to Edit, double-click text to type into the live page, then Save to write to source.
https://myapp.testWhat a Ruby-built element cannot give you
The stamper reads your templates as markup. An element you wrote as a tag gets a coordinate; an element Rails assembled from a helper call has no source tag to stamp, and falls back to a text search. Both still edit — one is exact, the other has to be unambiguous.
So a view written the ordinary way maps element for element. A view assembled entirely out of tag and content_tag calls still edits, but PortBay has to find the string rather than being told where it lives.
<%# written as markup — stamped, resolves exactly %><h1 class="pb-hero">Parity heading</h1><%# served as: data-pb-loc="app/views/pages/about.html.erb:2:1" %> <%# built in Ruby — no source tag exists to stamp %><%= tag.h1 "Parity heading", class: "pb-hero" %><%= content_tag :div, "Box", class: "pb-box" %><%= link_to "About", about_path, class: "nav" %><%# resolves by text search instead, and only if unique %> <%# never touched at all: %><%# .text.erb .json.erb .js.erb .xml.erb %>
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 →Local databases
Six engines, one wizard: isolated data dirs, dedicated ports, supervision, and connection vars injected into linked projects on start.
Explore →Asked before downloading
No, and that is the main confusion worth clearing up. Froala, TinyMCE and the rest of that category are WYSIWYG fields you embed in your app so that end users can write content, which is then stored in your database. This is a developer tool: it edits the .html.erb templates in your repository, and the change shows up in git.
One line in the :development group of your Gemfile, then a restart. The gem ships a Railtie, and Rails loads a Railtie for every gem in the Gemfile, so it registers the ERB template handler itself. There is no initializer to paste, no config/application.rb edit, and no TEMPLATES-style configuration to maintain. It requires Ruby 3.1 or newer and ActionView and Railties 7.0 or newer.
Yes — that is the part worth checking, because it is where naive approaches break. Each template is stamped in its own source, so an element in a partial points at the partial, and an element in a content_for block that renders through the layout's yield points at the block, not the layout. On served HTML measured against a zero-stamp control, 18 of 18 coordinates were exact on both Rails 8.1.3.1 and 7.2.3, covering the layout, a page view, a rendered partial, a content_for block, and a three-row collection render.
Yes. A Turbo Frame response is markup the server rendered through the same stamped templates, so the coordinates arrive with it — a Turbo Frame response measured 3 of 3 exact in the same run. That is a real difference from stacks that swap in markup assembled on the client, where the server never saw the fragment.
Elements built with tag or content_tag carry no coordinate, because there is no source tag in your template to stamp. An element written as <h1 class="hero"> gets a stamp; the same element written as tag.h1 does not. Those still edit — PortBay resolves them by searching your source files and refuses rather than guessing when the match is ambiguous — but you lose the exactness the stamper gives you elsewhere. Only .html.erb is stamped; .text.erb, .json.erb, .js.erb and .xml.erb are never touched.
No. The stamp is applied to the template source in memory, on its way through ActionView's ERB handler — the file on disk is never opened for writing, so no data-pb-loc and no marker attribute ever reaches your repository. When you save an edit, PortBay splices only the bytes that changed: a one-class change shows up in git diff as one changed token, and a multi-line attribute keeps its indentation.
No. It is a Pro feature, still in early access behind an opt-in toggle in Settings, and it is not compiled into the open-source build. It is also unavailable on a project while that project is publicly tunneled — the edit bar and its write-back endpoints are never routed onto public traffic. Running the Rails app, the database, the .test hostname and trusted HTTPS are all in the free, open-source 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