React Native
The Covara client makes no DOM assumptions, so the same client, repository, hooks, and subscriptions run in React Native. A few integration points differ from the browser.
Token storage
OIDC/JWT tokens are stored through a pluggable TokenStorage. In the browser the default is MemoryStorage (or LocalStorageAdapter); in React Native, provide an AsyncStorage-compatible adapter:
import AsyncStorage from "@react-native-async-storage/async-storage";
import { createClient } from "covara/client";
const asyncStorageAdapter = {
getItem: (key: string) => AsyncStorage.getItem(key),
setItem: (key: string, value: string) => AsyncStorage.setItem(key, value),
removeItem: (key: string) => AsyncStorage.removeItem(key),
};
const client = createClient({
baseUrl: "https://api.myapp.com",
auth: {
issuer: "https://auth.myapp.com/oidc",
clientId: "mobile-app",
redirectUri: "myapp://callback",
storage: asyncStorageAdapter, // satisfies TokenStorage
},
});
The same applies to useJWTAuth — pass an AsyncStorage-compatible storage.
Transport & offline backends
The transport and offline layers are environment-aware:
fetchand SSE work over React Native's networking.- For the offline queue, use
InMemoryOfflineStorageor supply an AsyncStorage/SQLite-backedOfflineStorageimplementation (the browser-onlyLocalStorageOfflineStorage/IndexedDBOfflineStoragearen't available natively). offline.tabSync(BroadcastChannel) is a no-op outside the browser — leave it off.
import { createClient, InMemoryOfflineStorage } from "covara/client";
const client = createClient({
baseUrl: "https://api.myapp.com",
offline: { enabled: true, storage: new InMemoryOfflineStorage() }, // or your AsyncStorage-backed store
});
Files
There's no <img>/<a> — use getDownloadUrl(id) from useFiles (or the file client) to obtain a URL, then fetch the bytes with React Native's fetch/Image source:
const { getDownloadUrl } = useFiles({ resourcePath: "/api/files" });
<Image source={{ uri: getDownloadUrl(file.id) }} />;
Hooks
useLiveList, useMutation, useAuth, useJWTAuth, useFileUpload, and the billing hooks all work unchanged — they depend only on React, not the DOM.