Blog

BuildShip + FlutterFlow: Creating an Offline Data App with Firebase Backup

Tutorial

·

Jul 24, 2024

The circle of no-code is complete. You can build out full stack applications using FlutterFlow for your frontend and BuildShip for your backend with ease. To add to it, integrate with any database (Firebase, Supabase, PostgresSQL, MySQL) or choose from 100s of pre-built nodes from popular platforms like Sendgrid, WhatsApp, and AI models on OpenAI, Replicate, Hugging Face, etc. 

In this blog, we’ll explore how to easily use FlutterFlow and BuildShip together with Firebase. We’ll dive into creating custom data types and sending them to BuildShip for analysis and decision-making. You’ll see how users can build an app that stores data locally on their device, without relying on an external database. When they’re ready, they can sync this data to Firebase via BuildShip workflows for safe storage. Changes made to the data can be synced back to Firebase, and if needed, users can retrieve and restore their data from Firebase to their device.

Let’s walk through the scenario step-by-step so you can see exactly what this application will do.

Referring the image above, you’ll find our FlutterFlow application in action. Here, users can create, read, and update notes, all stored locally on their device—no external database involved. Each note is managed through custom data types, which are integrated into the application state.

When the user decides to sync their data, they simply navigate to the settings and press a button. This action triggers an API call to a BuildShip workflow, which processes the data and uploads it to a Firebase Firestore database.

Users can make changes to their notes and sync these updates back to Firebase as needed. If they want to delete all their data, they can press another button in the UI. This triggers a request to BuildShip, which retrieves the records from Firebase and sends them back to the FlutterFlow application.

One key point is that all data is associated with a user ID generated when the application first loads. No authentication is required; instead, we use this persistent variable in FlutterFlow to reference the data stored in Firebase.

This overview covers the main steps, and we’ll guide you through the entire process. We’ve already set up a basic FlutterFlow application with CRUD functionality. Although it doesn’t sync with BuildShip yet, we’ll work through that together in this blog. Clone the project to follow along and get hands-on experience.

Here are a couple of things we’ll cover in this blog. The main thing is really how to use FlutterFlow and BuildShip together, especially when working with custom data types. You’ll learn how to convert custom data type data into a JSON request for BuildShip and handle the API response back into FlutterFlow to convert it back to a custom data type for display. These techniques are really useful for those new to this kind of work.

Getting started with Flutterflow

Let’s talk through how this application actually works in a demo style. You can see here we’ve got the running application up in test mode. I’ve clicked on the little “Tabs” here for the actual notes itself, and you can see we have no notes installed in this application.

If you hit the little plus option, you can create some notes to demonstrate how the application works. For now, we’ve added all of our notes. 


Inside the actual UI itself, you can update the notes and work independently.

There's no active communication with a database in the background other than persisted storage using custom data types within your FlutterFlow applications. This provides offline capability to store data within the application. In Firebase, you can see there's nothing initially present in a brand new instance.

To sync notes to the server, click the little Cog option and hit "sync."

This makes a call to BuildShip, goes through various checks in the workflow, and if you go back to the actual project, the notes appear. Here are the three notes we created. 

Now, back in the application, you can make changes. For example, if you remove the description from the first note and hit save, the note is updated locally but not saved back to Firebase immediately. You can continue to use the application, make changes, mark notes as complete, or delete them, all locally. When ready, hitting the sync button updates the Firebase database, reflecting all changes.

You can also delete notes on the device. After hitting delete and confirming, the notes disappear locally. However, they are still on the server. By clicking the refresh option, all notes are pulled back to the device in the same state as they were persisted in Firebase. This provides the ability to work offline and sync changes back to the server when necessary.

In summary:

- The FlutterFlow application allows users to take notes.

- Notes can be synced with Firebase using BuildShip.

- Retrieved notes are displayed in the app.

- Workflows handle syncing and restoring notes.

Let's move into the core of the blog and show how everything ties together. At the start, we created an application you can clone to follow along. This application functions generally but lacks the ability to sync through workflows to Firebase, which is the focus of this blog. We will focus on working with BuildShip and Firebase, not building the Flutterflow application itself.

Here's what we have:

- No APIs initially.

- An App State variable containing a user ID, generated randomly when the application loads.

