You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The source inspector is the one part of the devtools that still requires @tanstack/devtools-vite to be the thing that serves the app. Everything else about it is plain DOM code that works anywhere. I'd like a config key for the URL it calls, so the feature is usable on hosts that can inject data-tsd-source but cannot mount your dev-server middleware.
Where it's pinned
packages/devtools/src/components/source-inspector.tsx (L114-116 on main):
BASE_URL came out of #248, where the inspector broke behind a proxy on a subpath — so the principle that this URL has to adapt to its host is already accepted. But BASE_URL is a Vite variable: outside Vite import.meta.env is undefined and it falls back to /, and the __tsd/open-source half is fixed regardless. Nothing in TanStackDevtoolsConfig reaches either.
Why it matters outside Vite
data-tsd-source is just an attribute, and other toolchains can produce it. I inject it from an SWC plugin so the inspector works in Next.js, where Turbopack and webpack both run SWC plugins but neither has a Vite plugin hook. The attribute side is a non-issue — same name, same path:line:column format, and the overlay lights up correctly.
The click is where it stops. Next has no place to mount middleware on /__tsd/open-source, and the failure is invisible: fetch(...).catch(() => {}) swallows the 404, so a click on a highlighted element looks identical to a click that did nothing. That's a confusing first ten minutes for anyone in this position.
What I'd like
A single key on TanStackDevtoolsConfig, alongside sourceAction, taking the clicked element's data-tsd-source value and returning the URL to request:
A function rather than a string. I started out wanting the string form, then found that settings are persisted to local storage and take priority over config on the next load — so a string would stay frozen at whatever the app was configured with the first time it ran, and later changes would be ignored. JSON.stringify drops functions, so a function stays out of storage the way customTrigger already does. It also covers the "expose the underlying API" half of #314 for the same three lines.
The whole URL rather than just its base, because another host generally wants another parameter shape — the Next.js endpoint below takes the position split into three, so a configurable base alone would still leave it unreachable.
The change is contained: build the URL from the config value when present, keep the current BASE_URL behaviour as the default. No new surface anywhere else.
Worth mentioning what does not solve it. sourceAction: 'copy-path' avoids the network entirely, but it gives up the feature — the point is opening the file. And the fetch could be monkey-patched from the app, which is exactly the kind of thing a config key exists to prevent.
What I'm doing meanwhile
For anyone who lands here from a search: Next's dev overlay already serves /__nextjs_launch-editor?file=&line1=&column1=, which does the same job, so the packed param can be split with a redirect and no app code at all:
A redirect rather than a rewrite, because __nextjs_launch-editor is served by dev middleware that runs ahead of Next's router — a rewritten URL never reaches it and returns 404, while the 307 makes the browser issue a second request that does. Verified end to end on Next.js 16.3.1 with @tanstack/react-devtools 0.10.11 (@tanstack/devtools 0.14.1): hold the hotkey, hover, click, and the editor opens at src/app/page.tsx:17:11.
It works, but it only works because Next happens to ship a compatible endpoint, and it costs a redirect rule that has to encode your source format. A host with its own editor-opening endpoint under a different shape has no route at all.
With openSourceUrl the redirect disappears — the builder produces Next's shape directly:
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The source inspector is the one part of the devtools that still requires
@tanstack/devtools-viteto be the thing that serves the app. Everything else about it is plain DOM code that works anywhere. I'd like a config key for the URL it calls, so the feature is usable on hosts that can injectdata-tsd-sourcebut cannot mount your dev-server middleware.Where it's pinned
packages/devtools/src/components/source-inspector.tsx(L114-116 on main):BASE_URLcame out of #248, where the inspector broke behind a proxy on a subpath — so the principle that this URL has to adapt to its host is already accepted. ButBASE_URLis a Vite variable: outside Viteimport.meta.envis undefined and it falls back to/, and the__tsd/open-sourcehalf is fixed regardless. Nothing inTanStackDevtoolsConfigreaches either.Why it matters outside Vite
data-tsd-sourceis just an attribute, and other toolchains can produce it. I inject it from an SWC plugin so the inspector works in Next.js, where Turbopack and webpack both run SWC plugins but neither has a Vite plugin hook. The attribute side is a non-issue — same name, samepath:line:columnformat, and the overlay lights up correctly.The click is where it stops. Next has no place to mount middleware on
/__tsd/open-source, and the failure is invisible:fetch(...).catch(() => {})swallows the 404, so a click on a highlighted element looks identical to a click that did nothing. That's a confusing first ten minutes for anyone in this position.What I'd like
A single key on
TanStackDevtoolsConfig, alongsidesourceAction, taking the clicked element'sdata-tsd-sourcevalue and returning the URL to request:A function rather than a string. I started out wanting the string form, then found that settings are persisted to local storage and take priority over
configon the next load — so a string would stay frozen at whatever the app was configured with the first time it ran, and later changes would be ignored.JSON.stringifydrops functions, so a function stays out of storage the waycustomTriggeralready does. It also covers the "expose the underlying API" half of #314 for the same three lines.The whole URL rather than just its base, because another host generally wants another parameter shape — the Next.js endpoint below takes the position split into three, so a configurable base alone would still leave it unreachable.
The change is contained: build the URL from the config value when present, keep the current
BASE_URLbehaviour as the default. No new surface anywhere else.Worth mentioning what does not solve it.
sourceAction: 'copy-path'avoids the network entirely, but it gives up the feature — the point is opening the file. And the fetch could be monkey-patched from the app, which is exactly the kind of thing a config key exists to prevent.What I'm doing meanwhile
For anyone who lands here from a search: Next's dev overlay already serves
/__nextjs_launch-editor?file=&line1=&column1=, which does the same job, so the packed param can be split with a redirect and no app code at all:A redirect rather than a rewrite, because
__nextjs_launch-editoris served by dev middleware that runs ahead of Next's router — a rewritten URL never reaches it and returns 404, while the 307 makes the browser issue a second request that does. Verified end to end on Next.js 16.3.1 with@tanstack/react-devtools0.10.11 (@tanstack/devtools0.14.1): hold the hotkey, hover, click, and the editor opens atsrc/app/page.tsx:17:11.It works, but it only works because Next happens to ship a compatible endpoint, and it costs a redirect rule that has to encode your source format. A host with its own editor-opening endpoint under a different shape has no route at all.
With
openSourceUrlthe redirect disappears — the builder produces Next's shape directly:Status
Opened #517 with the function form above. Happy to reshape the key or close it if this isn't the direction you'd want.
All reactions