Handling Attachments
Examples of syncing attachments between a client app and Supabase Storage.
React Native Example
Our React Native To-Do List example app showcases how to sync attachments (such as photos) using the @powersync/attachments library, the PowerSync Service, and Supabase.
In this example, we are syncing photos, however other media types, such as PDFs, are also supported.
The library and this example implementation can be used as a reference for implementing similar functionality for a Postgres backend without Supabase.
The below assumes you have completed the steps outlined in the To-Do List app Readme. This includes installing and running the PowerSync React Native SDK; setting up a Supabase project; setting up a PowerSync instance and connecting it with Supabase.
Configure Storage in Supabase
In this example app, Supabase Storage is used to store and serve attachments. To configure this for your app, navigate to the Storage section of your Supabase project and create a new bucket:
Give the storage bucket a name, such as media, and hit Save:
Next, link this storage bucket to your app by opening up the AppConfig.ts file and adding the bucket name as the value to the supabaseBucket
key:
Lastly, configure a policy for this bucket. In this example app, we will allow all user operations on the media bucket.
Create a new policy for the media bucket:
Give the new policy a name, and allow SELECT, INSERT, UPDATE, and DELETE.
Proceed to review and save the policy.
This concludes the necessary configuration for handling attachments in the To-Do List example app. When running the app now, a photo can be taken for a to-do list item, and PowerSync will ensure that the photo syncs to Supabase and other devices (if sync rules allow).
Read on to learn more about how this works under the hood.
Implementation Details
The @powersync/attachments library is used in conjunction with the PowerSync Service to sync photos. Refer to the library’s README for an overview of the main components. In summary, they are:
AttachmentRecord
to store the metadata of attachments.AttachmentState
to track the sync state of anAttachmentRecord
.AbstractAttachmentQueue
class to manage and syncAttachmentRecord
s:- Track and sync attachment metadata.
- Watch for changes and handle CRUD operations on
AttachmentRecord
s. - Store attachment data on the user’s local storage, using file URIs on the device.
The UI of the example app supports taking photos as follows:
- CameraWidget uses
expo-camera
to allow users to capture a photo. - The photo is stored on the user’s local storage.
- See the savePhoto() method.
- The app includes a basic prompt for the user to grant permission to use the device’s camera.
The app’s schema was modified to link a photo to a to-do item:
- A
photo_id
was added as a column to thetodos
table to link a photo to a to-do item. - A local-only
attachments
table is instantiated to store the metadata of photos.
The PhotoAttachmentQueue class extends the AbstractAttachmentQueue
abstract class and:
- Uses a PowerSync query to gather the relevant photo IDs (see
attachmentIds()
) - Creates
AttachmentRecord
s to store photo metadata. (seenewAttachmentRecord()
) - Uses the
savePhoto()
method to save photos into local storage and add them to the sync queue.
How Syncing Works
Refer to this section in the library’s README to learn more about the various sync states and operations.
Future Improvements
The following improvements can be considered for this implementation.
- An easier way to set up the local-only
attachments
table and related schema. - Better tooling/APIs for retrying/resuming uploads or downloads when transitioning from an offline into an online state.
Flutter Example
Our Flutter To-Do List example app showcases how to sync attachments (such as photos) using our powersync_attachments_helper package for Flutter.
See Also
Was this page helpful?