React Native Integration
Build mobile AI experiences with the Fig1 SDK in React Native.
Setup
The SDK is a REST API—no native modules required.
// lib/fig1-client.ts
const API_BASE = 'https://app.fig1.ai/api/sdk';
class Fig1Client {
private apiKey: string;
constructor(apiKey: string) {
this.apiKey = apiKey;
}
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const response = await fetch(`${API_BASE}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
'X-Fig1-API-Key': this.apiKey,
...options.headers,
},
});
const data = await response.json();
if (!data.success) throw new Error(data.error);
return data.data;
}
async chat(message: string, sessionId?: string, options?: {
personaId?: string;
preferences?: Record<string, any>;
}) {
return this.request<{
message: string;
sessionId: string;
actions?: any[];
}>('/agent/chat', {
method: 'POST',
body: JSON.stringify({ message, sessionId, ...options }),
});
}
}
export const fig1 = new Fig1Client('YOUR_API_KEY');
Chat Hook
// hooks/useChat.ts
import { useState, useCallback } from 'react';
import { fig1 } from '../lib/fig1-client';
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
}
export function useChat(personaId?: string) {
const [messages, setMessages] = useState<Message[]>([]);
const [sessionId, setSessionId] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const sendMessage = useCallback(async (text: string) => {
const userMessage: Message = {
id: Date.now().toString(),
role: 'user',
content: text,
};
setMessages(prev => [...prev, userMessage]);
setLoading(true);
try {
const response = await fig1.chat(text, sessionId || undefined, { personaId });
setSessionId(response.sessionId);
const assistantMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: response.message,
};
setMessages(prev => [...prev, assistantMessage]);
return response;
} finally {
setLoading(false);
}
}, [sessionId, personaId]);
const clearChat = useCallback(() => {
setMessages([]);
setSessionId(null);
}, []);
return { messages, sendMessage, clearChat, loading, sessionId };
}
Chat Screen
// screens/ChatScreen.tsx
import React, { useState, useRef } from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
FlatList,
KeyboardAvoidingView,
Platform,
StyleSheet,
} from 'react-native';
import { useChat } from '../hooks/useChat';
export function ChatScreen() {
const [input, setInput] = useState('');
const { messages, sendMessage, loading } = useChat();
const flatListRef = useRef<FlatList>(null);
const handleSend = async () => {
if (!input.trim() || loading) return;
const text = input;
setInput('');
await sendMessage(text);
};
return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={90}
>
<FlatList
ref={flatListRef}
data={messages}
keyExtractor={(item) => item.id}
onContentSizeChange={() => flatListRef.current?.scrollToEnd()}
contentContainerStyle={styles.messageList}
renderItem={({ item }) => (
<View style={[
styles.messageBubble,
item.role === 'user' ? styles.userBubble : styles.assistantBubble
]}>
<Text style={[
styles.messageText,
item.role === 'user' && styles.userText
]}>
{item.content}
</Text>
</View>
)}
/>
{loading && (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>Thinking...</Text>
</View>
)}
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
value={input}
onChangeText={setInput}
placeholder="Type a message..."
editable={!loading}
onSubmitEditing={handleSend}
returnKeyType="send"
/>
<TouchableOpacity
style={[styles.sendButton, (!input.trim() || loading) && styles.sendButtonDisabled]}
onPress={handleSend}
disabled={!input.trim() || loading}
>
<Text style={styles.sendButtonText}>Send</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
messageList: {
padding: 16,
},
messageBubble: {
maxWidth: '80%',
padding: 12,
borderRadius: 16,
marginBottom: 8,
},
userBubble: {
backgroundColor: '#007AFF',
alignSelf: 'flex-end',
},
assistantBubble: {
backgroundColor: '#F0F0F0',
alignSelf: 'flex-start',
},
messageText: {
fontSize: 16,
},
userText: {
color: '#fff',
},
loadingContainer: {
padding: 8,
alignItems: 'center',
},
loadingText: {
color: '#666',
},
inputContainer: {
flexDirection: 'row',
padding: 12,
borderTopWidth: 1,
borderTopColor: '#E0E0E0',
},
input: {
flex: 1,
borderWidth: 1,
borderColor: '#E0E0E0',
borderRadius: 20,
paddingHorizontal: 16,
paddingVertical: 8,
fontSize: 16,
},
sendButton: {
marginLeft: 8,
backgroundColor: '#007AFF',
borderRadius: 20,
paddingHorizontal: 20,
justifyContent: 'center',
},
sendButtonDisabled: {
opacity: 0.5,
},
sendButtonText: {
color: '#fff',
fontWeight: '600',
},
});
Handling Actions
// hooks/useAgentActions.ts
import { useCallback } from 'react';
import { Linking } from 'react-native';
import { useNavigation } from '@react-navigation/native';
interface ClientAction {
type: string;
payload: Record<string, any>;
immediate?: boolean;
}
export function useAgentActions() {
const navigation = useNavigation();
const handleActions = useCallback((actions: ClientAction[]) => {
for (const action of actions) {
if (action.immediate === false) continue;
switch (action.type) {
case 'navigate':
if (action.payload.route) {
navigation.navigate(action.payload.route as never);
}
break;
case 'open_url':
if (action.payload.url) {
Linking.openURL(action.payload.url);
}
break;
case 'show_product':
if (action.payload.productId) {
navigation.navigate('ProductDetail' as never, {
productId: action.payload.productId
} as never);
}
break;
}
}
}, [navigation]);
return { handleActions };
}
Environment Variables
For React Native, use react-native-config or a similar solution:
# .env
FIG1_API_KEY=fig1_sdk_your_api_key
import Config from 'react-native-config';
const fig1 = new Fig1Client(Config.FIG1_API_KEY);
Security Note
For production apps, route requests through your own backend to keep API keys secure. The mobile app should call your server, which then calls the Fig1 API.