the effing blog

Effing 0.37.0: dev servers, side by side

Run multiple dev servers without port juggling, plus two canvas fixes: SVG fragments now render, and an honest note about baseline alignment.

Effing 0.37.0 is out. The short version: you can now run as many effing dev instances as you like without thinking about ports, and two canvas quirks got sorted out.

Multiple dev servers, zero configuration

If you’ve ever had two Effing projects open at once — or one project and an agent working on another — you’ve probably met EADDRINUSE, the least helpful error message in the port-collision business. That’s gone.

effing dev now picks its own way out of a collision: when you haven’t chosen a port explicitly, it walks up from 3839 to the next free one. If you did choose a port (--port or dev.port in your config), it stays strict and fails fast with a clear message — you asked for that port, so you probably meant it.

Everything downstream follows along automatically:

  • BASE_URL defaults to the dev server’s own address when unset. If a stale localhost BASE_URL in your .env points at a different port, you get a warning at startup instead of silently broken links.
  • The FFS sidecar gets its own free port per instance (walking up from 2000), with FFS_BASE_URL set to match.
  • effing url defaults BASE_URL to the configured dev address, so URLs resolve correctly without extra setup.

Two smaller things rode along. The preview’s FFS flows no longer demand FFS_API_KEY — the auth header is only sent when a key is actually set, which matches the sidecar, which never enforced auth without one. And Vite’s unused HMR WebSocket server turned out to be a hidden cross-instance collision on port 24678; it’s now disabled.

The net effect on a fresh project: only SECRET_KEY is required in development. The starter template’s .env.example and guide now say so.

Canvas: fragments inside SVG actually draw now

React fragments inside an <svg> subtree used to keep their fragment type through layout, and the SVG drawer silently skipped them — so fragment-rooted icons rendered as nothing at all. Fragments are now unwrapped during SVG tree resolution, and their children draw (and resolve currentColor) as if placed directly in the parent element.

Canvas: a confession about baseline

baseline was listed as a supported value for alignItems and alignSelf, but the bundled Yoga layout engine’s JS binding exposes no baseline function. In practice it aligns children to the line-box bottom — the same result as flex-end — rather than to the typographic baseline, so rows mixing font sizes don’t share a text baseline. (Satori, which the layout engine derives from, has the same caveat.)

Nothing changed in behavior here; the README just tells the truth now. If you were relying on baseline to line up mixed font sizes, it never did what you hoped — and now the docs won’t suggest otherwise.

Upgrading

Bump your @effing/* packages to 0.37.0 and you’re set. The full changelogs are in the release PR.