Command Palette

Search for a command to run...

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.

.env
1 PYLO_API_KEY=your-api-token-here
pylo.config.ts
1 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 generate

The 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.

App.tsx
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.

lib/pylo.ts
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.

tsx
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:

tsx
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.