One API, four transports
Android JavascriptInterface, iOS WKWebView message handlers, iframe postMessage, and a web loopback for local dev — auto-detected at runtime.
Type-safe, real-time messaging with Android WebViews, iOS WKWebViews, and iframes — promise-based, validated, observable.
Define messages once, get typed payloads and responses everywhere — with the validator you already use, or none at all.
import { z } from "zod";
import { createBridge, defineMessage } from "nbridge";
const schemas = {
getUser: defineMessage({
type: "getUser",
payloadSchema: z.object({ id: z.string() }),
responseSchema: z.object({ name: z.string(), email: z.string() }),
}),
};
const bridge = createBridge({ schemas });
// Typed + validated at runtime
const user = await bridge.sendWithResponse("getUser", { id: "42" });
console.log(user.name);import * as v from "valibot";
import { createBridge, defineMessage } from "nbridge";
const schemas = {
getUser: defineMessage({
type: "getUser",
payloadSchema: v.object({ id: v.string() }),
responseSchema: v.object({ name: v.string(), email: v.string() }),
}),
};
const bridge = createBridge({ schemas });
const user = await bridge.sendWithResponse("getUser", { id: "42" });
console.log(user.name);import { createBridge } from "nbridge";
const bridge = createBridge();
// Fire-and-forget
await bridge.send("analytics", { event: "page_view" });
// Request/response, correlated by message id
const user = await bridge.sendWithResponse<
{ id: string },
{ name: string; email: string }
>("getUser", { id: "42" });
// Listen for messages from the host
bridge.on("themeChanged", (payload) => {
console.log("Native says:", payload);
});