- A notes app state variable containing a list of notes.

- A custom data type "note" with fields like user ID, title, description, update count, created timestamp, is complete, mark for deletion, and is in sync.

In the widget tree:

- The notes page displays notes.

- The note editor component allows adding and updating notes, generating a unique ID, and associating notes with the user ID.

The action flows:

- Show the note editor on the notes page.

- Save button updates or creates a new note in the app state variable.

Syncing BuildShip with Firebase

Next, let's look at BuildShip and see how it ties together with Firebase. In BuildShip, different routes handle various tasks:

- A notes route with endpoints to get all notes and create new notes.

- An update route for updating notes.

- A delete route for deleting notes.

- A sync route for syncing notes with Firebase.

These routes and endpoints handle necessary operations and integrate with our Firebase database. Let's start setting up these endpoints and building out the routes to handle note operations in our application.

Let’s start with setting up a new project called “dpnotes” in Firebase. Go to Build > Firestore Database and create a database. Choose Europe for the location and start in test mode. Click “Enable” and wait for setup to complete.

Next, let’s go to  BuildShip. You need to configure permissions for BuildShip to work with Firebase. Copy the service account from BuildShip and go to Google Cloud Platform. Select your project, navigate to IAM & Admin, and grant access.

Paste the service account and assign the following roles:

- Cloud Datastore User

- Firebase Admin SDK Service Agent

Save the changes. BuildShip and Firebase should now be integrated.

In BuildShip, create your first workflow for syncing data from Flutterflow to Firebase. Start by creating a new workflow named “sync.” Set up a REST POST request trigger with no parameters required.

Add a loop to iterate over each note.

Configure the loop to process each note based on its `is_in_sync` status. If `is_in_sync` is false, proceed to handle the note.

Create a branch to check if the note is marked for deletion. If true, use Firebase to delete the document. Specify the collection name as “Notes” and use the UUID from the note for the document ID.

If the note is not marked for deletion, either create or update the document in Firebase. Provide the collection name, document ID, and note details (is_in_sync, note content, UUID) for the data fields.

This workflow will loop through all notes from FlutterFlow, syncing or deleting them as needed.

Let’s review the code. It’s simple: it takes the input object, sets `is_in_sync` to true, and returns it. You can save it now and move on.

Next, add a Firestore node to create or update a document. Choose Firestore and select "Create Firestore Document." Copy the project ID and paste it into the project ID field. For the collection, use "notes," and for the document ID, select the ID from the loop’s item.

To merge document values, set "Merge" to true. For the data, use the object returned by `set_is_in_sync`. This ensures the object is updated in Firestore.

After configuring, return a status 200 at the end of the loop. Add a return node, set the status code to 200, and return a success message like `{"status": "ok", "message": "All notes are now in sync"}`.

Once your workflow is complete, click the "Ship" button to deploy it. Copy the endpoint URL provided, which you’ll use in FlutterFlow. 

In FlutterFlow, go to the API calls section and add a new API group. Name it “BuildShip" and use the base URL from the endpoint, omitting "/sync."

Add an API call named "sync," set it as a POST request, and create a variable for the notes with JSON type. 

In the body, use JSON format and include the notes array. Save the API call and test it. If there are errors, check your BuildShip workflow for issues and try testing again.

Finally, for data manipulation before sending it to BuildShip, consider using a custom function in your app state variable. This will allow you to format the data as needed.

Let's start with custom functions. In your project, you’ll find `convertNotesToJson` and `convertJsonToNotes`. The `convertNotesToJson` function is used when syncing. It transforms your app’s notes into a JSON format suitable for Build Chip. This function maps each note’s properties and converts dates to strings for consistency. When the data comes back, it will be converted back to date objects. This function prepares your data for BuildShip, and it’s a useful technique for handling data in your projects.

Next, we’ll connect this function to the sync button. In FlutterFlow, go to the sync button’s settings, open the action flow editor, and add an API call named `syncResult`.

Select the BuildShip group and the `sync` endpoint. For variables, choose the `notes` variable set up earlier.

Call the `convertNotesToJson` function and pass in the notes from app state.

After sending the notes, handle the response. Add an action to show a snack bar if the status is 200. Set the snack bar’s message to the status from the API response, use a green background for success, and white text. For errors, copy the snackbar action and adjust the background color to red.

