Documentation Index
Fetch the complete documentation index at: https://docs.go.gbgplc.com/llms.txt
Use this file to discover all available pages before exploring further.
The GBG GO Native Bridge is a browser-only library. It requires window and browser APIs that are not available during server-side rendering (SSR).
All bridge code must execute on the client. The bridge cannot run on the server.
App Router (recommended)
In the App Router, components are server-rendered by default. Because the bridge needs window, you have to opt the relevant subtree into the client with 'use client' — typically by wrapping BridgeProvider in a small client-only component.
Mark bridge components as client-only
// app/layout.tsx
import { BridgeWrapper } from './bridge-wrapper';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<BridgeWrapper>{children}</BridgeWrapper>
</body>
</html>
);
}
The wrapper itself is a client component that just renders BridgeProvider:
// app/bridge-wrapper.tsx
'use client';
import { BridgeProvider } from '@gbgplc-internal/ggo-native-bridge-react';
export function BridgeWrapper({ children }: { children: React.ReactNode }) {
return <BridgeProvider>{children}</BridgeProvider>;
}
The 'use client' directive ensures the BridgeProvider and all bridge-related code only runs in the browser.
Using hooks in client components
Any component that calls a bridge hook also needs 'use client'. From there, the hooks behave exactly as they do outside Next.js:
// components/document-capture.tsx
'use client';
import { useNativeCamera, useBridge } from '@gbgplc-internal/ggo-native-bridge-react';
export function DocumentCapture() {
const { isEmbedded, capabilitiesReady } = useBridge();
const { isNativeAvailable, requestCapture } = useNativeCamera('document');
if (!capabilitiesReady) return <p>Loading...</p>;
return (
<button onClick={() => isNativeAvailable && requestCapture({ side: 'front' })}>
Capture
</button>
);
}
Dynamic import fallback
If you need to conditionally load bridge code:
// app/page.tsx
import dynamic from 'next/dynamic';
const DocumentCapture = dynamic(
() => import('../components/document-capture').then(mod => mod.DocumentCapture),
{ ssr: false },
);
export default function Page() {
return <DocumentCapture />;
}
Pages Router
// pages/_app.tsx
import type { AppProps } from 'next/app';
import { BridgeProvider } from '@gbgplc-internal/ggo-native-bridge-react';
export default function App({ Component, pageProps }: AppProps) {
return (
<BridgeProvider>
<Component {...pageProps} />
</BridgeProvider>
);
}
Since Pages Router components are client-rendered by default, the bridge works without additional configuration.
Things to avoid
| Pattern | Problem | Solution |
|---|
| Import bridge in Server Components | Crashes — no window | Add 'use client' directive |
Call NativeBridge.getInstance() at module scope | Runs during SSR build | Call inside useEffect or useMemo |
Use detectEnvironment() in getServerSideProps | Returns 'standalone' (no window) | Only call on the client |
Environment detection during SSR
If you need to know the environment during SSR (e.g., for conditional rendering), pass it as a prop from the client:
'use client';
import { detectEnvironment } from '@gbgplc-internal/ggo-native-bridge';
import { useState, useEffect } from 'react';
function useEnvironment() {
const [env, setEnv] = useState<string>('standalone');
useEffect(() => {
setEnv(detectEnvironment());
}, []);
return env;
}
This avoids hydration mismatches by starting with 'standalone' and updating on the client.