React Native
TalaDB runs natively on iOS and Android via a JSI integration — calls from JavaScript go directly into the Rust engine without bridge overhead or JSON serialisation on the hot path.
Requirements
- React Native 0.73+ with New Architecture enabled
- Expo SDK 50+ (if using Expo)
- Xcode 15+ for iOS builds
- Android NDK r27+ for Android builds
Installation
pnpm add taladb @taladb/react-nativeiOS
cd ios && pod installAndroid
No extra steps — Gradle links the native library automatically.
Enable the New Architecture
TalaDB requires the New Architecture for its JSI integration.
android/gradle.properties
newArchEnabled=trueios/Podfile
use_framework! :staticQuick start
Call TalaDBModule.initialize once at app startup — before any component tries to use the database.
// App.tsx
import { TalaDBModule } from '@taladb/react-native'
import { openDB } from 'taladb'
await TalaDBModule.initialize('myapp.db')
const db = await openDB('myapp.db')
const users = db.collection('users')
await users.insert({ name: 'Alice', createdAt: Date.now() })
const all = await users.find()That's it. The taladb package detects React Native automatically — the same code you write for the browser or Node.js works here too.
HTTP push sync
Pass a sync config as the second argument to TalaDBModule.initialize to automatically push mutation events to a remote endpoint after every write:
// App.tsx
import { TalaDBModule } from '@taladb/react-native'
import { openDB } from 'taladb'
await TalaDBModule.initialize('myapp.db', JSON.stringify({
sync: {
enabled: true,
endpoint: 'https://api.example.com/taladb-events',
headers: { Authorization: `Bearer ${myToken}` },
exclude_fields: ['embedding'], // omit large vector fields
},
}))
const db = await openDB('myapp.db')
// Every write now fires an HTTP event in the backgroundAfter every committed write, TalaDB spawns a background Rust thread and POSTs the event payload to the configured endpoint with up to 3 retries and exponential backoff (200 ms / 400 ms / 800 ms). The write path is never blocked.
Per-event endpoint overrides are supported:
await TalaDBModule.initialize('myapp.db', JSON.stringify({
sync: {
enabled: true,
endpoint: 'https://api.example.com/events',
insert_endpoint: 'https://api.example.com/events/insert',
update_endpoint: 'https://api.example.com/events/update',
delete_endpoint: 'https://api.example.com/events/delete',
headers: { Authorization: 'Bearer YOUR_TOKEN' },
},
}))See the HTTP Push Sync guide for the full config reference, payload shapes, and retry behaviour.
Full example
// App.tsx
import React, { useEffect, useState } from 'react'
import { View, Text, Button, FlatList } from 'react-native'
import { TalaDBModule } from '@taladb/react-native'
import { openDB, type Collection } from 'taladb'
interface Note {
_id?: string
text: string
createdAt: number
}
let notes: Collection<Note>
export default function App() {
const [items, setItems] = useState<Note[]>([])
useEffect(() => {
async function init() {
await TalaDBModule.initialize('notes.db')
const db = await openDB('notes.db')
notes = db.collection<Note>('notes')
await notes.createIndex('createdAt')
setItems(await notes.find())
}
init()
}, [])
async function addNote() {
await notes.insert({ text: `Note ${Date.now()}`, createdAt: Date.now() })
setItems(await notes.find())
}
return (
<View style={{ flex: 1, padding: 40 }}>
<Button title="Add Note" onPress={addNote} />
<FlatList
data={items}
keyExtractor={(item) => item._id!}
renderItem={({ item }) => <Text>{item.text}</Text>}
/>
</View>
)
}Vector search
TalaDB supports on-device semantic search — store embeddings from a local ML model (Core ML, TensorFlow Lite) and search them without any server.
interface Article {
_id?: string
title: string
body: string
embedding: number[]
}
const articles = db.collection<Article>('articles')
await articles.createVectorIndex('embedding', { dimensions: 384 })
// Insert with embedding from your on-device model
const embedding = await myModel.embed(content)
await articles.insert({ title, body: content, embedding })
// Semantic search
const queryVec = await myModel.embed(userQuery)
const results = await articles.findNearest('embedding', queryVec, 5)
results.forEach(({ document, score }) => {
console.log(score.toFixed(3), document.title)
})
// Hybrid: combine vector ranking with a metadata filter
const filtered = await articles.findNearest('embedding', queryVec, 5, {
category: 'faq',
})Where data is stored
| Platform | Location |
|---|---|
| iOS | NSDocumentDirectory (iCloud-excluded by default) |
| Android | Context.getFilesDir() (app-private, no permissions needed) |
No special permissions are required on either platform.
Migrations
const db = await openDB('myapp.db', {
migrations: [
{
version: 1,
description: 'Add notes index',
up: async (db) => {
await db.collection('notes').createIndex('createdAt')
},
},
],
})Troubleshooting
__TalaDB__ JSI HostObject not foundopenDB was called before TalaDBModule.initialize completed. Move initialize to the very top of your app entry point and await it before any database access.
TurboModuleRegistry.getEnforcing('TalaDB'): 'TalaDB' could not be found (Android) The native module was not linked. Verify that your android/gradle.properties has newArchEnabled=true and that you are using a custom dev client — @taladb/react-native cannot run inside Expo Go.
New Architecture is not enabled Set newArchEnabled=true in android/gradle.properties and add use_framework! :static to your ios/Podfile.
Pod install fails on iOS Make sure Xcode command-line tools are active: xcode-select --install. Then re-run pod install.
Current limitations
- Expo Go — not supported. You must use a custom dev client (
expo prebuild). - Live queries (
subscribe) — polling-based on React Native; native file-watch push is planned for a future release.