Now, test your application. Add a note, save it, and try syncing. If there’s an error, check BuildShip logs for issues. Once resolved, retry syncing and verify that notes appear in Firebase. Test by updating and deleting notes to ensure everything works as expected.

Finally, set up Workflow 2 to restore notes. Create a new workflow named `restore`, add a POST REST API trigger with the path `restore`, and include a user ID parameter. For the Firestore query, set the project ID, collection to "notes," and filter by user ID to return only relevant notes.

To return data to your FlutterFlow application, add a return node with a status code of 200. Use JavaScript to set the status message to "OK." This setup handles the successful case; consider extending it for error handling if needed.

Name the returned value "result" or any other preferred name. Link it to the Firestore collection returning data. Save these settings, and deploy the workflow by clicking the ship option.

In Flutterflow, create some test notes and sync them. Verify their presence in Firebase, ensuring each note includes the user ID. The user ID is set when the app loads and is stored in the App State.

Test the workflow in BuildShip by simulating a request with the user ID. If there are issues, check for mistakes in the input values or parameters. Correct any errors and retest until the response is correct.

Once testing is successful, set up an API call in FlutterFlow. Name it "restore," set it as a POST request, and use the endpoint "restore" from BuildShip. Add a user ID parameter of type string to match the BuildShip setup.

Format the request body to include the user ID in double quotes. Test this API call to ensure it retrieves notes correctly. Use the JSON path to extract the notes from the response.

In Flutterflow, connect the restore button to the "restore" API call. Use the custom function `convertJsonToNotes` to update the application state with the retrieved notes. Select the appropriate JSON path to access the notes in the response.

To ensure the UI reflects the latest data, reload the UI tree. Add a navigation action to return to the homepage after restoring notes.

This workflow covers:

- Syncing and restoring notes between FlutterFlow and Firebase.

- Updating the application state with new data.

- Reflecting changes in the UI and navigating back to the homepage.

Consider enhancing the app with features like error handling, authentication, and additional data processing to better meet your needs.

———

This blog is based on a video by Steve from The Digital Pro's NoCode Academy YouTube channel. Steve is a Flutterflow Ambassador and a BuildShip Expert. Check out his entire playlist on building with BuildShip here.

For a complete video guide related to this blog, click below:

Conclusion

In summary, you’ve:

- Created a note-taking app in FlutterFlow.

- Synced notes with Firebase using BuildShip.

- Retrieved and displayed notes from Firebase.

- Established workflows for syncing and restoring notes.

This foundation will help you build more complex applications integrating with cloud services. Explore new features and customize as needed. We covered the entire process from building the basic app to integrating BuildShip workflows for data management.

Feel free to clone the provided project, follow along with the video tutorial, and explore how these tools can enhance your app development skills.

The circle of no-code is complete. You can build out full stack applications using FlutterFlow for your frontend and BuildShip for your backend with ease. To add to it, integrate with any database (Firebase, Supabase, PostgresSQL, MySQL) or choose from 100s of pre-built nodes from popular platforms like Sendgrid, WhatsApp, and AI models on OpenAI, Replicate, Hugging Face, etc. 

In this blog, we’ll explore how to easily use FlutterFlow and BuildShip together with Firebase. We’ll dive into creating custom data types and sending them to BuildShip for analysis and decision-making. You’ll see how users can build an app that stores data locally on their device, without relying on an external database. When they’re ready, they can sync this data to Firebase via BuildShip workflows for safe storage. Changes made to the data can be synced back to Firebase, and if needed, users can retrieve and restore their data from Firebase to their device.

Let’s walk through the scenario step-by-step so you can see exactly what this application will do.

Referring the image above, you’ll find our FlutterFlow application in action. Here, users can create, read, and update notes, all stored locally on their device—no external database involved. Each note is managed through custom data types, which are integrated into the application state.

When the user decides to sync their data, they simply navigate to the settings and press a button. This action triggers an API call to a BuildShip workflow, which processes the data and uploads it to a Firebase Firestore database.

Users can make changes to their notes and sync these updates back to Firebase as needed. If they want to delete all their data, they can press another button in the UI. This triggers a request to BuildShip, which retrieves the records from Firebase and sends them back to the FlutterFlow application.

