From 2fc52fe14c74a5a3e6f10d7a3a226afaf0d13f10 Mon Sep 17 00:00:00 2001 From: Abhin Rustagi Date: Thu, 20 Aug 2026 16:53:53 +0530 Subject: [PATCH 1/5] Serve Devtools from a CDN instead of bundling it into react-lang. Apps pick up widget updates on next reload, and react-lang no longer depends on the Devtools package. --- packages/react-lang/package.json | 1 - packages/react-lang/src/devtoolsBootstrap.ts | 39 ++++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/react-lang/package.json b/packages/react-lang/package.json index 58a410073..5ac433141 100644 --- a/packages/react-lang/package.json +++ b/packages/react-lang/package.json @@ -82,7 +82,6 @@ }, "author": "engineering@thesys.dev", "dependencies": { - "@openuidev/devtools": "workspace:^", "@openuidev/lang-core": "workspace:^", "@openuidev/observability": "workspace:^" }, diff --git a/packages/react-lang/src/devtoolsBootstrap.ts b/packages/react-lang/src/devtoolsBootstrap.ts index 4654e036c..9b045f044 100644 --- a/packages/react-lang/src/devtoolsBootstrap.ts +++ b/packages/react-lang/src/devtoolsBootstrap.ts @@ -3,9 +3,10 @@ * * This module runs as a top-level side effect when the web entry is loaded in * a browser. In production builds the whole block is dead-code-eliminated by - * the consumer's bundler (the NODE_ENV condition folds to false), so neither - * `@openuidev/devtools` nor `react-dom/client` enters the production graph. - * The React Native entry (index.native.ts) never imports this module. + * the consumer's bundler (the NODE_ENV condition folds to false), so + * `react-dom` / `react-dom/client` never enter the production graph, and + * nothing is fetched. The React Native entry (index.native.ts) never imports + * this module. * * This module is inlined into the web entry (dist/index.*), which is listed * in package.json's `sideEffects` so bundlers preserve the side effect while @@ -21,17 +22,31 @@ if (process.env.NODE_ENV === "development" && typeof document !== "undefined") { // (ESM/CJS dual build, multiple package versions). if (!flags[AUTO_MOUNT_FLAG]) { flags[AUTO_MOUNT_FLAG] = true; - Promise.all([import("@openuidev/devtools"), import("react"), import("react-dom/client")]) - .then(([devtools, react, reactDomClient]) => { + + // Pinned to the protocol major, not @latest: cached for days, and a + // protocol-breaking release (mount() args, Symbol keys, event kinds) + // would otherwise take down every app that hasn't bumped. + const url = "https://cdn.jsdelivr.net/npm/@openuidev/devtools@0/dist/devtools.browser.js"; + + Promise.all([ + import(/* webpackIgnore: true */ /* @vite-ignore */ url), + import("react"), + import("react-dom"), + import("react-dom/client"), + ]) + .then(([devtools, react, reactDom, reactDomClient]) => { const mount = () => { - const host = document.createElement("div"); - host.setAttribute("data-openui-devtools-root", ""); - document.body.appendChild(host); - reactDomClient - .createRoot(host) - .render(react.createElement(devtools.OpenUIDevtools, { __autoMounted: true })); + devtools.mountOpenUIDevtools({ + React: react, + createPortal: reactDom.createPortal, + createRoot: reactDomClient.createRoot, + // Closed over this module's graph so the bundler resolves it — + // the CDN file never imports "@openuidev/react-lang" itself. + loadReactLang: () => import("@openuidev/react-lang"), + __autoMounted: true, + }); }; - // Module evaluation can happen before exists (script in ). + if (document.body) mount(); else document.addEventListener("DOMContentLoaded", mount, { once: true }); }) From 092cf176c9731227150d18923b4bce19171dcaca Mon Sep 17 00:00:00 2001 From: AB <55152006+AbhinRustagi@users.noreply.github.com> Date: Thu, 20 Aug 2026 18:12:13 +0530 Subject: [PATCH 2/5] Update devtoolsBootstrap.ts --- packages/react-lang/src/devtoolsBootstrap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-lang/src/devtoolsBootstrap.ts b/packages/react-lang/src/devtoolsBootstrap.ts index 9b045f044..89aa08e0c 100644 --- a/packages/react-lang/src/devtoolsBootstrap.ts +++ b/packages/react-lang/src/devtoolsBootstrap.ts @@ -46,7 +46,7 @@ if (process.env.NODE_ENV === "development" && typeof document !== "undefined") { __autoMounted: true, }); }; - + // Module evaluation can happen before exists (script in ). if (document.body) mount(); else document.addEventListener("DOMContentLoaded", mount, { once: true }); }) From 987aacf13ee6c7f3e1b90ec0fbb79f29e3606150 Mon Sep 17 00:00:00 2001 From: Abhin Rustagi Date: Thu, 20 Aug 2026 18:17:24 +0530 Subject: [PATCH 3/5] Pass host ReactDOM modules into the CDN mount from react-lang. The widget contract takes library refs, not plucked createRoot/createPortal. --- packages/react-lang/src/devtoolsBootstrap.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-lang/src/devtoolsBootstrap.ts b/packages/react-lang/src/devtoolsBootstrap.ts index 89aa08e0c..177f367c9 100644 --- a/packages/react-lang/src/devtoolsBootstrap.ts +++ b/packages/react-lang/src/devtoolsBootstrap.ts @@ -38,8 +38,8 @@ if (process.env.NODE_ENV === "development" && typeof document !== "undefined") { const mount = () => { devtools.mountOpenUIDevtools({ React: react, - createPortal: reactDom.createPortal, - createRoot: reactDomClient.createRoot, + ReactDOM: reactDom, + ReactDOMClient: reactDomClient, // Closed over this module's graph so the bundler resolves it — // the CDN file never imports "@openuidev/react-lang" itself. loadReactLang: () => import("@openuidev/react-lang"), From a06c0f829e820aa30d0dd753effd4976cd9dac85 Mon Sep 17 00:00:00 2001 From: Abhin Rustagi Date: Fri, 21 Aug 2026 14:27:32 +0530 Subject: [PATCH 4/5] fix: version bump --- packages/react-lang/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-lang/package.json b/packages/react-lang/package.json index 5ac433141..19a1dcf5f 100644 --- a/packages/react-lang/package.json +++ b/packages/react-lang/package.json @@ -1,6 +1,6 @@ { "name": "@openuidev/react-lang", - "version": "0.2.14", + "version": "0.2.15", "description": "Define component libraries, generate LLM system prompts, and render streaming OpenUI Lang output in React — the core runtime for OpenUI generative UI", "license": "MIT", "type": "module", From 4e65ff3eadcd6fe3ef4048427c4e3b082cbc6c53 Mon Sep 17 00:00:00 2001 From: Abhin Rustagi Date: Fri, 21 Aug 2026 16:31:53 +0530 Subject: [PATCH 5/5] fix: regenerate lockfile after dropping react-lang's devtools dep --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19bf98fb4..25d21eba9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1929,9 +1929,6 @@ importers: packages/react-lang: dependencies: - '@openuidev/devtools': - specifier: workspace:^ - version: link:../devtools '@openuidev/lang-core': specifier: workspace:^ version: link:../lang-core