Example
Miniapp-ready website
Let the same web app work in browsers and inside U-net.
@union-networks/web-login@union-networks/server
Scenario
A partner wants their existing website to open through U-net's miniapp shell.
Steps
- Serve the well-known manifest.
- Use bridge login inside U-net.
- Fall back to QR login in normal browsers.
- Verify all assertions server-side.
Code
{
"serviceId": "example-shop",
"name": "Example Shop",
"provider": "example-shop.com",
"description": "A web app that can also run as a U-net miniapp.",
"icon": "basket-outline",
"launchUrl": "https://shop.example.com/app",
"permissions": ["identity.scoped"]
}
type BridgeResponse<T> = {
id: string;
ok: boolean;
result?: T;
error?: string;
};
function callUnetHost<T>(action: string, payload = {}): Promise<T> {
const bridge = window.ReactNativeWebView;
if (!bridge) throw new Error('not_running_inside_unet');
const id = crypto.randomUUID();
return new Promise((resolve, reject) => {
const onMessage = (event: MessageEvent<BridgeResponse<T>>) => {
if (event.data?.id !== id) return;
window.removeEventListener('message', onMessage as EventListener);
event.data.ok
? resolve(event.data.result as T)
: reject(new Error(event.data.error ?? 'unet_bridge_failed'));
};
window.addEventListener('message', onMessage as EventListener);
bridge.postMessage(JSON.stringify({ id, action, payload }));
});
}
const session = await callUnetHost<{
scopedUserId: string;
assertionJws: string;
}>('host.createServiceSession');
await fetch('/api/unet/session', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ assertionJws: session.assertionJws }),
});