One key point is that all data is associated with a user ID generated when the application first loads. No authentication is required; instead, we use this persistent variable in FlutterFlow to reference the data stored in Firebase.

This overview covers the main steps, and we’ll guide you through the entire process. We’ve already set up a basic FlutterFlow application with CRUD functionality. Although it doesn’t sync with BuildShip yet, we’ll work through that together in this blog. Clone the project to follow along and get hands-on experience.

Here are a couple of things we’ll cover in this blog. The main thing is really how to use FlutterFlow and BuildShip together, especially when working with custom data types. You’ll learn how to convert custom data type data into a JSON request for BuildShip and handle the API response back into FlutterFlow to convert it back to a custom data type for display. These techniques are really useful for those new to this kind of work.

Getting started with Flutterflow

Let’s talk through how this application actually works in a demo style. You can see here we’ve got the running application up in test mode. I’ve clicked on the little “Tabs” here for the actual notes itself, and you can see we have no notes installed in this application.

If you hit the little plus option, you can create some notes to demonstrate how the application works. For now, we’ve added all of our notes. 


Inside the actual UI itself, you can update the notes and work independently.

There's no active communication with a database in the background other than persisted storage using custom data types within your FlutterFlow applications. This provides offline capability to store data within the application. In Firebase, you can see there's nothing initially present in a brand new instance.

To sync notes to the server, click the little Cog option and hit "sync."

This makes a call to BuildShip, goes through various checks in the workflow, and if you go back to the actual project, the notes appear. Here are the three notes we created. 

Now, back in the application, you can make changes. For example, if you remove the description from the first note and hit save, the note is updated locally but not saved back to Firebase immediately. You can continue to use the application, make changes, mark notes as complete, or delete them, all locally. When ready, hitting the sync button updates the Firebase database, reflecting all changes.

You can also delete notes on the device. After hitting delete and confirming, the notes disappear locally. However, they are still on the server. By clicking the refresh option, all notes are pulled back to the device in the same state as they were persisted in Firebase. This provides the ability to work offline and sync changes back to the server when necessary.

In summary:

- The FlutterFlow application allows users to take notes.

- Notes can be synced with Firebase using BuildShip.

- Retrieved notes are displayed in the app.

- Workflows handle syncing and restoring notes.

Let's move into the core of the blog and show how everything ties together. At the start, we created an application you can clone to follow along. This application functions generally but lacks the ability to sync through workflows to Firebase, which is the focus of this blog. We will focus on working with BuildShip and Firebase, not building the Flutterflow application itself.

Here's what we have:

- No APIs initially.

- An App State variable containing a user ID, generated randomly when the application loads.

- A notes app state variable containing a list of notes.

- A custom data type "note" with fields like user ID, title, description, update count, created timestamp, is complete, mark for deletion, and is in sync.

In the widget tree:

- The notes page displays notes.

- The note editor component allows adding and updating notes, generating a unique ID, and associating notes with the user ID.

The action flows:

- Show the note editor on the notes page.

- Save button updates or creates a new note in the app state variable.

Syncing BuildShip with Firebase

Next, let's look at BuildShip and see how it ties together with Firebase. In BuildShip, different routes handle various tasks:

- A notes route with endpoints to get all notes and create new notes.

- An update route for updating notes.

- A delete route for deleting notes.

- A sync route for syncing notes with Firebase.

These routes and endpoints handle necessary operations and integrate with our Firebase database. Let's start setting up these endpoints and building out the routes to handle note operations in our application.

Let’s start with setting up a new project called “dpnotes” in Firebase. Go to Build > Firestore Database and create a database. Choose Europe for the location and start in test mode. Click “Enable” and wait for setup to complete.

Next, let’s go to  BuildShip. You need to configure permissions for BuildShip to work with Firebase. Copy the service account from BuildShip and go to Google Cloud Platform. Select your project, navigate to IAM & Admin, and grant access.

Paste the service account and assign the following roles:

- Cloud Datastore User

- Firebase Admin SDK Service Agent

Save the changes. BuildShip and Firebase should now be integrated.

In BuildShip, create your first workflow for syncing data from Flutterflow to Firebase. Start by creating a new workflow named “sync.” Set up a REST POST request trigger with no parameters required.

