Skip to content
PortBay

Click a Next.js element, change that exact span of .tsx

One dev dependency and six lines in next.config, and the elements you wrote are mapped to their exact line of source. Click one in the browser, change it, and PortBay rewrites that span of the .tsx. Pro, early access, opt-in.

The short answer

How do I edit a Next.js app visually?

Editing a React app visually means mapping a rendered DOM node back to the JSX that produced it, and a browser cannot do that alone: by the time an element reaches the page, the component boundary, the file and the line are gone. There are two ways to recover them. Write id attributes into your source and read them back, which leaves markers in your components — or add the coordinate during compilation and never persist it. PortBay takes the second route. An SWC plugin, @portbay/swc-plugin-loc at 0.1.1 or newer, stamps each element you wrote with its file, line and column under Turbopack and webpack alike, and an edit is rewritten into the .tsx through a tree-sitter path. One gap is real: markup rendered by a component you did not author carries no coordinate.

Verified against the product, 2026-09-05.

In the app

A Next.js app with its source mapped

acme-shop · Board6 cards3 agents online
Pending2
infra
Rate-limit the API
P1
Dark mode polish
P2
Todo2
auth
Add OAuth login
P0Claude Code0/3oauth-login
Auto-dispatching
implement OAuth on app.test
db
Migrate to Postgres
P1
In Progress1
Fix flaky checkout test
P0
Done2
Set up Mailpit inbox
P2
Seed demo data
P2
1/5 · AssignA card lands in Todo and @claude is mentioned

PortBay runs your Next.js project at its own .test URL with trusted HTTPS and dispatches board cards into it. The visual editor edits that same running app in your real browser — one live site, not a multi-frame design canvas.

Walkthrough

Your first JSX edit

Five steps from a running Next.js app to a change written into a .tsx file. The version floor in step three is not optional — read it.

  1. Install PortBay and add your Next.js project
  2. Turn the visual editor on
  3. Install the SWC plugin — version 0.1.1 or newer
  4. Register it in next.config
  5. Restart the dev server and open Edit in browser

Install PortBay and add your Next.js project

Homebrew installs the app and the bundled portbay CLI. Add the project folder and PortBay detects Next.js, runs your dev server, and serves it at its own .test hostname over trusted HTTPS.

brew tap portbay-app/portbay && brew install --cask portbay

Turn 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 Access

Install the SWC plugin — version 0.1.1 or newer

The floor matters more than it looks. Version 0.1.0 emits no stamps whatsoever under Turbopack, and no error either: Turbopack hands the plugin a project-relative filename where webpack hands it an absolute one, and 0.1.0 gives up on that silently. A plain ^0.1 range resolves both, so pin the floor. If your lockfile already has 0.1.0, upgrade it.

npm install --save-dev @portbay/swc-plugin-loc@^0.1.1

Register it in next.config

Add ['@portbay/swc-plugin-loc', { root: process.cwd(), enabled: process.env.NODE_ENV !== 'production' }] to experimental.swcPlugins. Two details are load-bearing: use the bare package specifier rather than require.resolve, which hands Turbopack an absolute .wasm path it cannot load, and use process.cwd() rather than __dirname, which does not exist in an ESM config. PortBay does not write this file for you — unlike Vite, next dev reads its config only from your project root and resolves SWC plugins only from your node_modules, so PortBay hands you the text instead of changing your project.

next.config.js › experimental.swcPlugins

Restart the dev server and open 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 page is fully interactive. Switch to Edit, double-click text to type into the live page, then Save to write to source.

https://myapp.test
Without PortBay

The same className change, done by hand

React makes the round trip long. You see a button in the browser, and nothing in the DOM tells you which of nine files declared it or which of three components wrapped it on the way out.

With the plugin registered the element itself names app/(marketing)/page.tsx line 88 — so the edit lands on the usage you clicked rather than on the shared primitive that would have changed nine other pages.

Questions

Asked before downloading

Does PortBay's visual editor write data-id or marker attributes into my React components?

No, and this is the main thing separating PortBay from the category. The data-pb-loc stamp exists only in the HTML your dev server renders — it is added during compilation and never written to a file in your repo. Nothing is left behind to clean up before shipping, no attribute survives into git, and the plugin self-gates on NODE_ENV so a production build emits nothing at all.

Why does PortBay's Next.js plugin need version 0.1.1 specifically?

Because 0.1.0 fails silently under Turbopack. Turbopack passes the plugin a filename relative to the project root where webpack passes an absolute one, and 0.1.0 gives up on the relative form without logging anything — you get a dev server that returns HTTP 200 with zero stamps and no clue why. 0.1.1 handles both. A ^0.1 range resolves either version, so pin ^0.1.1 or a stale lockfile will keep serving you the broken one.

Does PortBay's visual editor work with Turbopack, or only webpack?

Both, at 0.1.1 and above. That was verified against the served HTML of a real Next 16.3.x app running on default Turbopack, with a 0.1.0 build as the negative control. Next 16 uses Turbopack by default and Next 15 uses webpack by default; the same config key, experimental.swcPlugins, covers both.

Will PortBay edit my next.config for me?

No, deliberately. It hands you the exact text to paste and changes nothing in your project. Vite and Astro projects get stamping for free because PortBay launches those dev servers and can pass its own config from outside your repo, but next dev reads its config only from your project root and resolves SWC plugins only from your node_modules — so instrumenting Next.js without touching your project is not possible, and PortBay asks rather than doing it behind your back.

What can't PortBay's visual editor map in a React app?

One tier, and it is worth stating plainly: an element produced by a component you did not author — a UI library's own markup — carries no source coordinate. The elements you wrote are stamped; the ones a dependency rendered are not. The reason is that in a .tsx a capitalised tag can be a TypeScript generic parameter list rather than a component, and guessing wrong would insert a syntax error into your module, so PortBay stamps host elements only rather than guessing.

Can PortBay's visual editor edit className in Next.js, or only text?

Both. A className edit goes through a tree-sitter JSX path that rewrites the attribute in place, and the right-hand rail covers layout, spacing, size, position, typography, backgrounds, borders and effects. Text is edited by double-clicking it in the live page rather than typing into a panel field.

Can PortBay's visual editor do more than change text and classes in Next.js?

Two capabilities are worth knowing about. Renaming a Tailwind design token rewrites every reference to it across the project in the same save, so the definition and its uses never drift apart. And a selection can be extracted into a new component — that works on JSX, and on Astro, Svelte and Vue elsewhere in PortBay — with a by-name refusal when the selection contains a template expression it cannot safely move. Both write to your source the way any other edit does.

Is PortBay's visual editor an infinite canvas like the design-tool editors?

No. There is one preview: your real dev server, at your real .test URL, with your real routes and data, opened in your actual browser with a docked edit bar. There is no multi-frame canvas and no artboard model. If you want to compare two screens side by side, you open two browser tabs.

PortBay mascot — a friendly blue tugboat

Give your projects and your agents a real local home.

Download for macOS

Free & open source · macOS 11+ on Apple Silicon · Pro from $10/mo