Skip to content
PortBay

Edit .astro files in the browser, with nothing added to your repo

PortBay launches your Astro dev server, so it registers source-location stamping under astro.config's own vite.plugins key from a config generated outside your repo. Nothing to install, and your project is byte-identical afterwards. Pro, early access, opt-in.

The short answer

Can I edit an Astro site visually without installing a plugin?

Visually editing an Astro project comes down to one question: can the tool trace a rendered element back to the .astro file that produced it? Astro vendors Vite rather than exposing it, and ignores a root vite.config entirely, so a plugin has to register under astro.config's own vite.plugins key. PortBay does that from a config it generates outside your repository and hands to the dev server it launches, so there is nothing for you to install and your package.json, lockfile and astro.config stay byte-identical. Every element in your .astro files then carries its file, line and column, and clicking one in the browser writes the change back into that exact span. Because .astro is markup-first, component usages carry coordinates too. The editor is Pro, in early access behind a Settings opt-in, and absent from the open-source build.

Verified against the product, 2026-09-05.

In the app

An Astro site with a stamped dev server

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 Astro project 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.

Walkthrough

Your first .astro edit

Four steps, and none of them adds a dependency. The stamping is already in place by the time astro dev finishes booting.

  1. Install PortBay and add your Astro project
  2. Turn the visual editor on
  3. Start the project — the stamping is already on
  4. Open Edit in browser and change something

Install PortBay and add your Astro project

Homebrew installs the app and the bundled portbay CLI. Add the project folder and PortBay recognises Astro, runs its dev server for you, 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, so there is no hidden entry point to find.

Settings › Account › Early Access

Start the project — the stamping is already on

PortBay writes an astro.config.mjs into its own data directory, importing and spreading your real config and adding one plugin under the vite.plugins key. Astro's --config flag takes a path relative to the project root, so that is how it is passed. Nothing is created inside your repo, and removing PortBay leaves package.json, node_modules and astro.config untouched.

portbay start mysite

Open 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 any text to type into the live page, then Save to write it into the .astro file. The right-hand rail also edits your Tailwind design tokens: rename one and every class referencing it is rewritten across your markup in the same save.

https://mysite.test
Without PortBay

What the stamp looks like on an Astro page

The coordinate is added while the dev server serves the file and exists only in the HTML that reaches your browser. Nothing is written into src/, before or after the edit.

Click the h1, retype it, Save, and line 5 columns 3 of about.astro changes. Your indentation, your attribute order, and no leftover attribute in git.

Questions

Asked before downloading

No. The plugin is compiled into the PortBay app, written out to PortBay's own data directory, and handed to Astro through a generated astro.config.mjs that imports and spreads your real one. Nothing is added to your repo: uninstall PortBay and package.json, node_modules and astro.config are byte-for-byte what they were. There is no package on npm for this and there never will be, because nothing needs to serve it.

Astro vendors Vite rather than exposing it, and ignores a root vite.config entirely. That was measured rather than assumed: a scratch minimal Astro project carried the same logging plugin twice, once in a root vite.config.ts and once under astro.config's vite.plugins, and only the astro.config one ever ran. A generated Vite config would point Astro at a file it never reads, so the Astro lane registers under astro.config and passes --config as a path relative to your project root, which is the spelling Astro's flag expects.

Not through the visual editor's source mapping. Astro pages, layouts and components in .astro are stamped; .mdx is explicitly refused because its top level is Markdown rather than markup, and a coordinate placed into prose would be wrong. Plain .md is not stamped for the same reason. In practice you edit the template that renders the content — the layout, the page, the component — rather than the prose body, which is what your existing content workflow already handles well.

Both, on this lane. .astro is a markup-first format, so a <Card /> tag carries its own coordinate alongside the host elements around it. That means an element rendered by one of your components still traces back to the line where you used it. This is a real difference from the .jsx and .tsx lane, where component usages are deliberately not stamped because a capitalised tag there can also be a TypeScript generic parameter list.

React, Svelte and Vue islands are stamped by extension, the same as anywhere else. .svelte and .vue islands are markup-first and get the full treatment including component usages. .jsx and .tsx islands get their host elements stamped but not their component usages, so markup produced by a UI library you did not author carries no coordinate. Everything you wrote yourself in an island still maps to its own line.

No. The plugin declares apply: 'serve', so it is loaded for the dev server and never for astro build. There is also nothing to leave behind in your source, because the attribute is added while a file is served rather than written into it — the difference from editors that insert their own id attributes into your components and expect you to strip them before shipping.

PortBay's visual editor 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 also refuses to run while a project is shared over a public tunnel — stop the share first — and the edit bar is limited to local .test hosts. Everything else on this page, including running your Astro dev server on a real .test domain with trusted HTTPS, is in the free app.

Yes — Astro is one of the four formats where that structural edit is supported, alongside JSX, Svelte and Vue. The element's authored span moves out of the page into a new component file, an import is added to the page's script region, and the span it left behind becomes a tag. One refusal is deliberate and named rather than silent: a span carrying a template expression is refused, because a value that was a page local would not exist in the new file and the splice would leave you with a project that no longer builds.

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