Add a loop to iterate over each note.

Configure the loop to process each note based on its `is_in_sync` status. If `is_in_sync` is false, proceed to handle the note.

Create a branch to check if the note is marked for deletion. If true, use Firebase to delete the document. Specify the collection name as “Notes” and use the UUID from the note for the document ID.

If the note is not marked for deletion, either create or update the document in Firebase. Provide the collection name, document ID, and note details (is_in_sync, note content, UUID) for the data fields.

This workflow will loop through all notes from FlutterFlow, syncing or deleting them as needed.

Let’s review the code. It’s simple: it takes the input object, sets `is_in_sync` to true, and returns it. You can save it now and move on.

Next, add a Firestore node to create or update a document. Choose Firestore and select "Create Firestore Document." Copy the project ID and paste it into the project ID field. For the collection, use "notes," and for the document ID, select the ID from the loop’s item.

To merge document values, set "Merge" to true. For the data, use the object returned by `set_is_in_sync`. This ensures the object is updated in Firestore.

After configuring, return a status 200 at the end of the loop. Add a return node, set the status code to 200, and return a success message like `{"status": "ok", "message": "All notes are now in sync"}`.

Once your workflow is complete, click the "Ship" button to deploy it. Copy the endpoint URL provided, which you’ll use in FlutterFlow. 

In FlutterFlow, go to the API calls section and add a new API group. Name it “BuildShip" and use the base URL from the endpoint, omitting "/sync."

Add an API call named "sync," set it as a POST request, and create a variable for the notes with JSON type. 

In the body, use JSON format and include the notes array. Save the API call and test it. If there are errors, check your BuildShip workflow for issues and try testing again.

Finally, for data manipulation before sending it to BuildShip, consider using a custom function in your app state variable. This will allow you to format the data as needed.

Let's start with custom functions. In your project, you’ll find `convertNotesToJson` and `convertJsonToNotes`. The `convertNotesToJson` function is used when syncing. It transforms your app’s notes into a JSON format suitable for Build Chip. This function maps each note’s properties and converts dates to strings for consistency. When the data comes back, it will be converted back to date objects. This function prepares your data for BuildShip, and it’s a useful technique for handling data in your projects.

Next, we’ll connect this function to the sync button. In FlutterFlow, go to the sync button’s settings, open the action flow editor, and add an API call named `syncResult`.

Select the BuildShip group and the `sync` endpoint. For variables, choose the `notes` variable set up earlier.

Call the `convertNotesToJson` function and pass in the notes from app state.

After sending the notes, handle the response. Add an action to show a snack bar if the status is 200. Set the snack bar’s message to the status from the API response, use a green background for success, and white text. For errors, copy the snackbar action and adjust the background color to red.

Now, test your application. Add a note, save it, and try syncing. If there’s an error, check BuildShip logs for issues. Once resolved, retry syncing and verify that notes appear in Firebase. Test by updating and deleting notes to ensure everything works as expected.

Finally, set up Workflow 2 to restore notes. Create a new workflow named `restore`, add a POST REST API trigger with the path `restore`, and include a user ID parameter. For the Firestore query, set the project ID, collection to "notes," and filter by user ID to return only relevant notes.

To return data to your FlutterFlow application, add a return node with a status code of 200. Use JavaScript to set the status message to "OK." This setup handles the successful case; consider extending it for error handling if needed.

Name the returned value "result" or any other preferred name. Link it to the Firestore collection returning data. Save these settings, and deploy the workflow by clicking the ship option.

In Flutterflow, create some test notes and sync them. Verify their presence in Firebase, ensuring each note includes the user ID. The user ID is set when the app loads and is stored in the App State.

Test the workflow in BuildShip by simulating a request with the user ID. If there are issues, check for mistakes in the input values or parameters. Correct any errors and retest until the response is correct.

Once testing is successful, set up an API call in FlutterFlow. Name it "restore," set it as a POST request, and use the endpoint "restore" from BuildShip. Add a user ID parameter of type string to match the BuildShip setup.

Format the request body to include the user ID in double quotes. Test this API call to ensure it retrieves notes correctly. Use the JSON path to extract the notes from the response.

