Skip to content

WebView Integration

Understand how the Lingu SDK uses WebView for a seamless chat experience.

Hybrid Architecture

The Lingu React Native SDK uses a hybrid approach that combines the best of both worlds:

ComponentTechnologyPurpose
UI LayerWebViewConsistent, beautiful chat interface
API LayerNativeFast, reliable network requests
StorageAsyncStoragePersistent message history

Why WebView?

Advantages

  1. Consistent UI: Same pixel-perfect interface on iOS and Android
  2. Rapid Updates: UI improvements without app store updates
  3. Smaller Bundle: Core UI shipped via web, reducing app size
  4. Feature Parity: New features available instantly across platforms

How It Works

mermaid
sequenceDiagram
    participant User
    participant WebView as WebView (UI)
    participant Native as Native Layer
    participant API as Lingu API

    User->>WebView: Types message
    WebView->>Native: postMessage()
    Native->>API: HTTP Request
    API-->>Native: AI Response
    Native->>WebView: Inject response
    WebView-->>User: Display message

Communication Bridge

The SDK creates a bridge between WebView and React Native:

Web → Native

javascript
// Inside WebView
window.ReactNativeWebView.postMessage(JSON.stringify({
  type: 'SEND_MESSAGE',
  payload: { text: 'Hello!' }
}));

Native → Web

typescript
// React Native side
webViewRef.current?.injectJavaScript(`
  window.receiveMessage(${JSON.stringify(message)});
`);

WebView Configuration

The SDK configures the WebView optimally:

tsx
<WebView
  source={{ uri: WIDGET_URL }}
  javaScriptEnabled={true}
  domStorageEnabled={true}
  mixedContentMode="compatibility"
  allowsInlineMediaPlayback={true}
  onMessage={handleMessage}
  // ... other configs
/>

Security Settings

SettingValueReason
javaScriptEnabledtrueRequired for chat functionality
domStorageEnabledtrueLocal data storage
allowsFullscreenVideofalseNot needed
allowsBackForwardNavigationGesturesfalsePrevent accidental navigation

Native API Benefits

While using WebView for UI, the SDK makes native API calls for:

1. Network Requests

Native HTTP requests are faster and more reliable than WebView network calls:

typescript
// Native fetch instead of WebView fetch
const response = await fetch(API_URL + '/message', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': apiKey,
  },
  body: JSON.stringify({ message, sessionId }),
});

2. Session Management

Sessions are managed natively for better reliability:

typescript
// Heartbeat runs in native code
setInterval(() => {
  api.sendHeartbeat(sessionId);
}, 30000); // Every 30 seconds

3. Local Storage

Messages are persisted using AsyncStorage:

typescript
import AsyncStorage from '@react-native-async-storage/async-storage';

// Save messages
await AsyncStorage.setItem('lingu_messages', JSON.stringify(messages));

// Restore on app open
const saved = await AsyncStorage.getItem('lingu_messages');

Offline Support

The hybrid architecture enables basic offline functionality:

FeatureOffline Behavior
View message historyWorks (from AsyncStorage)
Send new messagesQueued until online
Receive new messagesRequires connection

Performance Optimization

1. Lazy Loading

The WebView loads only when the user opens the chat:

tsx
const [isOpen, setIsOpen] = useState(false);

return (
  <>
    <FloatingButton onPress={() => setIsOpen(true)} />
    {isOpen && <LinguWebView />}
  </>
);

2. Preloading

For faster open times, preload the WebView in the background:

tsx
// Preload WebView but keep it hidden
<View style={{ height: 0, overflow: 'hidden' }}>
  <LinguWebView />
</View>

3. Caching

Static assets are cached for faster subsequent loads:

tsx
<WebView
  cacheEnabled={true}
  cacheMode="LOAD_CACHE_ELSE_NETWORK"
/>

Custom WebView Integration

For advanced use cases, you can integrate the WebView manually:

tsx
import { WebView } from 'react-native-webview';
import { LinguAPI } from '@lingu/react-native-sdk';

const WIDGET_URL = 'https://widget.uselingu.app';

function CustomChat() {
  const webViewRef = useRef<WebView>(null);
  const api = new LinguAPI('your-api-key');
  
  const handleMessage = async (event) => {
    const data = JSON.parse(event.nativeEvent.data);
    
    if (data.type === 'SEND_MESSAGE') {
      const response = await api.sendMessage(data.payload.text, sessionId);
      
      webViewRef.current?.injectJavaScript(`
        window.receiveMessage(${JSON.stringify(response)});
      `);
    }
  };
  
  return (
    <WebView
      ref={webViewRef}
      source={{ uri: WIDGET_URL }}
      onMessage={handleMessage}
      javaScriptEnabled={true}
    />
  );
}

Debugging

Inspect WebView Content

For iOS (Safari):

  1. Enable Safari Web Inspector on device
  2. Open Safari on Mac → Develop → [Device Name]

For Android (Chrome):

  1. Enable USB debugging on device
  2. Open chrome://inspect in Chrome

Log Bridge Messages

tsx
const handleMessage = (event) => {
  console.log('WebView message:', event.nativeEvent.data);
  // ... handle message
};

Powered by Lingu