Expo Quickstart
The Expo SDK (@pylo/expo) is everything @pylo/react
provides, with the device keychain wired up as the token store and app focus wired up to React
Query.
Install
npx expo install @pylo/expo @tanstack/react-query expo-secure-store
1. Generate types
Create an API token in Settings > API Tokens in the admin panel (see
API Tokens) and put it in .env.
1
PYLO_API_KEY=your-api-token-here1
2
3
4
5
6
import { defineConfig } from '@pylo/expo/codegen';
export default defineConfig({
apiKey: process.env.PYLO_API_KEY!,
output: '.pylo', // optional, defaults to '.pylo'
});npx pylo generateThe generated index.ts registers the schema on @pylo/expo, so the PyloSelect and PyloResult
helpers are typed with no declare module step.
Keep the token out of your bundle
Only pylo generate reads PYLO_API_KEY, and only at build time. Expo inlines an environment
variable into the app only when its name starts with EXPO_PUBLIC_, so an unprefixed name stays
out of the bundle.
2. Add the provider
Import PyloProvider from @pylo/expo and pass no storage: it defaults to SecureStore.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { PyloProvider } from '@pylo/expo';
import { Root } from './Root';
const queryClient = new QueryClient();
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<PyloProvider appId={process.env.EXPO_PUBLIC_PYLO_APP_ID}>
<Root />
</PyloProvider>
</QueryClientProvider>
);
}appId scopes the session to one app. Find your app id in Settings > Apps in the admin panel.
3. Use the hooks
usePyloAuth, createPyloHooks, usePyloClient and the rest are re-exported from @pylo/expo
unchanged. Follow the React Quickstart from here.
1
2
3
4
import { createPyloHooks } from '@pylo/expo';
import type { PyloSchema } from '../.pylo';
export const pylo = createPyloHooks<PyloSchema>();Token storage
SecureStore is backed by the OS keychain, so tokens are encrypted at rest and a native app has no
XSS surface to leak them through. Reads are asynchronous, which is why usePyloAuth reports
isLoading until the stored session has been read.
Uploading files
React Native has no File for a local file. Pass the reference its pickers return, and the platform
streams it from disk.
1
2
3
const { startUpload } = pylo.usePyloUpload({ entityRelationPath: 'contact.avatar' });
await startUpload({ uri: asset.uri, name: asset.fileName, type: asset.mimeType });Such a reference carries no byte length, so progress across a batch weights each file equally rather than by size. See Uploading & Downloading for the rest of the upload API.
Refetching when the app returns to the foreground
TanStack Query decides focus from a browser event React Native does not have, so without wiring,
queries never refetch when your app foregrounds. PyloProvider does this for you.
TanStack's focus manager is global, so it applies to every query in your app, not only Pylo's. That is what TanStack's own React Native guide recommends. If you already wire it up yourself, turn ours off:
1
<PyloProvider refetchOnAppFocus={false}>Network state is a separate matter and stays opt-in, because it needs a community package. See the TanStack Query React Native guide for that half.