In Flutterflow, connect the restore button to the "restore" API call. Use the custom function `convertJsonToNotes` to update the application state with the retrieved notes. Select the appropriate JSON path to access the notes in the response.

To ensure the UI reflects the latest data, reload the UI tree. Add a navigation action to return to the homepage after restoring notes.

This workflow covers:

- Syncing and restoring notes between FlutterFlow and Firebase.

- Updating the application state with new data.

- Reflecting changes in the UI and navigating back to the homepage.

Consider enhancing the app with features like error handling, authentication, and additional data processing to better meet your needs.

———

This blog is based on a video by Steve from The Digital Pro's NoCode Academy YouTube channel. Steve is a Flutterflow Ambassador and a BuildShip Expert. Check out his entire playlist on building with BuildShip here.

For a complete video guide related to this blog, click below:

Conclusion

In summary, you’ve:

- Created a note-taking app in FlutterFlow.

- Synced notes with Firebase using BuildShip.

- Retrieved and displayed notes from Firebase.

- Established workflows for syncing and restoring notes.

This foundation will help you build more complex applications integrating with cloud services. Explore new features and customize as needed. We covered the entire process from building the basic app to integrating BuildShip workflows for data management.

Feel free to clone the provided project, follow along with the video tutorial, and explore how these tools can enhance your app development skills.

The circle of no-code is complete. You can build out full stack applications using FlutterFlow for your frontend and BuildShip for your backend with ease. To add to it, integrate with any database (Firebase, Supabase, PostgresSQL, MySQL) or choose from 100s of pre-built nodes from popular platforms like Sendgrid, WhatsApp, and AI models on OpenAI, Replicate, Hugging Face, etc. 

In this blog, we’ll explore how to easily use FlutterFlow and BuildShip together with Firebase. We’ll dive into creating custom data types and sending them to BuildShip for analysis and decision-making. You’ll see how users can build an app that stores data locally on their device, without relying on an external database. When they’re ready, they can sync this data to Firebase via BuildShip workflows for safe storage. Changes made to the data can be synced back to Firebase, and if needed, users can retrieve and restore their data from Firebase to their device.

Let’s walk through the scenario step-by-step so you can see exactly what this application will do.

Referring the image above, you’ll find our FlutterFlow application in action. Here, users can create, read, and update notes, all stored locally on their device—no external database involved. Each note is managed through custom data types, which are integrated into the application state.

When the user decides to sync their data, they simply navigate to the settings and press a button. This action triggers an API call to a BuildShip workflow, which processes the data and uploads it to a Firebase Firestore database.

Users can make changes to their notes and sync these updates back to Firebase as needed. If they want to delete all their data, they can press another button in the UI. This triggers a request to BuildShip, which retrieves the records from Firebase and sends them back to the FlutterFlow application.

One key point is that all data is associated with a user ID generated when the application first loads. No authentication is required; instead, we use this persistent variable in FlutterFlow to reference the data stored in Firebase.

This overview covers the main steps, and we’ll guide you through the entire process. We’ve already set up a basic FlutterFlow application with CRUD functionality. Although it doesn’t sync with BuildShip yet, we’ll work through that together in this blog. Clone the project to follow along and get hands-on experience.

Here are a couple of things we’ll cover in this blog. The main thing is really how to use FlutterFlow and BuildShip together, especially when working with custom data types. You’ll learn how to convert custom data type data into a JSON request for BuildShip and handle the API response back into FlutterFlow to convert it back to a custom data type for display. These techniques are really useful for those new to this kind of work.

Getting started with Flutterflow

Let’s talk through how this application actually works in a demo style. You can see here we’ve got the running application up in test mode. I’ve clicked on the little “Tabs” here for the actual notes itself, and you can see we have no notes installed in this application.

If you hit the little plus option, you can create some notes to demonstrate how the application works. For now, we’ve added all of our notes. 


Inside the actual UI itself, you can update the notes and work independently.

There's no active communication with a database in the background other than persisted storage using custom data types within your FlutterFlow applications. This provides offline capability to store data within the application. In Firebase, you can see there's nothing initially present in a brand new instance.

To sync notes to the server, click the little Cog option and hit "sync."

