U-net Docs
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

  1. Serve the well-known manifest.
  2. Use bridge login inside U-net.
  3. Fall back to QR login in normal browsers.
  4. Verify all assertions server-side.

Code

jsonManifest
{
  "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"]
}
tsBridge
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 }),
});