diff --git a/packages/bun-framework-react/bun.lock b/packages/bun-framework-react/bun.lock
new file mode 100644
index 0000000000..c08e4dfde8
--- /dev/null
+++ b/packages/bun-framework-react/bun.lock
@@ -0,0 +1,18 @@
+{
+ "lockfileVersion": 1,
+ "workspaces": {
+ "": {
+ "devDependencies": {
+ "@types/react": "^19.1.12",
+ "@types/react-dom": "^19.1.9",
+ },
+ },
+ },
+ "packages": {
+ "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="],
+
+ "@types/react-dom": ["@types/react-dom@19.1.9", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ=="],
+
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+ }
+}
diff --git a/src/bake/bun-framework-react/index.ts b/packages/bun-framework-react/index.ts
similarity index 100%
rename from src/bake/bun-framework-react/index.ts
rename to packages/bun-framework-react/index.ts
diff --git a/packages/bun-framework-react/package.json b/packages/bun-framework-react/package.json
new file mode 100644
index 0000000000..a92461bdbe
--- /dev/null
+++ b/packages/bun-framework-react/package.json
@@ -0,0 +1,7 @@
+{
+ "type": "module",
+ "devDependencies": {
+ "@types/react": "^19.1.12",
+ "@types/react-dom": "^19.1.9"
+ }
+}
diff --git a/packages/bun-framework-react/src/components/link.tsx b/packages/bun-framework-react/src/components/link.tsx
new file mode 100644
index 0000000000..7464c00878
--- /dev/null
+++ b/packages/bun-framework-react/src/components/link.tsx
@@ -0,0 +1,3 @@
+export function Link(props: React.ComponentProps<"a">) {
+ return ;
+}
diff --git a/src/bake/bun-framework-react/client.tsx b/packages/bun-framework-react/src/rendering/client.tsx
similarity index 88%
rename from src/bake/bun-framework-react/client.tsx
rename to packages/bun-framework-react/src/rendering/client.tsx
index 939e5cb81c..a61d4d1b2d 100644
--- a/src/bake/bun-framework-react/client.tsx
+++ b/packages/bun-framework-react/src/rendering/client.tsx
@@ -2,7 +2,7 @@
// Components integration. It is designed as a minimal base to build RSC
// applications on, and to showcase what features that Bake offers.
///
-import { onServerSideReload } from "bun:bake/client";
+import { onServerSideReload } from "bun:app/client";
import * as React from "react";
import { flushSync } from "react-dom";
import { hydrateRoot } from "react-dom/client";
@@ -11,32 +11,65 @@ import { createFromReadableStream } from "react-server-dom-bun/client.browser";
const te = new TextEncoder();
const td = new TextDecoder();
+const windowDebugKey = "$bake";
+
+interface WindowDebugObject {
+ navigate: (href: string, cacheId?: number) => Promise;
+ onServerSideReload: (cb: () => void | Promise) => Promise;
+ readonly currentCssList: string[] | undefined;
+}
+
+type WindowWithBakeDebugObject = { [key in typeof windowDebugKey]: WindowDebugObject };
+declare global {
+ interface Window extends WindowWithBakeDebugObject {}
+}
+
// It is the framework's responsibility to ensure that client-side navigation
// loads CSS files. The implementation here loads all CSS files as tags,
// and uses the ".disabled" property to enable/disable them.
const cssFiles = new Map | null; link: HTMLLinkElement }>();
let currentCssList: string[] | undefined = undefined;
+declare global {
+ interface Window {
+ __bun_f:
+ | Array>
+ | {
+ // it's still an array, but we overwrite the push method to not return
+ // a number and instead use the `handleChunk` function
+ push: (chunk: string | Uint8Array) => void;
+ forEach: (callback: (chunk: string | Uint8Array) => void) => void;
+ };
+ }
+}
+
// The initial RSC payload is put into inline