This makes a call to BuildShip, goes through various checks in the workflow, and if you go back to the actual project, the notes appear. Here are the three notes we created. 

Now, back in the application, you can make changes. For example, if you remove the description from the first note and hit save, the note is updated locally but not saved back to Firebase immediately. You can continue to use the application, make changes, mark notes as complete, or delete them, all locally. When ready, hitting the sync button updates the Firebase database, reflecting all changes.

You can also delete notes on the device. After hitting delete and confirming, the notes disappear locally. However, they are still on the server. By clicking the refresh option, all notes are pulled back to the device in the same state as they were persisted in Firebase. This provides the ability to work offline and sync changes back to the server when necessary.

In summary:

- The FlutterFlow application allows users to take notes.

- Notes can be synced with Firebase using BuildShip.

- Retrieved notes are displayed in the app.

- Workflows handle syncing and restoring notes.

Let's move into the core of the blog and show how everything ties together. At the start, we created an application you can clone to follow along. This application functions generally but lacks the ability to sync through workflows to Firebase, which is the focus of this blog. We will focus on working with BuildShip and Firebase, not building the Flutterflow application itself.

Here's what we have:

- No APIs initially.

- An App State variable containing a user ID, generated randomly when the application loads.

- A notes app state variable containing a list of notes.

- A custom data type "note" with fields like user ID, title, description, update count, created timestamp, is complete, mark for deletion, and is in sync.

In the widget tree:

- The notes page displays notes.

- The note editor component allows adding and updating notes, generating a unique ID, and associating notes with the user ID.

The action flows:

- Show the note editor on the notes page.

- Save button updates or creates a new note in the app state variable.

Syncing BuildShip with Firebase

Next, let's look at BuildShip and see how it ties together with Firebase. In BuildShip, different routes handle various tasks:

- A notes route with endpoints to get all notes and create new notes.

- An update route for updating notes.

- A delete route for deleting notes.

- A sync route for syncing notes with Firebase.

These routes and endpoints handle necessary operations and integrate with our Firebase database. Let's start setting up these endpoints and building out the routes to handle note operations in our application.

Let’s start with setting up a new project called “dpnotes” in Firebase. Go to Build > Firestore Database and create a database. Choose Europe for the location and start in test mode. Click “Enable” and wait for setup to complete.

Next, let’s go to  BuildShip. You need to configure permissions for BuildShip to work with Firebase. Copy the service account from BuildShip and go to Google Cloud Platform. Select your project, navigate to IAM & Admin, and grant access.

Paste the service account and assign the following roles:

- Cloud Datastore User

- Firebase Admin SDK Service Agent

Save the changes. BuildShip and Firebase should now be integrated.

In BuildShip, create your first workflow for syncing data from Flutterflow to Firebase. Start by creating a new workflow named “sync.” Set up a REST POST request trigger with no parameters required.

Add a loop to iterate over each note.

Configure the loop to process each note based on its `is_in_sync` status. If `is_in_sync` is false, proceed to handle the note.

Create a branch to check if the note is marked for deletion. If true, use Firebase to delete the document. Specify the collection name as “Notes” and use the UUID from the note for the document ID.

If the note is not marked for deletion, either create or update the document in Firebase. Provide the collection name, document ID, and note details (is_in_sync, note content, UUID) for the data fields.

This workflow will loop through all notes from FlutterFlow, syncing or deleting them as needed.

Let’s review the code. It’s simple: it takes the input object, sets `is_in_sync` to true, and returns it. You can save it now and move on.

Next, add a Firestore node to create or update a document. Choose Firestore and select "Create Firestore Document." Copy the project ID and paste it into the project ID field. For the collection, use "notes," and for the document ID, select the ID from the loop’s item.

To merge document values, set "Merge" to true. For the data, use the object returned by `set_is_in_sync`. This ensures the object is updated in Firestore.

After configuring, return a status 200 at the end of the loop. Add a return node, set the status code to 200, and return a success message like `{"status": "ok", "message": "All notes are now in sync"}`.

Once your workflow is complete, click the "Ship" button to deploy it. Copy the endpoint URL provided, which you’ll use in FlutterFlow. 

In FlutterFlow, go to the API calls section and add a new API group. Name it “BuildShip" and use the base URL from the endpoint, omitting "/sync."

