Motion
Offline-first React Native app for field surveyors with local SQLite storage and automatic data synchronization.
The Challenge
Field surveyors for BKI (Biro Klasifikasi Indonesia) needed to collect complex inspection and survey data directly from mobile devices, often in remote environments where internet connectivity was unstable or completely unavailable.
The requirement was clear: build a reliable offline-first mobile application that allows surveyors to fill, save, edit, and submit hundreds of complex forms without depending on an active internet connection. The app also needed to synchronize data automatically once the connection was restored, including form submissions, attachments, and deleted records.
Tech Stack
Technical Implementation
- Offline-First Local Database
Implemented a local database architecture using SQLite and Drizzle ORM to store survey forms, dropdown references, user inputs, attachments, and synchronization metadata directly on the device. This allowed surveyors to continue working even without an internet connection.
- Custom Upload Queue System
Engineered a custom upload queue to manage pending form submissions, attachment uploads, and deleted items. Each action is stored locally first, then processed safely when the device reconnects to the internet, reducing the risk of duplicated or lost data.
- Sync Center & Retry Mechanism
Built a Sync Center module that detects unsynchronized records and processes them in the correct order. Failed sync attempts are marked and can be retried, ensuring data remains consistent between the local database and the server.
- Attachment Synchronization
Implemented offline attachment handling so users can capture or upload images and files while offline. The app stores attachments locally and uploads them automatically once a reliable connection is available.
- Device Time Validation
Added a time manipulation detection mechanism to help protect survey data integrity by identifying potential device time changes before allowing critical submissions.
const syncData = async () => {
try {
const pendingItems = await db.query.uploadQueue.findMany({
where: (queue, { eq }) => eq(queue.status, "pending"),
});
for (const item of pendingItems) {
await markAsProcessing(item.id);
try {
if (item.type === "FORM_SUBMISSION") {
await api.submitForm(item.payload);
}
if (item.type === "ATTACHMENT_UPLOAD") {
await api.uploadAttachment(item.payload);
}
if (item.type === "ATTACHMENT_DELETE") {
await api.deleteAttachment(item.remoteId);
}
await markAsSynced(item.id);
} catch (error) {
await markAsFailed(item.id, String(error));
}
}
} catch (error) {
console.error("Sync failed:", error);
}
};Impact & Results
The deployment of Motion improved the field surveying workflow by allowing users to continue collecting and saving data even without internet access. The offline-first approach reduced the risk of lost submissions, improved surveyor confidence, and made the reporting process more stable in real field conditions.