@randomaccessmemories/pool-kit wraps the Swift SDK as an Expo module. The API keeps the Swift names, so every guide in these docs applies: read the Swift example and call the same method from TypeScript. It runs on iOS 18 and later. Android is not supported, so guard your calls with Platform.OS === "ios".
Requirements
- Expo SDK 53 or later, with a development build. Expo Go cannot load native modules.
- A bare React Native app works too, once it has Expo modules installed.
- An app key from the dashboard, with your app’s bundle ID added.
1. Install
PoolKit pod, which ships the SDK as a binary XCFramework. npx expo prebuild and pod install fetch it for you.
2. Add the config plugin
The plugin writes the photo library sentence and the background task settings into your app’s Info.plist at prebuild, raises the iOS deployment target to 18.0 (inPodfile.properties.json and the Xcode project, never lowering a higher one), and adds the PoolKit pod to your Podfile from the pool-kit repo. In a bare React Native app without prebuild, set platform :ios, '18.0' and add that line to your Podfile yourself:
Podfile
app.json
With background indexing on, the plugin adds the task identifier,
<bundle ID>.pool.update and <bundle ID>.pool.continue.* to BGTaskSchedulerPermittedIdentifiers, processing to UIBackgroundModes, and the identifier as PoolKitBackgroundTaskIdentifier. The module then registers the background tasks itself at launch, so there is no native code to write. A background task waits up to 20 seconds for PoolKit.open, so call it early, for example in your root component’s first effect. See Indexing for how runs are scheduled. Run npx expo prebuild after you change the plugin’s options.
3. Open, ask for access, ask a question
open names the grant it runs under; pass the Grant object or its id. Store the id if you want to reuse a grant across launches, and read the live ones with PoolKit.authorization.grants().
How the API maps
Results are plain objects with the Swift field names. Dates are ISO 8601 strings. A Swift enum with a payload becomes an object keyed by its case, so
.growingFrom(.months(3)) is { growingFrom: { months: 3 } }. All types are exported under their Swift names, such as Grant, QueryResult, AssetSearchResult and IndexOptions.
Streams
askUpdates, signals.subscribe, sources.statusUpdates and sources.batches resolve to a stream. Call remove() when the screen goes away.
Index options
PassindexOptions to open, or change them later with PoolKit.sources.setIndexOptions. The fields match Indexing.
Errors
A rejected promise carriescode, the name of the Swift PoolError case, and message, the case with its values, such as rateLimited(retryAfter: 60). PoolKit.errorDetails(error) (also a named export) reads any rejection into { code, message, retryable, retryAfter?, serverCode? }, the same fields as in Errors. Stream onError handlers receive a PoolKitStreamError with those fields.
Without React Native
The same XCFramework is available to native apps that do not use Swift Package Manager.- CocoaPods
- XCFramework
Podfile