Add an API call named "sync," set it as a POST request, and create a variable for the notes with JSON type. 

In the body, use JSON format and include the notes array. Save the API call and test it. If there are errors, check your BuildShip workflow for issues and try testing again.

Finally, for data manipulation before sending it to BuildShip, consider using a custom function in your app state variable. This will allow you to format the data as needed.

Let's start with custom functions. In your project, you’ll find `convertNotesToJson` and `convertJsonToNotes`. The `convertNotesToJson` function is used when syncing. It transforms your app’s notes into a JSON format suitable for Build Chip. This function maps each note’s properties and converts dates to strings for consistency. When the data comes back, it will be converted back to date objects. This function prepares your data for BuildShip, and it’s a useful technique for handling data in your projects.

Next, we’ll connect this function to the sync button. In FlutterFlow, go to the sync button’s settings, open the action flow editor, and add an API call named `syncResult`.

Select the BuildShip group and the `sync` endpoint. For variables, choose the `notes` variable set up earlier.

Call the `convertNotesToJson` function and pass in the notes from app state.

After sending the notes, handle the response. Add an action to show a snack bar if the status is 200. Set the snack bar’s message to the status from the API response, use a green background for success, and white text. For errors, copy the snackbar action and adjust the background color to red.

Now, test your application. Add a note, save it, and try syncing. If there’s an error, check BuildShip logs for issues. Once resolved, retry syncing and verify that notes appear in Firebase. Test by updating and deleting notes to ensure everything works as expected.

Finally, set up Workflow 2 to restore notes. Create a new workflow named `restore`, add a POST REST API trigger with the path `restore`, and include a user ID parameter. For the Firestore query, set the project ID, collection to "notes," and filter by user ID to return only relevant notes.

To return data to your FlutterFlow application, add a return node with a status code of 200. Use JavaScript to set the status message to "OK." This setup handles the successful case; consider extending it for error handling if needed.

Name the returned value "result" or any other preferred name. Link it to the Firestore collection returning data. Save these settings, and deploy the workflow by clicking the ship option.

In Flutterflow, create some test notes and sync them. Verify their presence in Firebase, ensuring each note includes the user ID. The user ID is set when the app loads and is stored in the App State.

Test the workflow in BuildShip by simulating a request with the user ID. If there are issues, check for mistakes in the input values or parameters. Correct any errors and retest until the response is correct.

Once testing is successful, set up an API call in FlutterFlow. Name it "restore," set it as a POST request, and use the endpoint "restore" from BuildShip. Add a user ID parameter of type string to match the BuildShip setup.

Format the request body to include the user ID in double quotes. Test this API call to ensure it retrieves notes correctly. Use the JSON path to extract the notes from the response.

In Flutterflow, connect the restore button to the "restore" API call. Use the custom function `convertJsonToNotes` to update the application state with the retrieved notes. Select the appropriate JSON path to access the notes in the response.

To ensure the UI reflects the latest data, reload the UI tree. Add a navigation action to return to the homepage after restoring notes.

This workflow covers:

- Syncing and restoring notes between FlutterFlow and Firebase.

- Updating the application state with new data.

- Reflecting changes in the UI and navigating back to the homepage.

Consider enhancing the app with features like error handling, authentication, and additional data processing to better meet your needs.

———

This blog is based on a video by Steve from The Digital Pro's NoCode Academy YouTube channel. Steve is a Flutterflow Ambassador and a BuildShip Expert. Check out his entire playlist on building with BuildShip here.

For a complete video guide related to this blog, click below:

Conclusion

In summary, you’ve:

- Created a note-taking app in FlutterFlow.

- Synced notes with Firebase using BuildShip.

- Retrieved and displayed notes from Firebase.

- Established workflows for syncing and restoring notes.

This foundation will help you build more complex applications integrating with cloud services. Explore new features and customize as needed. We covered the entire process from building the basic app to integrating BuildShip workflows for data management.

Feel free to clone the provided project, follow along with the video tutorial, and explore how these tools can enhance your app development skills.

Start building your
BIGGEST ideas
in the *simplest* of ways.

Start building your
BIGGEST ideas
in the *simplest* of ways.

Start building your
BIGGEST ideas
in the *simplest* of ways.

You might also like