Stop babysitting npm run dev — Grove 0.5
Grove 0.5 supervises your site's long-running dev processes — the Vite dev server and a queue worker — with one click, over trusted local HTTPS, with logs in the dashboard. No terminal panes to babysit.
Every Laravel dev has the same little ritual. Open the project. Split the terminal. npm run dev in one pane, php artisan queue:work in another, maybe php artisan pail for logs, and — if you're on the modern skeleton — composer run dev to juggle all of it at once. Then you actually start working. And when you switch projects, you do the whole dance again.
It's a small tax. But it's a daily one, and it's the kind of thing your local environment should just handle. So Grove learned to.
In 0.5, Grove runs your site's long-running dev processes for you — the Vite dev server and a queue worker — with one click, over trusted HTTPS, with the logs right in the dashboard. No terminal panes to babysit.
Why: Grove already serves the app
Here's the insight that makes this clean. composer run dev actually starts four things via concurrently:
php artisan serve # a dev web server
php artisan queue:listen
php artisan pail # tail logs
npm run dev # Vite / HMR
But under Grove, the web server part is redundant — Grove already serves your app on https://myapp.test via its own FastCGI + FPM. And pail? Grove has a Logs panel. So the only things actually left to run are Vite and, if your project has a real queue, a worker.
That's exactly what Grove now supervises — nothing more, nothing you don't need.
How: one toggle, or one command
In the desktop app, every site in the Sites table has a ⚡ button:
🖥 Sites
┌───────────────────────────────────────────────────────────────┐
│ HOST DRIVER PHP NODE HTTPS ACTIONS │
│ elyra-web.test laravel 8.4 — 🟢 ↗ ⚡ 🌍 📁 🗑 │ ← ⚡ = run dev
└───────────────────────────────────────────────────────────────┘
Click ⚡ and Grove starts Vite (and a queue worker if you have one), using that site's Node and PHP versions, running as you (not root), with output streamed to the Logs panel. Click again to stop.
Prefer the terminal? It's a Grove-aware composer run dev:
$ grove dev start elyra-web
✓ dev started for elyra-web: vite
$ grove dev list
● dev running: elyra-web
And in the logs:
VITE v8.1.0 ready in 113 ms
➜ Network: https://elyra-web.test:5173/
Notice that https. Which brings us to the interesting part.
The part that took some doing: Vite over trusted HTTPS
Your site is served over HTTPS (https://myapp.test), so the Vite dev server has to be HTTPS too — otherwise the browser blocks the assets as mixed content, and you get a sad, unstyled page.
Grove handles this without you configuring anything, and — importantly — without borrowing any other tool's directories. When it starts Vite for an HTTPS site, it:
Issues a leaf certificate for the host, signed by Grove's already-trusted local CA.
Hands it to Vite via the standard
VITE_DEV_SERVER_CERT/VITE_DEV_SERVER_KEYenv vars thatlaravel-vite-pluginreads natively.
$ cat public/hot
https://elyra-web.test:5173
$ curl -sI https://elyra-web.test:5173/@vite/client | head -1
HTTP/1.1 200 OK # trusted cert — no -k needed
That's the same mechanism Herd uses — Grove just uses its own paths. So a plain, standard vite.config.js works everywhere:
export default defineConfig({
plugins: [
laravel({ input: ['resources/css/app.css', 'resources/js/app.js'], refresh: true }),
tailwindcss(),
],
});
No hard-coded cert paths, no tool lock-in. Portable between Grove and anything else.
Two honest gotchas we ironed out
Building this surfaced a couple of real bugs — the good kind, because fixing them makes the feature solid:
Orphaned dev servers. If the daemon restarted, its Vite children weren't cleaned up and kept squatting ports, so
public/hotwould drift to:5174,:5176… Grove now kills its dev processes on shutdown, so a restart always gives you a clean:5173.A strict Content-Security-Policy. A well-secured app can send a CSP so tight (
'self') that it blocks the Vite dev server — because the dev server, on its own port, is technically a different origin.curldoesn't care about CSP; your browser rightly does. The fix lives in the app: in local dev, allow the Vite origin. (Grove serves everything correctly; the browser was just enforcing the app's own rules.)
Both are the sort of thing you only hit once — and now you won't.
Getting it
Grove auto-updates. After it relaunches, restart the background service once (Tools → Restart daemon), then:
$ grove dev start myapp
✓ dev started for myapp: vite, queue
Open the site, edit a component, watch it hot-reload. No terminal panes, no artisan serve, no remembering.
That's the whole theme of Grove: take the plumbing you shouldn't have to think about — DNS, HTTPS, PHP, databases, tunnels, containers, and now your dev processes — and quietly handle it, so you can get back to building. One click, and your app is live-reloading. 🌱🌳