Inertia pages edit like Vite source, because that is what they are
Inertia is the best-supported stack in the Laravel family, because its pages are ordinary Vite source files. PortBay stamps the dev server it launches, so your page components get precise and structural editing with nothing installed. Pro, early access, opt-in.
How do I visually edit Inertia pages in a Laravel app?
An Inertia application is two things at once — a Laravel back end and a Vue, React or Svelte front end compiled by Vite — and which half a visual editor can reach decides what it can do. The Vite half is the good half. PortBay launches your dev server, so it adds source-location stamping to it from a config generated outside your repo, with nothing to install; your page components then carry their file, line and column and get precise and structural editing. The Blade shell around them is a server-rendered template and still edits by matching markup. Page settings are resolved from the route's Inertia page name to that page component, where a Head element is written — created, with its import, if the component has none. Pro, early access, opt-in.
Verified against the product, 2026-09-05.
An Inertia page on the Vite lane
PortBay runs your Inertia app at its own .test URL with trusted HTTPS, starts PHP-FPM and your Vite dev server, and dispatches board cards into it. The visual editor edits that same running app in your real browser — one live page, not a multi-frame design canvas.
Your first Inertia page edit
Four steps, and none of them installs anything. Inertia gets here by being a Vite project wearing a Laravel coat.
- Install PortBay and add your Inertia project
- Turn the visual editor on
- Start the project — your Vite server gets the stamping
- Open Edit in browser and change a page
Install PortBay and add your Inertia project
Homebrew installs the app and the bundled portbay CLI. PortBay identifies the Laravel family from composer.json plus artisan, checks composer.json for inertiajs/inertia-laravel before anything else in that family, then serves the app at its own .test hostname over trusted HTTPS with PHP-FPM running.
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 AccessStart the project — your Vite server gets the stamping
PortBay launches the Vite dev server that compiles your page components, so it hands Vite a generated config that imports and spreads your own and adds a source-location plugin carried inside the app. The generated file lives in PortBay's data directory, never in your repo. Nothing is added to package.json or composer.json.
portbay start myappOpen Edit in browser and change a page
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 your Inertia links and visits work normally. Switch to Edit, click an element in a page component, and the change is spliced into that exact span of the source file.
https://myapp.test/aboutTwo halves, two lanes
An Inertia route passes through a Blade shell and lands in a page component. Both are editable; only one of them is precisely mapped, and it is the one you spend your time in.
A Vue or Svelte page gets one extra tier over a React one: those formats are markup-first, so component usages carry coordinates too. In a .jsx or .tsx page, markup produced by a component you did not author has none.
<?php// routes/web.php — resolved to the page NAME, not to a Blade viewRoute::get('/about', function () { return Inertia::render('About');});?> // resources/js/Pages/About.jsx — precise + structural editingimport { Head } from '@inertiajs/react'; export default function About() { return ( <main> <Head title="About us" /> {/* Page settings write here. If this element is missing, it is created — along with the @inertiajs/react import — rather than the field being locked. */} <h1 className="hero">We build boats</h1> {/* stamped */} <p className="lede">Since 1994.</p> {/* stamped */} </main> );} {{-- resources/views/app.blade.php — the shell, markup-matching lane --}}<html> <head>@inertiaHead</head> <body class="antialiased">@inertia</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 →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
Because its pages are not Blade. An Inertia route renders a Vue, React or Svelte component compiled by Vite, and PortBay launches that dev server itself — so it can add source-location stamping from outside your repo, exactly as it does for any other Vite project. Blade renders on the server, where there is no such seam, which is why the other two lanes in the Laravel family behave differently.
No. Nothing goes into composer.json and nothing goes into package.json. The stamping plugin ships inside the PortBay app and reaches Vite through a generated config that imports and spreads your own, kept in PortBay's data directory. Uninstall PortBay and both manifests, your lockfiles and your vite.config are byte-for-byte what they were.
PortBay identifies the Laravel family from a composer.json plus an artisan file, then checks composer.json for inertiajs/inertia-laravel before checking anything else in that family. That order is deliberate: a project carrying both Inertia and Livewire is treated as Inertia, because that is the lane with the better capability rather than the one that happens to be alphabetically first.
Into the page component, not into a Blade view. PortBay resolves the route through routes/web.php to the Inertia page name the action passed — Inertia::render('About') gives About — then to the component file behind that name, and writes an Inertia Head element there. If the component has no Head yet, one is created and the import is added, rather than the field being reported as locked. Before that adapter existed, this entire lane refused Inertia projects.
In one respect, yes. .vue and .svelte are markup-first formats, so a component usage carries its own coordinate and an element rendered by one of your components still traces back to where you used it. .jsx and .tsx are script-first: host elements are stamped but component usages are not, because a capitalised tag there can be a TypeScript generic parameter list. The practical difference is markup produced by a library you did not author, which has no coordinate on a React page.
Yes, on the other lane. app.blade.php is a server-rendered template with no source stamping, so edits there are resolved by finding your markup in the file rather than by following a coordinate — which means text, class and attribute edits write, and structural edits are refused rather than guessed. In practice the shell is a handful of lines you rarely touch, and everything you do touch is in the page components.
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 project is shared over a public tunnel, and the edit bar works only on local .test hosts. Running an Inertia app on a real .test domain with trusted HTTPS, PHP-FPM and a managed database is in the free app.
Yes, on the page-component side. JSX, TSX and Vue are among the four formats where that structural edit is supported, so an element in a page component can be moved into a new component file, with the import added and the original span replaced by the tag. A span carrying a template expression is refused by name, because the values it uses are locals of the page and would not exist in the new file. The Blade shell does not get this: extraction is refused there rather than half-written, because a component means something different in a PHP template.

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