SolidStart routes, edited in the browser with nothing installed
SolidStart 2 runs Vite directly, which is the whole reason this works with nothing installed: PortBay launches that dev server and hands it a plugin from outside your repo. Click an element, change it, and the route file changes. Pro, early access, opt-in.
Can I edit a SolidStart app visually?
Whether a SolidStart project can be edited visually depends on which major version it is on, and the reason is the dev server rather than the framework. SolidStart 1 runs through vinxi, which accepts no config path, so nothing can add source mapping to it; SolidStart 2 dropped vinxi and its dev script is literally vite dev, with a real vite.config in the project root. PortBay launches that dev server, so on version 2 it passes a generated config that imports and spreads yours and adds a source-location plugin — nothing installed, project byte-identical. Click an element in your running app and the change is written into the route file that produced it. Title and description write into the same route's @solidjs/meta tags. A version 1 project still edits, by matching markup instead. Pro, early access, opt-in.
Verified against the product, 2026-09-05.
A SolidStart 2 app on Vite
PortBay runs your SolidStart 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 route, not a multi-frame design canvas.
Your first SolidStart route edit
Four steps. Check step three against your own package.json before anything else — it is the one thing that decides which lane you are on.
- Install PortBay and add your SolidStart project
- Turn the visual editor on
- Check which SolidStart you are on
- Open Edit in browser and change something
Install PortBay and add your SolidStart project
Homebrew installs the app and the bundled portbay CLI. Add the project folder and PortBay recognises SolidStart from @solidjs/start in your package.json, runs your dev server, and serves it 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 AccessCheck which SolidStart you are on
Open package.json and read the dev script. If it says vite dev, you are on SolidStart 2 and precise mapping is available with nothing installed. If it says vinxi dev, you are on the version 1 layout: everything still edits, but by matching markup rather than by following a coordinate, and structural edits are refused rather than guessed.
package.json › "dev": "vite dev"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 routing and signals still work. Switch to Edit, double-click text to type into the live page, then Save. Tailwind design tokens are editable from the same rail: renaming one rewrites every class that references it across your markup in one save.
https://myapp.test/aboutOne route file, markup and head together
Solid's meta components portal into the real document head from wherever they sit in the tree, which means a route's title lives in the same JSX as its markup. Both are editable, through different paths.
That is the evidence for the claim, taken on the HTML the browser actually received rather than on the config file, because a generated config being read is not the same thing as a generated config being obeyed.
// src/routes/about/index.tsximport { Title, Meta } from "@solidjs/meta"; export default function About() { return ( <main> <Title>About</Title> {/* Page settings */} <Meta name="description" content="About us" /> {/* writes here */} <h1 class="hero">We build boats</h1> {/* element edits */} <p class="lede">Since 1994, in one shed.</p> {/* write here */} </main> );} // Measured on served HTML, SolidStart 2.0 + vite 8.2.2, same project twice:// npm run dev -> 200, 3016 bytes, 0 coordinates// npm run dev -- --config <gen> -> 200, 3219 bytes, 5 coordinates:// src/routes/index.tsx:6:5 <main>// src/routes/index.tsx:8:7 <h1>// src/routes/index.tsx:10:7 <p>// src/routes/index.tsx:12:9 <a>// src/components/Counter.tsx:7:5 <button>
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 →HTTPS + .test domains
https://name.test per project: mkcert certificates, managed local DNS and a bundled Caddy edge, with expiry and reissue in view.
Explore →Asked before downloading
Why does the SolidStart version matter so much?
Because it decides whether there is a seam to instrument. SolidStart 1 runs its dev server through vinxi, which takes no flag pointing at a config, so a plugin cannot be handed to it from outside. SolidStart 2 dropped vinxi: the scaffold ships a direct vite dependency, a real root vite.config.ts, and a dev script that is literally vite dev. That is an ordinary Vite project as far as instrumentation is concerned, so it needs nothing added.
Do I have to install anything on SolidStart 2?
No. PortBay launches your dev server, so it passes a generated config that imports and spreads your own vite.config and adds a source-location plugin carried inside the app. The generated file lives in PortBay's data directory and never in your repo, so package.json, node_modules and vite.config.ts stay byte-identical whether PortBay is installed or not.
How do you know PortBay's stamps actually reach a SolidStart page?
The stamps were measured on served HTML rather than inferred from the config, because a generated config being right and a framework actually reading it have turned out to be different things more than once. Two runs of the same SolidStart 2 project, differing only in the flag: 3016 bytes and zero coordinates without it, 3219 bytes and five with it, naming real lines in src/routes/index.tsx and src/components/Counter.tsx.
What still works on a SolidStart 1 project?
Text, class and attribute edits, and page settings — all four write lanes. What is lost is the precision tier: without a coordinate, edits are resolved by finding your markup in the route files instead, structural edits are refused rather than guessed, and style edits go to a PortBay override sheet rather than into your source. PortBay says which mode it is in rather than degrading quietly.
Where do title and description edits go in SolidStart?
Into the route's own @solidjs/meta components — the <Title> and <Meta> tags in that file's JSX. They portal into the real document head at runtime from wherever they sit in the tree, so PortBay reads and writes them in place rather than trying to find a static HTML head that does not exist. A field the route has no tag for is inserted into the same tree.
What does PortBay's visual editor not map in a Solid route?
Component usages, the same as every other .tsx file. Host elements you wrote carry coordinates; a <Counter /> tag does not, so markup produced by a component you did not author has no coordinate to follow. The reason is that a capitalised tag in a .tsx can be a TypeScript generic parameter list rather than a component, and guessing wrong would insert a syntax error into your module.
Is PortBay's visual editor free for SolidStart?
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 refuses to run while the project is shared over a public tunnel, and the edit bar works only on local .test hosts. Running SolidStart on a real .test domain with trusted HTTPS is in the free app.
Can PortBay's visual editor pull a SolidStart element into its own component?
Yes, on the precise lane. JSX and TSX are among the four formats where that structural edit is supported, so an element in a route file can be moved into a new component file, with the import added and the original span replaced by the tag, all in one save. A span carrying a template expression is refused by name instead: the expression's route-local values would not exist in the new file, and the splice would produce source that does not compile.

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