Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.
Used in conjunction with FlutterFlow, PowerSync enables developers to build local-first apps that are robust in poor network conditions and that have highly responsive frontends while relying on Supabase for their backend. This guide walks you through configuring PowerSync within your FlutterFlow project that has Supabase integration enabled.
New and Improved integration: Welcome to our updated FlutterFlow integration guide. This version introduces a dedicated PowerSync FlutterFlow Library, offering a simpler and more robust solution compared to the previous version which required extensive custom code.Key improvements are:
Working Attachments package - learn how to sync attachments here.
Note that using libraries in FlutterFlow requires being on a paid plan with FlutterFlow. If this is not an option for you, you can use our legacy guide with custom code to integrate PowerSync in your FlutterFlow project.
This guide uses Supabase as the backend source database provider for its seamless integration with PowerSync. However, you can integrate a different backend using custom actions. For more information, refer to the Custom backend connectors section.
A paid plan with FlutterFlow for the ability to import a Library into a project.
This guide walks you through building a basic item management app from scratch and takes about 30-40 minutes to complete. You should then be able to use this knowledge to build and extend your own app.
To set up the Postgres database for our demo app, we will create a lists table. The demo app will have access to this table even while offline. Run the below SQL statement in your Supabase SQL Editor:
create tablepublic.lists ( id uuid not null default gen_random_uuid (), created_at timestamp with time zone not null default now(), name text not null, owner_id uuid not null, constraint lists_pkey primary key (id), constraint lists_owner_id_fkey foreign key (owner_id) references auth.users (id) on delete cascade) tablespace pg_default
PowerSync uses the Postgres Write Ahead Log (WAL) to replicate data changes in order to keep PowerSync SDK clients up to date. Run the below SQL statement in your Supabase SQL Editor to create a Postgres role/user with replication privileges:
-- Create a role/user with replication privileges for PowerSyncCREATE ROLE powersync_role WITH REPLICATION BYPASSRLS LOGIN PASSWORD 'myhighlyrandompassword';-- Set up permissions for the newly created role-- Read-only (SELECT) access is requiredGRANT SELECT ON ALL TABLES IN SCHEMA public TO powersync_role; -- Optionally, grant SELECT on all future tables (to cater for schema additions)ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO powersync_role;
To restrict read access to specific tables, explicitly list allowed tables for both the SELECT privilege, and for the publication mentioned in the next step (as well as for any other publications that may exist).
Create a Postgres publication using the SQL Editor. This will enable data to be replicated from Supabase so that your FlutterFlow app can download it.
-- Create a publication to replicate tables. The publication must be named "powersync"CREATE PUBLICATION powersync FOR ALL TABLES;
Note that the PowerSync Service has to read all updates present in the publication, regardless of whether the table is referenced in your Sync Streams. This can cause large spikes in memory usage or introduce replication delays, so if you’re dealing with large data volumes, you’ll want to specify a comma-separated subset of tables to replicate instead of FOR ALL TABLES.
The snippet above replicates all tables and is the simplest way to get started in a dev environment.
When creating a project in the PowerSync Dashboard, Development and Production instances of the PowerSync Service will be created by default. Select the instance you want to configure.If you need to create a new instance, follow the steps below.
In the dashboard, select your project and open the instance selection dropdown. Click Add Instance.
Give your instance a name, such as “Production”.
[Optional] You can change the default cloud region. You can’t change the region after you create the instance. See Regions for details.
In the PowerSync Dashboard, go to the Client Auth view.
Select Use Supabase Auth.
If your Supabase project uses legacy JWT secrets, copy the JWT secret from your project’s JWT Keys settings into Supabase JWT Secret (optional). If your project uses JWT signing keys, leave this field empty. PowerSync configures your project’s signing keys automatically.
Sync Rules allow developers to control which data gets synced to which user devices using a SQL-like syntax in a YAML file. For the demo app, we’re going to specify that each user can only see their own lists.
In the PowerSync Dashboard, select your project and instance and go to the Sync Rules view.
Edit the Sync Rules in the editor and replace the contents with the below:
# This will sync the entire table to all users - we will refine this laterbucket_definitions: global: data: - SELECT * FROM lists
Click “Validate” and ensure there are no errors. This validates your Sync Rules against your Postgres database.
Click “Deploy” to deploy your Sync Rules.
Confirm in the dialog and wait a couple of minutes for the deployment to complete.
For additional information on PowerSync’s Sync Rules, refer to the Sync Rules documentation.
If you’re wondering how Sync Rules relate to Supabase Postgres RLS, see this subsection.
Under “App Settings” -> “Integrations”, enable “Supabase”.
Enter your Supabase “API URL” and public “Anon Key”. You can find these under “Project Settings” -> “API Keys” -> anonpublic in your Supabase dashboard.
In the PowerSync Dashboard, select your project and instance and click the Connect button in the top bar to generate the client-side schema based on your Sync Rules. Select “FlutterFlow” as the language.
Copy and paste the generated schema into the “PowerSyncSchema” field.
Copy and paste your PowerSync instance URL into the “PowerSyncUrl” field.
Note: The default path for the “HomePage” field under “Library Pages” can be left as is and ignored. FlutterFlow does not currently provide a way to remove it.
Close the library config.
Under “Custom Pub Dependencies”, add a dependency on powersync_core:1.3.0:
This version of powersync_core is required for running FlutterFlow on Web.
Under the “Page Selector”, click “Add Page, Component, or Flow”.
Select the “Auth 1” template and name the page Login.
Delete the Sign Up, Forgot Password and Social Login buttons — we will only be supporting Sign In for this demo app.
Under “App Settings” -> “App Settings” -> “Authentication”:
Enable Authentication.
Set “Authentication Type” to “Supabase”.
Set “Entry Page” to the Login page you just created.
Set “Logged In Page” to “HomePage”.
In your Supabase Dashboard, under “Authentication”, click on “Add User” -> “Create new user” and create a user for yourself to test with:
Test your app with test mode:
Click on 'Test'
Checkpoint: You should now be able to log into the app using the Supabase user account you just created. After logging in you should see a blank screen.
We will now create our first UI and bind it to the data in the local SQLite database on the device.There are three ways to read data from the SQLite database using PowerSync’s FlutterFlow library:
Auto-updating queries for Layout Elements with Dynamic Children e.g. the ListView Element
This uses the library’s PowerSyncQuery component.
Auto-updating queries for basic Layout Elements e.g. Text Elements.
This uses the library’s PowerSyncStateUpdater component.
Once-off reads for static data.
This uses the library’s PowerSyncQueryOnce custom action.
For reading data in FlutterFlow, you need a Custom Function per Supabase table to map Supabase rows to data that can be used by the library. This is because FlutterFlow Libraries do not support Supabase classes.
Navigate to “Custom Code” and add a Custom Function.
Name the function supabaseRowsToList (if your Supabase table name is “Customers”, you would name this supabaseRowsToCustomers).
Under Function Settings on the right, set the “Return Value” to Supabase Row
Check “Is List”.
Uncheck “Nullable”.
Under “Table Name”, select lists.
Also under Function Settings, click “Add Arguments”.
Set its “Name” to supabaseRows
Set its “Type” to “JSON”.
Check “Is List”.
Uncheck “Nullable”.
In the Function Code, paste the following code:
/// MODIFY CODE ONLY BELOW THIS LINEreturn supabaseRows.map((r) => ListsRow(r)).toList();
Click “Save Function”.
Custom function to map the lists table from Supabase
Notice that your homepage is still blank. This is because the lists table is empty in Supabase. Create a test row in the table by clicking on “Insert” -> “Insert Row” in your Supabase Table Editor.
Leave id and created_at blank.
Enter a name such as “Test from Supabase”.
Click “Select Record” for owner_id and select your test user.
Checkpoint: You should now see your single test row magically appear in your app:
2. Auto-Updating Queries for Basic Layout Elements
In this section, we will be making the ListView component clickable and navigate the user to a page which will eventually display the list’s To-Do items. This page will show the selected list’s name in the title bar (“AppBar”). This uses Page State and the PowerSyncStateUpdater library component.
Under the “Widget Palette”, select the “Components and custom widgets imported from library projects” panel.
Drag the PowerSyncStateUpdater library component into your page.
Under the “Widget Tree”, select the PowerSyncStateUpdater component.
In the “Properties” panel on the right, under “Component Parameters”:
Add the SQL query to fetch the selected list from the SQLite database. Paste the following into the “sql [String]” field: select * from lists where id = :id;
Click on “parameters [Json]” select “Create Map (JSON)” as the variable.
Under “Add Map Entries”, click “Add Key Value Pair”.
Set the “Key” to id.
Set the “Value” to the page parameter created previously called id.
Check “watch [Boolean]”. This ensures that the query auto-updates.
Click “Confirm”.
Still under “Component Parameters”, configure the onData action:
Open the “Action Flow Editor”.
Select the “Callback” trigger type.
Click “Add Action”.
Search for “update page” and select “Update Page State”.
Click “Add Field”.
Select your list page state variable.
Set “Select Update Type” to “Set Value”.
Set “Value to set” to “Custom Functions” -> supabaseRowsToList.
Set the “Value” to “Callback Parameters” -> rows
Click “Confirm”.
Under “Available Options”, select “Item at Index”.
Set “List Index Options” to “First”
Click “Confirm”.
Close the Action Flow Editor.
Still under the “Widget Tree”, select the “AppBar” -> “Text” widget.
In the “Properties” panel on the right, click on settings icon next to “Text”.
Click on “Page State” -> “List”.
Set “Supabase Row Fields” to “name”.
(Optional) Set the “Default Variable Value” to List Name.
You will now update the app so that we can capture new list entries.
Under the “Page Selector”, select your HomePage page.
Under the “Widget Palette”, search for “float” and drag the “FAB” widget onto your page.
In the “Actions” panel on the right, click “Add Action”.
Under “Custom Action” -> “PowerSync”, select powersyncWrite.
Under the “Set Action Arguments” -> “sql” section, add the SQL query to create a new list item. For the purpose of this guide we are hardcoding the list’s name, normally you would build UI for this.
Paste the following into the “Value” field: INSERT INTO lists(id, created_at, name, owner_id) VALUES(uuid(), datetime(), 'new item', :userId);
Under the “parameters” section, set the userId parameter we’re using the above query:
Click on “UNSET”.
Select “Create Map (JSON)” as the variable.
Under “Add Map Entries”, click “Add Key Value Pair”.
Set the “Key” to userId.
Set the “Value” to “Authenticated User” -> “User ID”.
Click “Confirm”.
Checkpoint: Reload your app and click on the + floating action button. A new list item should appear, which also automatically syncs to Supabase:
Updating data is possible today using the powersyncWrite helper of the Library, and a guide will be published soon. In the mean time, use the section below about Deleting Data as a reference. Please reach out on our Discord if you have any questions.
Navigate to “Custom Code” and create a new Custom Action called signOut without Arguments or Return Values and paste the below code:
In the below code, power_sync_b0w5r9 is the project ID of the PowerSync library. Update it if it changes.
// Automatic FlutterFlow importsimport '/backend/supabase/supabase.dart';import "package:power_sync_b0w5r9/backend/schema/structs/index.dart" as power_sync_b0w5r9_data_schema;import 'package:ff_theme/flutter_flow/flutter_flow_theme.dart';import '/flutter_flow/flutter_flow_util.dart';import '/custom_code/actions/index.dart'; // Imports other custom actionsimport '/flutter_flow/custom_functions.dart'; // Imports custom functionsimport 'package:flutter/material.dart';// Begin custom action code// DO NOT REMOVE OR MODIFY THE CODE ABOVE!import 'package:power_sync_b0w5r9/custom_code/actions/initialize_power_sync.dart' as ps;Future signOut() async { final database = await ps.getOrInitializeDatabase(); //await database.disconnectAndClear(); // this will completely delete all the local data, use with caution as there may be items still in the upload queue await database .disconnect(); //this will simply disconnect from the PowerSync Service and preserve all local data}// Set your action name, define your arguments and return parameter,// and then add the boilerplate code using the green button on the right!
Click “Save Action”.
Under the “Page Selector”, select your HomePage page.
Under the “Widget Palette”, drag a “Button” onto the right of your “AppBar”.
In the “Properties” panel on the right, rename the “Button Text” to Sign Out.
Switch to the “Actions” panel and open the “Action Flow Editor”.
Select “On Tap” as the action trigger.
Click “Add Action” and add a call to the signOut Custom Action.
Chain another Action and call to “Supabase Authentication” -> “Log Out”:
Click “Close”.
Checkpoint: You should now be able to reload your app and sign out and in again.
The PowerSync library provides a built-in component that displays real-time connectivity and sync status. Since the sync state is available globally as part of your app state, you can easily monitor the database status throughout your application. To add this status indicator:
Under the Widget Palette, select the “Components and custom widgets imported from library projects” panel.
Drag the PowerSyncConnectivity component into your home page’s “AppBar”.
PowerSync’s Sync Rules and Supabase’s support for Row Level Security (RLS) can be used in conjunction. Here are some high level similarities and differences:
RLS should be used as the authoritative set of security rules applied to your users’ CRUD operations that reach Postgres.
Sync Rules are only applied for data that is to be downloaded to clients — they do not apply to uploaded data.
Sync Rules can typically be considered to be complementary to RLS, and will generally mirror your RLS setup.
Currently all lists are synced to all users, regardless of who the owner of the list is. You will now update this so that only a user’s lists are synced to their device:
In the PowerSync Dashboard, select your project and instance and go to the Sync Rules view.
Edit the Sync Rules in the editor and replace the contents with the below:
bucket_definitions: user_lists: parameters: select request.user_id() as user_id data: - select * from lists where owner_id = bucket.user_id
Click “Validate”.
Click “Deploy” to deploy your Sync Rules.
Wait for the deploy to complete.
Checkpoint: Your app should continue running seamlessly as before.
For column values, PowerSync supports three basic types: Integers, doubles, and strings. These types have been chosen because they’re natively supported by SQLite while also being easy to transport as JSON.Of course, you may want to store other values in your Postgres database as well. When syncing a value that doesn’t fit into the three fundamental types, PowerSync will encode it as a JSON string. To use those values in your app, you’ll need to apply a mapping so that you display the correct values and use the correct representation when uploading data.As an example, let’s consider an added tags column on the lists table used in this guide. These tags will be encoded as a string array in Postgres:
Like all array values, PowerSync will transport this as a JSON string. For instance, a row with the default tags would be represented as this string: ["default", "tags"]. FlutterFlow does not support extracting a list from that string, so the custom functions responsible for mapping SQLite rows to FlutterFlow classes needs to be aware of the transformation and reverse it:
/// MODIFY CODE ONLY BELOW THIS LINEreturn supabaseRows.map((r) { return ListsRow({ ...r, 'tags': jsonDecode(r['tags'] as String), });}).toList();
This transforms the '["default", "tags"]' value as it appears into ["default", "tags"], the list value expected for this row.A similar approach is necessary when making local writes. The local database should be consistent with the data synced with PowerSync. So all local writes should write array and JSON values as strings by encoding them as JSON.Finally, the PowerSync mapping also needs to be reverted when uploading rows to Postgres. For a text[] column for instance, the local string value would not be accepted by Supabase. For this reason, the upload behavior for columns with advanced types needs to be customized.
New feature: This option has been added in version 0.0.7 of the PowerSync FlutterFlow library. Please make sure you’re using that version or later.
To customize the uploading behavior, create a new custom action (e.g. applyPowerSyncOptions). After the default imports, put this snippet:
import 'package:power_sync_b0w5r9/custom_code/actions/initialize_power_sync.dart';Future applyPowerSyncOptions() async { // Add your function code here! powerSyncOptions.transformData = (table, data) { switch (table) { case 'lists': data['tags'] = jsonDecode(data['tags'] as String); } };}
Also, add this function to your main.dart as a final action.When setting powersyncOptions.transformData, a callback is invoked every time a created or updated row is uploaded to Supabase. This allows you to customize how individual values are represented for Postgres. In this case, the tags column of the lists table is decoded as JSON so that it’s uploaded as a proper array while being stored as a list locally.
To enable an easy setup, the PowerSync FlutterFlow library integrates with Supabase by default. This means that as long as you use Supabase for authentication in your app, PowerSync will automatically connect as soon as users log in, and can automatically upload local writes to a Supabase database.For apps that don’t use Supabase, you can disable this default behavior and instead rely on your own backend connectors. For this, create your own custom action (e.g. applyPowerSyncOptions). It’s important that this action runs before anything else in your app uses PowerSync, so add this action to your main.dart as a final action.
import 'package:power_sync_b0w5r9/custom_code/actions/initialize_power_sync.dart';import 'package:powersync/powersync.dart' as ps;Future applyPowerSyncOptions() async { // Disable the default Supabase integration powerSyncOptions.useSupabaseConnector = false; final db = await getOrInitializeDatabase(); // TODO: Write your own connector and call connect/disconnect when a user logs // in. db.connect(connector: _MyCustomConnector());}final class _MyCustomConnector extends ps.PowerSyncBackendConnector { @override Future<ps.PowerSyncCredentials?> fetchCredentials() { // TODO: implement fetchCredentials throw UnimplementedError(); } @override Future<void> uploadData(ps.PowerSyncDatabase database) { // TODO: implement uploadData throw UnimplementedError(); }}
Deploying to the Apple App Store currently requires some workarounds due to limitations in FlutterFlow:
Download the code from FlutterFlow.
Open the Podfile located in the ios/ directory.
The following option in the Podfile needs to be updated from use_frameworks! :linkage => :static to use_frameworks! (remove everything after the exclamation sign).
After removing that option, clean the build folder and build the project again.
You should now be able to submit to the App Store.
Exporting the code from FlutterFlow using the “Download Code” action in FlutterFlow requires the same workaround listed above.
The PowerSync FlutterFlow Library does not currently support encryption at rest.
Other common issues and troubleshooting techniques are documented here: Troubleshooting.
{"docsConfig":{"theme":"almond","$schema":"https://mintlify.com/docs.json","name":"PowerSync","description":"PowerSync keeps a client-side SQLite database in sync with your backend database. Changes appear across users and devices in real time, user interactions feel instant, and your app continues to work even when offline.","colors":{"primary":"#4e89ff","light":"#4e89ff","dark":"#4e89ff"},"logo":{"light":"https://mintcdn.com/powersync/GTJdSKFSfUc2Sxtc/logo/light.svg?fit=max\u0026auto=format\u0026n=GTJdSKFSfUc2Sxtc\u0026q=85\u0026s=031755afb1ccb9d103407a97dbba0f77","dark":"https://mintcdn.com/powersync/GTJdSKFSfUc2Sxtc/logo/dark.svg?fit=max\u0026auto=format\u0026n=GTJdSKFSfUc2Sxtc\u0026q=85\u0026s=badf66d7ec3d69f747082c7d1090c613","href":"https://www.powersync.com/"},"favicon":"https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/favicon.png?fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=5e9a946a297885a946b02d1e401c9053","appearance":{"default":"system"},"navbar":{"links":[{"href":"https://dashboard.powersync.com/","label":"Dashboard"}],"primary":{"type":"button","label":"Get Started","href":"https://accounts.powersync.com/portal/powersync-signup?s=docs"}},"footer":{"socials":{"github":"https://github.com/powersync-ja","discord":"https://discord.com/invite/powersync","bluesky":"https://bsky.app/profile/powersync.com","x":"https://x.com/powersync_","youtube":"https://www.youtube.com/@powersync_","linkedin":"https://www.linkedin.com/showcase/journeyapps-powersync"},"links":[{"header":"Resources","items":[{"label":"Release Notes","href":"https://releases.powersync.com"},{"label":"System Status","href":"https://status.powersync.com/"},{"label":"Roadmap","href":"https://roadmap.powersync.com"},{"label":"Blog","href":"https://www.powersync.com/blog"}]}]},"seo":{"metatags":{"canonical":"https://docs.powersync.com","og:locale":"en_US","twitter:site":"@powersync_"},"organization":{"id":"https://www.powersync.com/#organization","name":"PowerSync","url":"https://www.powersync.com","logo":"https://docs.powersync.com/images/logo.png","sameAs":["https://github.com/powersync-ja","https://x.com/powersync_","https://www.linkedin.com/showcase/journeyapps-powersync/","https://bsky.app/profile/powersync.com"]}},"contextual":{"options":["copy","view","chatgpt","claude","mcp","cursor","vscode"],"display":"header"},"interaction":{"drilldown":true},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/powersync-ja"},{"anchor":"Community Discord","icon":"discord","href":"https://discord.com/invite/powersync"},{"anchor":"PowerSync Website","icon":"browser","href":"https://www.powersync.com/"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"powersync","hasAudioNarration":false,"actualSubdomain":"powersync","customDomains":["docs.powersync.com"],"gitSource":{"type":"github","owner":"powersync-ja","repo":"powersync-docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae1f217b41e76453cfc355a","collectionId":"648945fa-88a2-4de1-9b9f-e1af5a7c9a15","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae1f217b41e76453cfc355a"},"feedback":{"thumbs":false,"issues":true,"edits":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae1f217b41e76453cfc355a","clientVersion":"0.0.4006","searchFilterCounts":[{"language":"default","tag":"Client SDKs","count":63},{"language":"default","tag":"Sync Streams","count":38},{"language":"default","tag":"Advanced","count":33},{"language":"default","tag":"Maintenance \u0026 Ops","count":24},{"language":"default","tag":"JavaScript","count":20},{"language":"default","tag":"Configuration Details","count":18},{"language":"default","tag":"Sync Rules (Legacy)","count":15},{"language":"default","tag":"Self-Hosting","count":14},{"language":"default","tag":"Resources","count":14},{"language":"default","tag":"Tools","count":13}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[{"filePath":"styles.css","content":"@import url(https://fonts.googleapis.com/css2?Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900\u0026display=swap);body,h1,h2,h3,h4,h5,h6{font-family:'Inter',sans-serif}@media (min-width:1600px){.max-w-xl{max-width:50rem!important}}"}],"page":{"pagePath":"integrations/flutterflow/guide","slug":"/integrations/flutterflow/guide","pageMetadata":{"title":"FlutterFlow + PowerSync","description":"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.","sidebarTitle":"Overview","href":"/integrations/flutterflow/guide","hidden":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Check,CodeBlock,Frame,Heading,Note,OptimizedImage,Tip,Warning}=_components;if(!Check)_missingMdxReference(`Check`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Frame)_missingMdxReference(`Frame`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Used in conjunction with `,_jsx(_components.strong,{children:`FlutterFlow`}),`, PowerSync enables developers to build local-first apps that are robust in poor network conditions and that have highly responsive frontends while relying on Supabase for their backend. This guide walks you through configuring PowerSync within your FlutterFlow project that has Supabase integration enabled.`]}),`\n`,_jsxs(Tip,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`New and Improved integration`}),`: Welcome to our updated FlutterFlow integration guide. This version introduces a dedicated `,_jsx(_components.a,{href:`https://marketplace.flutterflow.io/item/dm1cuOwYzDv6yQL2QOFb`,children:`PowerSync FlutterFlow Library`}),`, offering a simpler and more robust solution compared to the `,_jsx(_components.a,{href:`/integrations/flutterflow/legacy-guide`,children:`previous version`}),` which required extensive custom code.`]}),_jsx(_components.p,{children:`Key improvements are:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Uses the new `,_jsx(_components.a,{href:`https://marketplace.flutterflow.io/item/dm1cuOwYzDv6yQL2QOFb`,children:`PowerSync FlutterFlow Library`})]}),`\n`,_jsx(_components.li,{children:`Supports Web-based test mode`}),`\n`,_jsx(_components.li,{children:`Streamlined Setup`}),`\n`,_jsx(_components.li,{children:`No more dozens of custom actions`}),`\n`,_jsxs(_components.li,{children:[`Working Attachments package - learn how to sync attachments `,_jsx(_components.a,{href:`/integrations/flutterflow/attachments`,children:`here`}),`.`]}),`\n`]}),_jsxs(_components.p,{children:[`Note that using libraries in FlutterFlow requires being on a `,_jsx(_components.a,{href:`https://www.flutterflow.io/pricing`,children:`paid plan with FlutterFlow`}),`. If this is not an option for you, you can use our `,_jsx(_components.a,{href:`/integrations/flutterflow/legacy-guide`,children:`legacy guide`}),` with custom code to integrate PowerSync in your FlutterFlow project.`]})]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`This guide uses `,_jsx(_components.strong,{children:`Supabase`}),` as the backend source database provider for its seamless integration with PowerSync. However, you can integrate a different backend using custom actions. For more information, refer to the `,_jsx(_components.a,{href:`#custom-backend-connectors`,children:`Custom backend connectors`}),` section.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`guide-overview`,children:`Guide Overview`}),`\n`,_jsxs(Note,{children:[_jsx(_components.p,{children:`Before starting this guide, you’ll need:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A PowerSync account (`,_jsx(_components.a,{href:`https://accounts.powersync.com/portal/powersync-signup?s=docs`,children:`sign up here`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`A Supabase account (`,_jsx(_components.a,{href:`https://supabase.com/dashboard/sign-up`,children:`sign up here`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`A `,_jsx(_components.a,{href:`https://www.flutterflow.io/pricing`,children:`paid plan`}),` with FlutterFlow for the ability to import a Library into a project.`]}),`\n`]})]}),`\n`,_jsx(_components.p,{children:`This guide walks you through building a basic item management app from scratch and takes about 30-40 minutes to complete. You should then be able to use this knowledge to build and extend your own app.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Configure Supabase and PowerSync Prerequisites`}),`\n`,_jsx(_components.li,{children:`Initialize Your FlutterFlow Project`}),`\n`,_jsx(_components.li,{children:`Build a Sign-in Screen`}),`\n`,_jsx(_components.li,{children:`Read Data`}),`\n`,_jsx(_components.li,{children:`Create Data`}),`\n`,_jsx(_components.li,{children:`Update Data (Guide coming soon)`}),`\n`,_jsx(_components.li,{children:`Delete Data`}),`\n`,_jsx(_components.li,{children:`Sign Out`}),`\n`,_jsx(_components.li,{children:`(New) Display Connectivity and Sync Status`}),`\n`,_jsx(_components.li,{children:`Secure Your App`}),`\n`,_jsx(_components.li,{children:`Enable RLS in Supabase`}),`\n`,_jsx(_components.li,{children:`Update Sync Rules in PowerSync`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`configure-supabase`,children:`Configure Supabase`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Create a new project in Supabase.`}),`\n`,_jsxs(_components.li,{children:[`To set up the Postgres database for our demo app, we will create a `,_jsx(_components.code,{children:`lists`}),` table. The demo app will have access to this table even while offline. Run the below SQL statement in your `,_jsx(_components.strong,{children:`Supabase SQL Editor`}),`:`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`sql`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`sql`,children:_jsxs(_components.code,{language:`sql`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`create`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` table`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`public`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`lists`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` id uuid `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`not null`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` default`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` gen_random_uuid (),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` created_at `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`timestamp with time zone`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` not null`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` default`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` now`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` name`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` text`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` not null`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` owner_id uuid `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`not null`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` constraint`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` lists_pkey `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`primary key`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (id),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` constraint`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` lists_owner_id_fkey `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`foreign key`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (owner_id) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`references`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` auth`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`users`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (id) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`on delete cascade`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) tablespace pg_default`})}),`\n`]})})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`PowerSync uses the Postgres `,_jsx(_components.a,{href:`https://www.postgresql.org/docs/current/wal-intro.html`,children:`Write Ahead Log (WAL)`}),` to replicate data changes in order to keep PowerSync SDK clients up to date. Run the below SQL statement in your `,_jsx(_components.strong,{children:`Supabase SQL Editor`}),` to create a Postgres role/user with replication privileges:`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`sql`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`sql`,children:_jsxs(_components.code,{language:`sql`,numberOfLines:`8`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`-- Create a role/user with replication privileges for PowerSync`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`CREATE`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` ROLE`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` powersync_role `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`WITH`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` REPLICATION BYPASSRLS `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`LOGIN`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` PASSWORD`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'myhighlyrandompassword'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`-- Set up permissions for the newly created role`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`-- Read-only (SELECT) access is required`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`GRANT`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` SELECT`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` ON`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ALL TABLES `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`IN`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` SCHEMA`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` public `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`TO`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` powersync_role; `})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`-- Optionally, grant SELECT on all future tables (to cater for schema additions)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`ALTER`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` DEFAULT`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` PRIVILEGES `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`IN`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` SCHEMA`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` public `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`GRANT`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` SELECT`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` ON`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` TABLES `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`TO`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` powersync_role; `})]}),`\n`]})})}),`\n`,`To restrict read access to specific tables, explicitly list allowed tables for both the `,_jsx(_components.code,{children:`SELECT`}),` privilege, and for the publication mentioned in the next step (as well as for any other publications that may exist).`]}),`\n`,_jsxs(_components.li,{children:[`Create a Postgres publication using the SQL Editor. This will enable data to be replicated from Supabase so that your FlutterFlow app can download it.`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`sql`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`sql`,children:_jsxs(_components.code,{language:`sql`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`-- Create a publication to replicate tables. The publication must be named \"powersync\"`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`CREATE`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` PUBLICATION powersync `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`FOR`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ALL TABLES;`})]}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Note that the PowerSync Service has to read all updates present in the publication, regardless of whether the table is referenced in your Sync Streams. This can cause large spikes in memory usage or introduce replication delays, so if you’re dealing with large data volumes, you’ll want to specify a comma-separated subset of tables to replicate instead of `,_jsx(_components.code,{children:`FOR ALL TABLES`}),`.`]})}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`The snippet above replicates all tables and is the simplest way to get started in a dev environment.`})}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`configure-powersync`,children:`Configure PowerSync`}),`\n`,_jsx(Heading,{level:`3`,id:`create-a-powersync-cloud-instance`,children:`Create a PowerSync Cloud Instance`}),`\n`,_jsxs(_components.p,{children:[`When creating a project in the `,_jsx(_components.a,{href:`https://dashboard.powersync.com/`,children:`PowerSync Dashboard`}),`, `,_jsx(_components.em,{children:`Development`}),` and `,_jsx(_components.em,{children:`Production`}),` instances of the PowerSync Service will be created by default. Select the instance you want to configure.`]}),`\n`,_jsx(_components.p,{children:`If you need to create a new instance, follow the steps below.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the dashboard, select your project and open the instance selection dropdown. Click `,_jsx(_components.strong,{children:`Add Instance`}),`.`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=de9f14ebfe66bd261f3cefbd883ed5c7`,\"data-og-width\":`737`,width:`737`,\"data-og-height\":`167`,height:`167`,\"data-path\":`images/usage/tools/dashboard-add-instance.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?w=280\u0026fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=5260e2a8669791853f3e4d8f42baca09 280w, https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?w=560\u0026fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=92b76f32a4f81c7d63b1727623af2a2d 560w, https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?w=840\u0026fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=effb48d78816773c39963aa706309fc4 840w, https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?w=1100\u0026fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=d6ab6ce4a78593266f5165967d4f7b93 1100w, https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?w=1650\u0026fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=924b810bbf82c32948bdf127f2921b34 1650w, https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?w=2500\u0026fit=max\u0026auto=format\u0026n=m6fGEiJuEsLbVG1i\u0026q=85\u0026s=b4416cbb9442ebdf7a87bea185e86871 2500w`})}),`\n`,_jsxs(_components.ol,{start:`2`,children:[`\n`,_jsx(_components.li,{children:`Give your instance a name, such as “Production”.`}),`\n`,_jsxs(_components.li,{children:[`[Optional] You can change the default cloud region. You can’t change the region after you create the instance. See `,_jsx(_components.a,{href:`/configuration/powersync-service/cloud-instances#regions`,children:`Regions`}),` for details.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Create Instance`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`connect-powersync-to-your-supabase`,children:`Connect PowerSync to Your Supabase`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In your Supabase Dashboard, click `,_jsx(_components.strong,{children:`Connect`}),` in the top navigation bar, or open `,_jsx(_components.a,{href:`https://supabase.com/dashboard/project/_?showConnect=true\u0026connectTab=direct`,children:`this link`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Direct`}),`, keep `,_jsx(_components.strong,{children:`Direct connection`}),` as the connection method, and copy the connection string, including the `,_jsx(_components.code,{children:`[YOUR-PASSWORD]`}),` placeholder.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.a,{href:`https://dashboard.powersync.com/`,children:`PowerSync Dashboard`}),`, select your project and instance and go to the `,_jsx(_components.strong,{children:`Database Connection`}),` view.`]}),`\n`,_jsxs(_components.li,{children:[`Select the `,_jsx(_components.strong,{children:`Postgres`}),` tab.`]}),`\n`,_jsxs(_components.li,{children:[`Paste the connection string into the `,_jsx(_components.strong,{children:`URI`}),` field. PowerSync fills in the other connection fields from the URI.`]}),`\n`,_jsxs(_components.li,{children:[`Change `,_jsx(_components.strong,{children:`Username`}),` and `,_jsx(_components.strong,{children:`Password`}),` to the `,_jsx(_components.code,{children:`powersync_role`}),` and password you created when you set up Supabase for PowerSync. See `,_jsx(_components.a,{href:`/configuration/source-db/setup#supabase`,children:`Source Database Setup`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Keep `,_jsx(_components.strong,{children:`SSL Mode`}),` set to `,_jsx(_components.code,{children:`verify-full`}),`. PowerSync trusts Supabase’s certificate by default, so you don’t need to add a server certificate.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Test Connection`}),` and fix any errors.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Save Connection`}),`.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`PowerSync now creates an isolated cloud environment for your instance. This typically takes a minute or two.`}),`\n`,_jsx(Heading,{level:`3`,id:`enable-supabase-auth`,children:`Enable Supabase Auth`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the PowerSync Dashboard, go to the `,_jsx(_components.strong,{children:`Client Auth`}),` view.`]}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Use Supabase Auth`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`If your Supabase project uses legacy JWT secrets, copy the JWT secret from your project’s `,_jsx(_components.a,{href:`https://supabase.com/dashboard/project/_/settings/jwt`,children:`JWT Keys`}),` settings into `,_jsx(_components.strong,{children:`Supabase JWT Secret (optional)`}),`. If your project uses JWT signing keys, leave this field empty. PowerSync configures your project’s signing keys automatically.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Save and Deploy`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`configure-sync-rules`,children:`Configure Sync Rules`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/sync/rules/overview`,children:`Sync Rules`}),` allow developers to control which data gets synced to which user devices using a SQL-like syntax in a YAML file. For the demo app, we’re going to specify that each user can only see their own lists.`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.a,{href:`https://dashboard.powersync.com/`,children:`PowerSync Dashboard`}),`, select your project and instance and go to the `,_jsx(_components.strong,{children:`Sync Rules`}),` view.`]}),`\n`,_jsxs(_components.li,{children:[`Edit the Sync Rules in the editor and replace the contents with the below:`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# This will sync the entire table to all users - we will refine this later`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`bucket_definitions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` global`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` data`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`SELECT * FROM lists`})]}),`\n`]})})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`“Validate”`}),` and ensure there are no errors. This validates your Sync Rules against your Postgres database.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`“Deploy”`}),` to deploy your Sync Rules.`]}),`\n`,_jsx(_components.li,{children:`Confirm in the dialog and wait a couple of minutes for the deployment to complete.`}),`\n`]}),`\n`,_jsx(Tip,{children:_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`For additional information on PowerSync’s Sync Rules, refer to the `,_jsx(_components.a,{href:`/sync/rules/overview`,children:`Sync Rules`}),` documentation.`]}),`\n`,_jsxs(_components.li,{children:[`If you’re wondering how Sync Rules relate to Supabase Postgres `,_jsx(_components.a,{href:`https://supabase.com/docs/guides/auth/row-level-security`,children:`RLS`}),`, see `,_jsx(_components.a,{href:`/integrations/supabase/rls-and-sync-streams`,children:`this subsection`}),`.`]}),`\n`]})}),`\n`,_jsx(Heading,{level:`2`,id:`initialize-your-flutterflow-project`,children:`Initialize Your FlutterFlow Project`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Create a new Blank project in FlutterFlow.`}),`\n`,_jsxs(_components.li,{children:[`Under `,_jsx(_components.strong,{children:`“App Settings” -> “Integrations”`}),`, enable “Supabase”.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Enter your Supabase “API URL” and public “Anon Key”. You can find these under `,_jsxs(_components.strong,{children:[`“Project Settings” -> “API Keys” -> `,_jsx(_components.code,{children:`anon`}),` `,_jsx(_components.code,{children:`public`})]}),` in your Supabase dashboard.`]}),`\n`,_jsx(_components.li,{children:`Click “Get Schema”.`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Add the `,_jsx(_components.a,{href:`https://marketplace.flutterflow.io/item/dm1cuOwYzDv6yQL2QOFb`,children:`PowerSync Library`}),` to your FlutterFlow account.`]}),`\n`,_jsxs(_components.li,{children:[`Under `,_jsx(_components.strong,{children:`“App Settings” -> “Project Dependencies” -> “FlutterFlow Libraries”`}),` click “Add Library”.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Select the “PowerSync” library.`}),`\n`,_jsxs(_components.li,{children:[`Add your schema:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.a,{href:`https://dashboard.powersync.com/`,children:`PowerSync Dashboard`}),`, select your project and instance and click the `,_jsx(_components.strong,{children:`Connect`}),` button in the top bar to generate the client-side schema based on your Sync Rules. Select “FlutterFlow” as the language.`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=68bd6decfff697dc43d1cdd8aecbc467`,\"data-og-width\":`300`,width:`300`,\"data-og-height\":`283`,height:`283`,\"data-path\":`images/integration-31.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?w=280\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=ce9745775ddd1397f536e0309af2ad2c 280w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?w=560\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=e9b9b1ea99c6558a8692b6b9543515e2 560w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?w=840\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=c03aa2ebd075d630c788888023f5435f 840w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=798a871363a9ee77090282886f6631da 1100w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=8e090c9753c6f499e024450b5857557c 1650w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-31.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=2da752c9bf0035cbb70cbeeedcb5a191 2500w`})}),`\n`,_jsxs(_components.ol,{start:`2`,children:[`\n`,_jsx(_components.li,{children:`Copy and paste the generated schema into the “PowerSyncSchema” field.`}),`\n`]}),`\n`]}),`\n`,_jsx(_components.li,{children:`Copy and paste your PowerSync instance URL into the “PowerSyncUrl” field.`}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=ba9436a133d3e4a6e449cef27d48009c`,\"data-og-width\":`1544`,width:`1544`,\"data-og-height\":`1246`,height:`1246`,\"data-path\":`images/integration-guides/flutterflow/powersync-library-config.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=917bfdce3facbc646ad028113ae1fc44 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=01987cbd34d778c577627644530ddd31 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=c9ace8428e1dc50fa4b1249a3a70d640 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=bb3989b722a37f6ef1156dee6e9dd0b5 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e36ad160e0c18c44e9c973ea8800c599 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-library-config.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=91e6b51010fb25ea10c3c4250f23f1af 2500w`})}),`\n`,_jsxs(_components.ol,{start:`4`,children:[`\n`,_jsx(_components.li,{children:`Note: The default path for the “HomePage” field under “Library Pages” can be left as is and ignored. FlutterFlow does not currently provide a way to remove it.`}),`\n`,_jsx(_components.li,{children:`Close the library config.`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Under `,_jsx(_components.strong,{children:`“Custom Pub Dependencies”`}),`, add a dependency on `,_jsx(_components.code,{children:`powersync_core:1.3.0`}),`:`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=ec27590ee013aa4f3bbc62513ac57236`,\"data-og-width\":`1624`,width:`1624`,\"data-og-height\":`662`,height:`662`,\"data-path\":`images/integration-guides/flutterflow/powersync-core.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d9b4c4a87509b6606071ad7519c4165f 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2ef923f8d7acdae69a2c8427edb8843b 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2d8adf9b452ba5b2490e44e79543a8a6 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=fc25a89efb718deab6a55c9dc78c271e 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3676c1e0180e20fc7bebe2311cdcc4d7 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-core.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=93b9dabcc62acff28db4ab7d94ea25e5 2500w`})}),`\n`,_jsxs(_components.p,{children:[`This version of `,_jsx(_components.code,{children:`powersync_core`}),` is required for running FlutterFlow on Web.`]}),`\n`,_jsx(Heading,{level:`2`,id:`build-a-sign-in-screen`,children:`Build A Sign-In Screen`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, click `,_jsx(_components.strong,{children:`“Add Page, Component, or Flow”`}),`.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=523b53c80cea6ed70b568bf664cf966c`,\"data-og-width\":`800`,width:`800`,\"data-og-height\":`347`,height:`347`,\"data-path\":`images/integration-25.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=280\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=322d0204d894c6eb1c63a511b3c48280 280w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=560\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=6898104d3147de2728958e2ad1c38549 560w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=840\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=32928459c52413a4cc8728d743a5f11a 840w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=7592a4941655ea082569bfa87379d01a 1100w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=ccd8f8814984d7815a2b20cb0519b5e6 1650w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=9b6eea60b7ebcdff9c0abde43e0a27d4 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Select the “Auth 1” template and name the page `,_jsx(_components.code,{children:`Login`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Delete the `,_jsx(_components.em,{children:`Sign Up`}),`, `,_jsx(_components.em,{children:`Forgot Password`}),` and `,_jsx(_components.em,{children:`Social Login`}),` buttons — we will only be supporting Sign In for this demo app.`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=d05bdfbeb5aa0c505a1a3f6f72ec16b8`,\"data-og-width\":`300`,width:`300`,\"data-og-height\":`378`,height:`378`,\"data-path\":`images/integration-26.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?w=280\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=df0182907b9512aca3c8ee48afae0cd6 280w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?w=560\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=0ec549655680e28d3e5a629fd1e59b94 560w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?w=840\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=2f1a158de7c64f5ad86685a14f12b8b0 840w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=82d56afb6ff4fb9ef91a333b56f038f4 1100w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=0bee75a4a7bf90503eab95fabcb7f91b 1650w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-26.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=5a26e8a29811bba6ab0827ff66ec741d 2500w`})}),`\n`,_jsxs(_components.ol,{start:`4`,children:[`\n`,_jsxs(_components.li,{children:[`Under `,_jsx(_components.strong,{children:`“App Settings” -> “App Settings” -> “Authentication”`}),`:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Enable Authentication.`}),`\n`,_jsx(_components.li,{children:`Set “Authentication Type” to “Supabase”.`}),`\n`,_jsxs(_components.li,{children:[`Set “Entry Page” to the `,_jsx(_components.code,{children:`Login`}),` page you just created.`]}),`\n`,_jsx(_components.li,{children:`Set “Logged In Page” to “HomePage”.`}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=04f48dd8f4ec1ca5b1dd21711156a088`,\"data-og-width\":`800`,width:`800`,\"data-og-height\":`538`,height:`538`,\"data-path\":`images/integration-27.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?w=280\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=3dfa8c46aca6ed24635b0877e21ae13b 280w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?w=560\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=64510eb3e13637e970b753fb5bc2881b 560w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?w=840\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=32ad87be1ac4a4dcdacc50e1fa829494 840w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=30128d4ff1b71de7e29bf3b7d3008c1a 1100w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=53fc1eb16acfe0896189b32cb723ed31 1650w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-27.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=c567c0e1b92aaf25a6021ae389e24637 2500w`})}),`\n`,_jsxs(_components.ol,{start:`5`,children:[`\n`,_jsxs(_components.li,{children:[`In your Supabase Dashboard, under `,_jsx(_components.strong,{children:`“Authentication”`}),`, click on `,_jsx(_components.strong,{children:`“Add User” -> “Create new user”`}),` and create a user for yourself to test with:`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=0a530c4e54dbdb49bfb6a09f4e6fb0de`,width:`60%`,\"data-og-width\":`776`,\"data-og-height\":`738`,\"data-path\":`images/integration-28.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?w=280\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=a7fd94e94b9bde3aa0779d46a5220d85 280w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?w=560\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=3c82dd63a6d96e57fed70c6d63542cc5 560w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?w=840\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=2a8bd95dccd7b32cf9d78d95f53bb293 840w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?w=1100\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=0c4875fbf376c863a49adce77107374c 1100w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?w=1650\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=e2e2caf5e21084caf6809791302f15e0 1650w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-28.png?w=2500\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=9e2c0943ec7892c46b22280886073ac7 2500w`})}),`\n`,_jsxs(_components.ol,{start:`6`,children:[`\n`,_jsx(_components.li,{children:`Test your app with test mode:`}),`\n`]}),`\n`,_jsx(Frame,{caption:`Click on 'Test'`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2ad969541f135cc644f82b0a876111d5`,\"data-og-width\":`1078`,width:`1078`,\"data-og-height\":`852`,height:`852`,\"data-path\":`images/integration-guides/flutterflow/test-run.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=f0488f26690942f635152d9da3b2a216 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=850a8f9ee3a32e9d539b204ffeb30c44 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=8b8f520093f3dcdb86972cc7cc4e5dce 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e67d357a50f6a9420b7968742c73b054 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=976a30ff666d566a88849cf8df6f9cc6 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/test-run.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d414e0f80883401d7253a5805a06b0f3 2500w`})}),`\n`,_jsxs(Check,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` You should now be able to log into the app using the Supabase user account you just created. After logging in you should see a blank screen.`]}),_jsx(Frame,{caption:`For once, a blank screen means success!`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=83a80ffbccaa4425e6f5962f2668ae1e`,width:`30%`,\"data-og-width\":`800`,\"data-og-height\":`1733`,\"data-path\":`images/integration-30.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?w=280\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=8ef3e7f99004bf386e6810fdd44fc7e4 280w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?w=560\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=3baad195abc475e2e8cc4e49c0ed976c 560w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?w=840\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=9d786d5dd057450f311fb3043dcae6f0 840w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=146f7b80e8fefd8bf845c3aacc1d1227 1100w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=a990ab3973e3ab71d29bdc24d1b202ae 1650w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-30.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=f215ee51b9e5da1d9ab73c111adb0a24 2500w`})})]}),`\n`,_jsx(Heading,{level:`2`,id:`read-data`,children:`Read Data`}),`\n`,_jsx(_components.p,{children:`We will now create our first UI and bind it to the data in the local SQLite database on the device.`}),`\n`,_jsx(_components.p,{children:`There are three ways to read data from the SQLite database using PowerSync’s FlutterFlow library:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Auto-updating queries for Layout Elements with Dynamic Children e.g. the ListView Element`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`This uses the library’s `,_jsx(_components.code,{children:`PowerSyncQuery`}),` component.`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Auto-updating queries for basic Layout Elements e.g. Text Elements.`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`This uses the library’s `,_jsx(_components.code,{children:`PowerSyncStateUpdater`}),` component.`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Once-off reads for static data.`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`This uses the library’s `,_jsx(_components.code,{children:`PowerSyncQueryOnce`}),` custom action.`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`prepare-supabase-tables-for-reads`,children:`Prepare Supabase Tables for Reads`}),`\n`,_jsx(_components.p,{children:`For reading data in FlutterFlow, you need a Custom Function per Supabase table to map Supabase rows to data that can be used by the library. This is because FlutterFlow Libraries do not support Supabase classes.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Navigate to `,_jsx(_components.strong,{children:`“Custom Code”`}),` and add a Custom Function.`]}),`\n`,_jsxs(_components.li,{children:[`Name the function `,_jsx(_components.code,{children:`supabaseRowsToList`}),` (if your Supabase table name is “Customers”, you would name this `,_jsx(_components.code,{children:`supabaseRowsToCustomers`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`Under `,_jsx(_components.strong,{children:`Function Settings`}),` on the right, set the “Return Value” to `,_jsx(_components.code,{children:`Supabase Row`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Check “Is List”.`}),`\n`,_jsx(_components.li,{children:`Uncheck “Nullable”.`}),`\n`,_jsxs(_components.li,{children:[`Under “Table Name”, select `,_jsx(_components.code,{children:`lists`}),`.`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Also under Function Settings, click “Add Arguments”.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Set its “Name” to `,_jsx(_components.code,{children:`supabaseRows`})]}),`\n`,_jsx(_components.li,{children:`Set its “Type” to “JSON”.`}),`\n`,_jsx(_components.li,{children:`Check “Is List”.`}),`\n`,_jsx(_components.li,{children:`Uncheck “Nullable”.`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`In the Function Code, paste the following code:`,`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`dart`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`dart`,children:_jsxs(_components.code,{language:`dart`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/// MODIFY CODE ONLY BELOW THIS LINE`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` supabaseRows.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`map`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`((r) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=>`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` ListsRow`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(r)).`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`toList`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`]})})}),`\n`]}),`\n`,_jsx(_components.li,{children:`Click “Save Function”.`}),`\n`]}),`\n`,_jsx(Frame,{caption:`Custom function to map the lists table from Supabase`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d7b5091f7a6b52e7dafbe04ede6e9413`,\"data-og-width\":`2842`,width:`2842`,\"data-og-height\":`1360`,height:`1360`,\"data-path\":`images/integration-guides/flutterflow/supabase-rows-custom-function.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=1624c5e6cfb6b18fb7dc96f255d43060 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=28fcad4f4cf7d2ceb20408672ab4b813 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=90214c13405d7131a372ae5dd7244eb0 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=c8d9d5c4d03c2b59efe0cb39053d7738 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=f180e51d6eb822b4582ac104e057a6d9 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/supabase-rows-custom-function.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e1ace86dfc9e9de5f83366ba29d1ed17 2500w`})}),`\n`,_jsx(Heading,{level:`3`,id:`1-auto-updating-queries-for-layout-elements-with-dynamic-children`,children:`1. Auto-Updating Queries for Layout Elements with Dynamic Children`}),`\n`,_jsx(Heading,{level:`4`,id:`create-a-component-to-display-list-items`,children:`Create a Component to Display List Items`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, click `,_jsx(_components.strong,{children:`“Add Page, Component, or Flow”`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Select the `,_jsx(_components.strong,{children:`“New Component”`}),` tab.`]}),`\n`,_jsxs(_components.li,{children:[`Select “Create Blank” and call the component `,_jsx(_components.code,{children:`ListItems`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Palette”`}),`, drag a “ListView” widget into the `,_jsx(_components.code,{children:`ListItems`}),` component.`]}),`\n`,_jsxs(_components.li,{children:[`Still under the `,_jsx(_components.strong,{children:`“Widget Palette”`}),`, drag a “ListTile” into the `,_jsx(_components.code,{children:`ListView`}),` widget.`,`\n`,_jsx(Frame,{caption:`The ListItems component should now look like this`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=1e3734d45f8ca90702384effa77af129`,\"data-og-width\":`1492`,width:`1492`,\"data-og-height\":`772`,height:`772`,\"data-path\":`images/integration-guides/flutterflow/listitems-component.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=a1b064a60f6c95bbf7365bbf28baa991 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3e6256e971226a3b0453bf9a90600c14 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=533ca127810b8ca773f13987eb2978b2 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9e3e6e8ee39faa690bb2dcb0e76a00ad 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=b6be1b7a92f10935bec291016e705d71 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=7ee72582da85bb7a44b09afbc69fa283 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the `,_jsx(_components.code,{children:`ListItems`}),` component.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`At the top right under “Component Parameters” click “Add Parameters”.`}),`\n`,_jsx(_components.li,{children:`Click “Add Parameter”.`}),`\n`,_jsxs(_components.li,{children:[`Set its “Name” to `,_jsx(_components.code,{children:`lists`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Set its “Type” to `,_jsx(_components.code,{children:`Supabase Row`}),`.`]}),`\n`,_jsx(_components.li,{children:`Check “Is List”.`}),`\n`,_jsxs(_components.li,{children:[`Under “Table Name”, select `,_jsx(_components.code,{children:`lists`}),`.`]}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Still under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the “ListView” widget.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Select the `,_jsx(_components.strong,{children:`“Generate Dynamic Children”`}),` panel on the right.`]}),`\n`,_jsxs(_components.li,{children:[`Set the “Variable Name” to `,_jsx(_components.code,{children:`listItem`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Set the “Value” to the component parameter created in the previous step (`,_jsx(_components.code,{children:`lists`}),`).`]}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`,_jsx(_components.li,{children:`Click “Save”.`}),`\n`,_jsx(_components.li,{children:`Click “Ok” when being prompted about the widget generating its children dynamically.`}),`\n`]}),`\n`,_jsx(Frame,{caption:`The ListItems component should now look like this`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=f431c7e2651212a6281cae81f9bb9b59`,\"data-og-width\":`1136`,width:`1136`,\"data-og-height\":`748`,height:`748`,\"data-path\":`images/integration-guides/flutterflow/listitems-component-children.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=6114335ca035200e4c3b8e56b2463fb1 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9c7cde353387c1b0fd71a0d072d77fe1 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e15f1ae14b4e7530cba97ac41f78c2b6 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=543627068bfee919d073ac4a520b2d34 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=25b512b6017c8827c6953315befe07ad 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-children.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0a29199b6ab975ada64d467ff8be5a63 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Still under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the `,_jsx(_components.code,{children:`ListTile`}),` widget.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, under “Title”, click on the settings icon next to “Text”.`]}),`\n`,_jsx(_components.li,{children:`Set as “listItem Item”.`}),`\n`,_jsx(_components.li,{children:`Under “Available Options”, select “Get Row Field”.`}),`\n`,_jsx(_components.li,{children:`Under “Supabase Row Fields”, select “name”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`,_jsx(Frame,{caption:`Set the list item title text`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=bad1095e13e4de74992339a85066c043`,\"data-og-width\":`1306`,width:`1306`,\"data-og-height\":`1010`,height:`1010`,\"data-path\":`images/integration-guides/flutterflow/list-item-title-text.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=53fd41211a1ea079849a332e4a2eecbe 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=c4b8291f0516af44a440d722bf6f8404 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=711d9f70ecd78c589c777e0af693e1ea 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0b4dc2d740e046849ff1575b59553330 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=906de882bc5a57b895762f9434709d73 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/list-item-title-text.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=4d32fe0c05100b9034b0fc4e8e5c796c 2500w`})}),`\n`]}),`\n`,_jsx(_components.li,{children:`Repeat Step 8 above for the “Subtitle”, setting it to “created_at”.`}),`\n`]}),`\n`,_jsx(Frame,{caption:`The ListItems component should now look like this`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=06f8dec1d82ef768f316d47ed3841a42`,\"data-og-width\":`1270`,width:`1270`,\"data-og-height\":`770`,height:`770`,\"data-path\":`images/integration-guides/flutterflow/listitems-component-titles.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=256cbd678a7a5d461cf6cbe9fdfe3d71 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=cd023b6fd5e589d9e1206d19647d57bb 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=7beea57b8a03adf2458edb43cd7d4a4e 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2d1f36f67d86ab3d8f59b833fabf2477 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e4ddd84ffa26a50c91641717408254e9 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/listitems-component-titles.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=a372c96ed56002abe8036a758fa1015d 2500w`})}),`\n`,_jsx(Heading,{level:`4`,id:`display-the-list-component-and-populate-it-with-data`,children:`Display the List Component and Populate it with Data`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, select your `,_jsx(_components.code,{children:`HomePage`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Palette”`}),`, select the “Components and custom widgets imported from library projects” panel.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e33767033bf7a9a992a7bb6c563fc281`,\"data-og-width\":`1076`,width:`1076`,\"data-og-height\":`518`,height:`518`,\"data-path\":`images/integration-guides/flutterflow/powersync-components.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9d23f8f4bdf1bc5909c234fb6960b6ea 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0c1ebcd2f59716a3f5a64dc4f29932b5 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=b03b3be20c5a07eb6709900cb68a7ab4 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=87e795da2749170cb0c42c5479f3ee5d 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d43cee46cb975dc535afbb7367d06eb1 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3efa9c359f9d735d41ee051981244af7 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Drag the `,_jsx(_components.code,{children:`PowerSyncQuery`}),` library component into your page.`]}),`\n`,_jsxs(_components.li,{children:[`In the Properties panel on the right, under `,_jsx(_components.strong,{children:`“Component Parameters” -> “child”`}),`:`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=4d7202846313f514ef4732abb6fd6713`,\"data-og-width\":`1858`,width:`1858`,\"data-og-height\":`992`,height:`992`,\"data-path\":`images/integration-guides/flutterflow/component-parameters-child.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?w=280\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=b58b0bd2e8eef36525bf2e1f83218fca 280w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?w=560\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=d7e938768f56547ee7d268a5b322c806 560w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?w=840\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=cff282f84668744d2d90f015eb58dcb8 840w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?w=1100\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=a8d227bd9e446c2a54d58a46bb6b12d6 1100w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?w=1650\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=ec68922e5211a326fbc874177bddb75b 1650w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/component-parameters-child.png?w=2500\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=01e0bc2b9ba998944f461729354cae3c 2500w`})}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Click on “Unknown”.`}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.code,{children:`ListItems`}),` we previously created.`]}),`\n`,_jsxs(_components.li,{children:[`Click on `,_jsx(_components.code,{children:`lists`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Set the “Value” to “Custom Functions” -> `,_jsx(_components.code,{children:`supabaseRowsToList`}),` we created previously.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.code,{children:`supabaseRows`}),` argument, set the “Value” to “Widget Builder Parameters” -> `,_jsx(_components.code,{children:`rows`}),`.`]}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Still under “Component Parameters” add the SQL query to fetch all list items from the SQLite database:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Paste the following into the “sql [String]” field: `,_jsx(_components.code,{children:`select * from lists order by created_at;`})]}),`\n`,_jsx(_components.li,{children:`For this query there are no parameters - this will be covered further down in the guide.`}),`\n`]}),`\n`]}),`\n`,_jsx(_components.li,{children:`Still under “Component Parameters”, check “watch [Boolean]”. This ensures that the query auto-updates.`}),`\n`]}),`\n`,_jsx(Heading,{level:`4`,id:`test-your-app`,children:`Test Your App`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Check that there are no project issues or errors.`}),`\n`,_jsx(_components.li,{children:`Reload your app or start another test session.`}),`\n`,_jsxs(_components.li,{children:[`Notice that your homepage is still blank. This is because the `,_jsx(_components.code,{children:`lists`}),` table is empty in Supabase. Create a test row in the table by clicking on “Insert” -> “Insert Row” in your Supabase Table Editor.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Leave `,_jsx(_components.code,{children:`id`}),` and `,_jsx(_components.code,{children:`created_at`}),` blank.`]}),`\n`,_jsx(_components.li,{children:`Enter a name such as “Test from Supabase”.`}),`\n`,_jsxs(_components.li,{children:[`Click “Select Record” for `,_jsx(_components.code,{children:`owner_id`}),` and select your test user.`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsxs(Check,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` You should now see your single test row magically appear in your app:`]}),_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=ed60fbc947643b77d3b17de3def3b1dd`,\"data-og-width\":`300`,width:`300`,\"data-og-height\":`201`,height:`201`,\"data-path\":`images/integration-44.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?w=280\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=c673fa95fb345971e66de9abedf33cca 280w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?w=560\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=d5629f691b584efb3d7dfb61cfbaea02 560w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?w=840\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=38990375ddfcc7a977ef0e3a69e83db5 840w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=879a6c9512acfb89e0609ab786e2724f 1100w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=5b4c8942be6c63e03f1bd5516769d731 1650w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-44.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=313ae7f476eeb1fa02bd966bc1a1c7a0 2500w`})})]}),`\n`,_jsx(Heading,{level:`3`,id:`2-auto-updating-queries-for-basic-layout-elements`,children:`2. Auto-Updating Queries for Basic Layout Elements`}),`\n`,_jsxs(_components.p,{children:[`In this section, we will be making the `,_jsx(_components.code,{children:`ListView`}),` component clickable and navigate the user to a page which will eventually display the list’s To-Do items. This page will show the selected list’s name in the title bar (“AppBar”). This uses Page State and the `,_jsx(_components.code,{children:`PowerSyncStateUpdater`}),` library component.`]}),`\n`,_jsx(Heading,{level:`4`,id:`create-a-page-parameter`,children:`Create a Page Parameter`}),`\n`,_jsx(_components.p,{children:`This parameter will store the selected list’s ID.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, click `,_jsx(_components.strong,{children:`“Add Page, Component, or Flow”`}),`.`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=523b53c80cea6ed70b568bf664cf966c`,\"data-og-width\":`800`,width:`800`,\"data-og-height\":`347`,height:`347`,\"data-path\":`images/integration-25.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=280\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=322d0204d894c6eb1c63a511b3c48280 280w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=560\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=6898104d3147de2728958e2ad1c38549 560w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=840\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=32928459c52413a4cc8728d743a5f11a 840w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=7592a4941655ea082569bfa87379d01a 1100w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=ccd8f8814984d7815a2b20cb0519b5e6 1650w, https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/integration-25.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=lquPOu2QW4XM9BQW\u0026q=85\u0026s=9b6eea60b7ebcdff9c0abde43e0a27d4 2500w`})}),`\n`,_jsxs(_components.ol,{start:`2`,children:[`\n`,_jsxs(_components.li,{children:[`Create a blank page and name it `,_jsx(_components.code,{children:`Todos`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select your `,_jsx(_components.code,{children:`Todos`}),` page.`]}),`\n`,_jsxs(_components.li,{children:[`At the top right of the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, click on the plus icon for Page Parameters.`]}),`\n`,_jsx(_components.li,{children:`Click “Add Parameter”.`}),`\n`,_jsxs(_components.li,{children:[`Set the “Parameter Name” to `,_jsx(_components.code,{children:`id`}),`.`]}),`\n`,_jsx(_components.li,{children:`Set the “Type” to “String”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`,_jsx(Heading,{level:`4`,id:`create-a-local-page-state-variable`,children:`Create a Local Page State Variable`}),`\n`,_jsx(_components.p,{children:`This variable will store the selected list row.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Still in the `,_jsx(_components.strong,{children:`“Widget Tree”`}),` with the `,_jsx(_components.code,{children:`Todos`}),` page selected:`]}),`\n`,_jsxs(_components.li,{children:[`Select the `,_jsx(_components.strong,{children:`“State Management Panel”`}),` on the right.`]}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=7153b9e1caf0298fe0bd2317dd8badff`,\"data-og-width\":`812`,width:`812`,\"data-og-height\":`534`,height:`534`,\"data-path\":`images/integration-guides/flutterflow/state-management.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=fe0f51f612073cc115c6bdb09dae66f6 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2775cb421c4a1e54b17cb9bfcea86b70 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9d1da2365862418fb1a60302f078cbaf 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=7cb1f3bd612369ed048f5b68b9f4fdbd 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=02887cbe8b35cdc182fb983b42c6e54d 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/state-management.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=47fee1497f866dc56d31fcc3a55bf776 2500w`})}),`\n`,_jsxs(_components.ol,{start:`3`,children:[`\n`,_jsx(_components.li,{children:`Click on “Add Field”.`}),`\n`,_jsxs(_components.li,{children:[`Set “Field Name” to `,_jsx(_components.code,{children:`list`}),`.`]}),`\n`,_jsx(_components.li,{children:`Set the “Type” to “Supabase Row”.`}),`\n`,_jsxs(_components.li,{children:[`Under “Table Name”, select `,_jsx(_components.code,{children:`lists`}),`.`]}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`,_jsx(Heading,{level:`4`,id:`bind-the-page-title-to-the-page-state`,children:`Bind the Page Title to the Page State`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Palette”`}),`, select the “Components and custom widgets imported from library projects” panel.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e33767033bf7a9a992a7bb6c563fc281`,\"data-og-width\":`1076`,width:`1076`,\"data-og-height\":`518`,height:`518`,\"data-path\":`images/integration-guides/flutterflow/powersync-components.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9d23f8f4bdf1bc5909c234fb6960b6ea 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0c1ebcd2f59716a3f5a64dc4f29932b5 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=b03b3be20c5a07eb6709900cb68a7ab4 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=87e795da2749170cb0c42c5479f3ee5d 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d43cee46cb975dc535afbb7367d06eb1 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3efa9c359f9d735d41ee051981244af7 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Drag the `,_jsx(_components.code,{children:`PowerSyncStateUpdater`}),` library component into your page.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the `,_jsx(_components.code,{children:`PowerSyncStateUpdater`}),` component.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, under “Component Parameters”:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Add the SQL query to fetch the selected list from the SQLite database. Paste the following into the “sql [String]” field: `,_jsx(_components.code,{children:`select * from lists where id = :id;`})]}),`\n`,_jsxs(_components.li,{children:[`Click on “parameters [Json]” select “Create Map (JSON)” as the variable.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Under “Add Map Entries”, click “Add Key Value Pair”.`}),`\n`,_jsxs(_components.li,{children:[`Set the “Key” to `,_jsx(_components.code,{children:`id`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Set the “Value” to the page parameter created previously called `,_jsx(_components.code,{children:`id`}),`.`]}),`\n`,_jsx(_components.li,{children:`Check “watch [Boolean]”. This ensures that the query auto-updates.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=82ed24d13ba12b4dce8f394e565529b0`,\"data-og-width\":`1678`,width:`1678`,\"data-og-height\":`1094`,height:`1094`,\"data-path\":`images/integration-guides/flutterflow/json-parameters.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=4220da93ec8307a25ded21f8b9a2679b 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=313e93b25fb593fc27f333fa1a34d3f9 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=99e41a59cf50cd41793019374a7aa701 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3e7b09f7bfeb70bc8b13f26eba658cc6 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=c99a64bec62fc9ec02ed74d339af404b 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/json-parameters.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2850f213d649e9a150a0f7d969229219 2500w`})}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Still under “Component Parameters”, configure the `,_jsx(_components.code,{children:`onData`}),` action:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Open the “Action Flow Editor”.`}),`\n`,_jsx(_components.li,{children:`Select the “Callback” trigger type.`}),`\n`,_jsx(_components.li,{children:`Click “Add Action”.`}),`\n`,_jsx(_components.li,{children:`Search for “update page” and select “Update Page State”.`}),`\n`,_jsx(_components.li,{children:`Click “Add Field”.`}),`\n`,_jsxs(_components.li,{children:[`Select your `,_jsx(_components.code,{children:`list`}),` page state variable.`]}),`\n`,_jsx(_components.li,{children:`Set “Select Update Type” to “Set Value”.`}),`\n`,_jsxs(_components.li,{children:[`Set “Value to set” to “Custom Functions” -> `,_jsx(_components.code,{children:`supabaseRowsToList`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Set the “Value” to “Callback Parameters” -> `,_jsx(_components.code,{children:`rows`})]}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`,_jsx(_components.li,{children:`Under “Available Options”, select “Item at Index”.`}),`\n`,_jsx(_components.li,{children:`Set “List Index Options” to “First”`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=64b0bc85e53f771385facc8b023df5c1`,\"data-og-width\":`2206`,width:`2206`,\"data-og-height\":`1490`,height:`1490`,\"data-path\":`images/integration-guides/flutterflow/update-page-state-action.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=88a1bcc18bbc28f94d42315798c1c375 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=87c2b08545a8788e9b080f1884b1541d 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0ff6a9bc3362ba783a92539439893d5d 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d8c852e8c59d842043126f7348375251 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0383ed78d2330c5e850368f4a29cd9fb 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/update-page-state-action.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=eb9acd8da36a3bb01f4f7429896c1d83 2500w`})}),`\n`,_jsxs(_components.ol,{start:`14`,children:[`\n`,_jsx(_components.li,{children:`Close the Action Flow Editor.`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Still under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the “AppBar” -> “Text” widget.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, click on settings icon next to “Text”.`]}),`\n`,_jsx(_components.li,{children:`Click on “Page State” -> “List”.`}),`\n`,_jsx(_components.li,{children:`Set “Supabase Row Fields” to “name”.`}),`\n`,_jsxs(_components.li,{children:[`(Optional) Set the “Default Variable Value” to `,_jsx(_components.code,{children:`List Name`}),`.`]}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsxs(Heading,{level:`4`,id:`make-the-listview-component-clickable`,children:[`Make the `,_jsx(_components.code,{children:`ListView`}),` Component Clickable`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, select your `,_jsx(_components.code,{children:`ListItems`}),` component.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the `,_jsx(_components.code,{children:`ListTile`}),` widget.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Actions”`}),` panel on the right, click “Add Action”. “On Tap” should be selected by default.`]}),`\n`,_jsx(_components.li,{children:`In the “Navigation” subsection, select “Navigate To”.`}),`\n`,_jsx(_components.li,{children:`Select the “Todos” page.`}),`\n`,_jsx(_components.li,{children:`Under “Parameters” click “Pass”.`}),`\n`,_jsx(_components.li,{children:`“id” should be auto-selected, click on it.`}),`\n`,_jsx(_components.li,{children:`Click on the settings icon next to “Value”`}),`\n`,_jsx(_components.li,{children:`Set it to “listItem Item”.`}),`\n`,_jsx(_components.li,{children:`Under “Available Options” select “Get Row Field”`}),`\n`,_jsx(_components.li,{children:`Under “Supabase Row Fields” select “id”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`,_jsxs(_components.li,{children:[`(Optional) Enable the back button to navigate back:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, select your `,_jsx(_components.code,{children:`Todos`}),` page.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the “AppBar” component.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, enable “Show Default Button”.`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`4`,id:`test-your-app-2`,children:`Test Your App`}),`\n`,_jsx(_components.p,{children:`Instant Reload your app or start another test session.`}),`\n`,_jsxs(Check,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` You should now be able to click on a list item and it should navigate you to a new page showing the name of the list in the title bar:`]}),_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=4a3aecb94a754b4036dd9e1c53eb14fa`,width:`60%`,\"data-og-width\":`808`,\"data-og-height\":`860`,\"data-path\":`images/integration-guides/flutterflow/todos-page-list-title.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=c873734cbde71a59ed77e3efd6d079cd 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=2ef497a35b3ac16478f5e669d4230a3c 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=209e2e2a32867167d7774ca76d434f0e 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=84ea2ea0ebb6649dfb7e45b90bedbe5b 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=1f7b6ac43e54800a715ef88cb75f68f8 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/todos-page-list-title.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=c4163e8586f6857059e1bc2a31a68d99 2500w`})})]}),`\n`,_jsx(Heading,{level:`3`,id:`3-once-off-reads-for-static-data`,children:`3. Once-Off Reads for Static Data`}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`This section is a work in progress. Please reach out on `,_jsx(_components.a,{href:`https://discord.gg/powersync`,children:`our Discord`}),` if you have any questions.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`create-data`,children:`Create Data`}),`\n`,_jsx(_components.p,{children:`You will now update the app so that we can capture new list entries.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, select your `,_jsx(_components.code,{children:`HomePage`}),` page.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Palette”`}),`, search for “float” and drag the “FAB” widget onto your page.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Actions”`}),` panel on the right, click “Add Action”.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under “Custom Action” -> “PowerSync”, select `,_jsx(_components.code,{children:`powersyncWrite`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Under the “Set Action Arguments” -> “sql” section, add the SQL query to create a new list item. For the purpose of this guide we are hardcoding the list’s name, normally you would build UI for this.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Paste the following into the “Value” field: `,_jsx(_components.code,{children:`INSERT INTO lists(id, created_at, name, owner_id) VALUES(uuid(), datetime(), 'new item', :userId);`})]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Under the “parameters” section, set the `,_jsx(_components.code,{children:`userId`}),` parameter we’re using the above query:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Click on “UNSET”.`}),`\n`,_jsx(_components.li,{children:`Select “Create Map (JSON)” as the variable.`}),`\n`,_jsx(_components.li,{children:`Under “Add Map Entries”, click “Add Key Value Pair”.`}),`\n`,_jsxs(_components.li,{children:[`Set the “Key” to `,_jsx(_components.code,{children:`userId`}),`.`]}),`\n`,_jsx(_components.li,{children:`Set the “Value” to “Authenticated User” -> “User ID”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsxs(Check,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` Reload your app and click on the + floating action button. A new list item should appear, which also automatically syncs to Supabase:`]}),_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=247f71c9779f3b2b97a379c6ad589e9d`,width:`60%`,\"data-og-width\":`836`,\"data-og-height\":`806`,\"data-path\":`images/integration-guides/flutterflow/create-new-item.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?w=280\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=167d9ab58f323efb8de21ee77cfdc75b 280w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?w=560\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=dd93cf23d4db01131e121a02f72d06e8 560w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?w=840\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=fe3708d699d51351053ce479203be2ac 840w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?w=1100\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=8c57737bd530608da19024243297c334 1100w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?w=1650\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=3d3e8622ad7aa813b0420eab4a8bfae8 1650w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-guides/flutterflow/create-new-item.png?w=2500\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=bc9a3cfe5fbd1bf1fa856d1baef1dfca 2500w`})})]}),`\n`,_jsx(Heading,{level:`2`,id:`update-data`,children:`Update Data`}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Updating data is possible today using the `,_jsx(_components.code,{children:`powersyncWrite`}),` helper of the Library, and a guide will be published soon. In the mean time, use the section below about `,_jsx(_components.a,{href:`#delete-data`,children:`Deleting Data`}),` as a reference. Please reach out on `,_jsx(_components.a,{href:`https://discord.gg/powersync`,children:`our Discord`}),` if you have any questions.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`delete-data`,children:`Delete Data`}),`\n`,_jsxs(_components.p,{children:[`In this section we will add the ability to swipe on a `,_jsx(_components.code,{children:`ListTile`}),` to delete it.`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, select your `,_jsx(_components.code,{children:`ListItems`}),` component.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Tree”`}),`, select the `,_jsx(_components.code,{children:`ListTile`}),` widget.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, enable “Slidable”.`]}),`\n`,_jsx(_components.li,{children:`Click “Open Slidable”.`}),`\n`,_jsxs(_components.li,{children:[`Select the “SlidableActionWidget”.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=670d24036486e3171af3e01e791710b7`,\"data-og-width\":`1182`,width:`1182`,\"data-og-height\":`660`,height:`660`,\"data-path\":`images/integration-guides/flutterflow/slidable-action-widget.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d71188ac3b5709cc75ae33b2701bfff1 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=4a268887f9b9088e2a332e1406c90b17 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d106457817601dd0ea4d4f16f2965dd7 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=178a1fbcc7eeac8ad1f82713185253b0 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=1c05159d2943cf4f87478fe0cee454c4 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/slidable-action-widget.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=48436887eee8339e38d4b4c4fd68ff85 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Actions”`}),` panel on the right, click “Add Action”.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under “Custom Action” -> “PowerSync”, select `,_jsx(_components.code,{children:`powersyncWrite`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Under the “Set Action Arguments” -> “sql” section, add the SQL query to delete the list item.`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Paste the following into the “Value” field: `,_jsx(_components.code,{children:`delete from lists where id = :id;`})]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Under the “parameters” section, set the `,_jsx(_components.code,{children:`id`}),` parameter we’re using the above query:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Click on “UNSET”.`}),`\n`,_jsx(_components.li,{children:`Select “Create Map (JSON)” as the variable.`}),`\n`,_jsx(_components.li,{children:`Under “Add Map Entries”, click “Add Key Value Pair”.`}),`\n`,_jsxs(_components.li,{children:[`Set the “Key” to `,_jsx(_components.code,{children:`id`}),`.`]}),`\n`,_jsx(_components.li,{children:`Set the “Value” to “listItem Item”.`}),`\n`,_jsx(_components.li,{children:`Under “Available Options” select “Get Row Field”.`}),`\n`,_jsx(_components.li,{children:`Under “Supabase Row Fields” select “id”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`,_jsx(_components.li,{children:`Click “Confirm”.`}),`\n`]}),`\n`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Check,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` Reload your app and swipe on a list item. Delete it, and note how it is deleted from the list as well as from Supabase.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`sign-out`,children:`Sign Out`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Navigate to `,_jsx(_components.strong,{children:`“Custom Code”`}),` and create a new Custom Action called `,_jsx(_components.code,{children:`signOut`}),` without Arguments or Return Values and paste the below code:`]}),`\n`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`In the below code, `,_jsx(_components.code,{children:`power_sync_b0w5r9`}),` is the project ID of the PowerSync library. Update it if it changes.`]})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`24`,language:`dart`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`dart`,children:_jsxs(_components.code,{language:`dart`,numberOfLines:`24`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Automatic FlutterFlow imports`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '/backend/supabase/supabase.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"package:power_sync_b0w5r9/backend/schema/structs/index.dart\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` power_sync_b0w5r9_data_schema;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'package:ff_theme/flutter_flow/flutter_flow_theme.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '/flutter_flow/flutter_flow_util.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '/custom_code/actions/index.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`; `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Imports other custom actions`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '/flutter_flow/custom_functions.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`; `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Imports custom functions`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'package:flutter/material.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Begin custom action code`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// DO NOT REMOVE OR MODIFY THE CODE ABOVE!`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'package:power_sync_b0w5r9/custom_code/actions/initialize_power_sync.dart'`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ps;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`Future`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` signOut`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`async`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` final`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` database `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ps.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`getOrInitializeDatabase`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` //await database.disconnectAndClear();`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // this will completely delete all the local data, use with caution as there may be items still in the upload queue`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` database`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`disconnect`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`//this will simply disconnect from the PowerSync Service and preserve all local data`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Set your action name, define your arguments and return parameter,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// and then add the boilerplate code using the green button on the right!`})}),`\n`]})})}),`\n`,_jsxs(_components.ol,{start:`2`,children:[`\n`,_jsx(_components.li,{children:`Click “Save Action”.`}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Page Selector”`}),`, select your `,_jsx(_components.code,{children:`HomePage`}),` page.`]}),`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`“Widget Palette”`}),`, drag a “Button” onto the right of your “AppBar”.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=1c649feb539729b48bedb80bfbd19a9b`,\"data-og-width\":`1210`,width:`1210`,\"data-og-height\":`738`,height:`738`,\"data-path\":`images/integration-guides/flutterflow/sign-out-button.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0399317aaabc20976d4d02d4e85d51f7 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e3ce8c196554bf32b0c2ca7b74281788 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=fae95f51c17a9783afd1e11f81fdbba4 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=71d338e7ac0ef8c9bc0721b5cfb5c8ab 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=160d086588cb8bf21217d662dc4661cd 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/sign-out-button.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3bc9458a513ae904eb2af6ccadc02f31 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`“Properties”`}),` panel on the right, rename the “Button Text” to `,_jsx(_components.code,{children:`Sign Out`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Switch to the `,_jsx(_components.strong,{children:`“Actions”`}),` panel and open the `,_jsx(_components.strong,{children:`“Action Flow Editor”`}),`.`]}),`\n`,_jsx(_components.li,{children:`Select “On Tap” as the action trigger.`}),`\n`,_jsxs(_components.li,{children:[`Click “Add Action” and add a call to the `,_jsx(_components.code,{children:`signOut`}),` Custom Action.`]}),`\n`,_jsx(_components.li,{children:`Chain another Action and call to “Supabase Authentication” -> “Log Out”:`}),`\n`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=e3a6771fedc40dcd4c61b266b6640de5`,\"data-og-width\":`800`,width:`800`,\"data-og-height\":`290`,height:`290`,\"data-path\":`images/integration-66.avif`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?w=280\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=3bbbb8bc5cdb6ca66c21b97a79b3e62b 280w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?w=560\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=bca990fb2a3b420eb09af33b2fb98b60 560w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?w=840\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=40c9bbef6ce989bda229d497b50aee88 840w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?w=1100\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=5b405b07be752647b788db430ba277de 1100w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?w=1650\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=e73c968bc2bec63e4f08f1a942ce7c8f 1650w, https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-66.avif?w=2500\u0026fit=max\u0026auto=format\u0026n=xadPobk0au2zv_hA\u0026q=85\u0026s=1ac808d608feb024646a7c913289e6a4 2500w`})}),`\n`,_jsxs(_components.ol,{start:`10`,children:[`\n`,_jsx(_components.li,{children:`Click “Close”.`}),`\n`]}),`\n`,_jsx(Check,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` You should now be able to reload your app and sign out and in again.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`optional-display-connectivity-and-sync-status`,children:`(Optional) Display Connectivity and Sync Status`}),`\n`,_jsx(_components.p,{children:`The PowerSync library provides a built-in component that displays real-time connectivity and sync status. Since the sync state is available globally as part of your app state, you can easily monitor the database status throughout your application. To add this status indicator:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Under the `,_jsx(_components.strong,{children:`Widget Palette`}),`, select the “Components and custom widgets imported from library projects” panel.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=e33767033bf7a9a992a7bb6c563fc281`,\"data-og-width\":`1076`,width:`1076`,\"data-og-height\":`518`,height:`518`,\"data-path\":`images/integration-guides/flutterflow/powersync-components.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9d23f8f4bdf1bc5909c234fb6960b6ea 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=0c1ebcd2f59716a3f5a64dc4f29932b5 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=b03b3be20c5a07eb6709900cb68a7ab4 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=87e795da2749170cb0c42c5479f3ee5d 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=d43cee46cb975dc535afbb7367d06eb1 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-components.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=3efa9c359f9d735d41ee051981244af7 2500w`})}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Drag the `,_jsx(_components.code,{children:`PowerSyncConnectivity`}),` component into your home page’s “AppBar”.`,`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9a0717915d7d3e628213940f3abe969e`,\"data-og-width\":`1130`,width:`1130`,\"data-og-height\":`686`,height:`686`,\"data-path\":`images/integration-guides/flutterflow/powersync-connectivity.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?w=280\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9ac820881ac9d8becbe7f7d6222aaa6f 280w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?w=560\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=9fb00fb07158fbe0db6d24cc00fab6ec 560w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?w=840\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=58ecee18bbf6058a38281aae634e4665 840w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?w=1100\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=1a23c38b6edb093cd7f694db01e2e3a9 1100w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?w=1650\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=8493c93ed528f4c484d8a52beac6d63b 1650w, https://mintcdn.com/powersync/uZoggfn0-9bg2k3I/images/integration-guides/flutterflow/powersync-connectivity.png?w=2500\u0026fit=max\u0026auto=format\u0026n=uZoggfn0-9bg2k3I\u0026q=85\u0026s=5c0655dc9bccea9289e57ca00cbf72b8 2500w`})}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`secure-your-app`,children:`Secure Your App`}),`\n`,_jsxs(_components.p,{children:[`PowerSync’s `,_jsx(_components.a,{href:`/sync/rules/overview`,children:`Sync Rules`}),` and Supabase’s support for `,_jsx(_components.a,{href:`https://supabase.com/docs/guides/auth/row-level-security`,children:`Row Level Security (RLS)`}),` can be used in conjunction. Here are some high level similarities and differences:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`RLS should be used as the authoritative set of security rules applied to your users’ CRUD operations that reach Postgres.`}),`\n`,_jsxs(_components.li,{children:[`Sync Rules are only applied for data that is to be downloaded to clients — they do not apply to uploaded data.`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Sync Rules can typically be considered to be complementary to RLS, and will generally mirror your RLS setup.`}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`enable-rls-in-supabase`,children:`Enable RLS in Supabase`}),`\n`,_jsxs(_components.p,{children:[`Run the below in your Supabase console to ensure that only list owners can perform actions on the lists table where `,_jsx(_components.code,{children:`owner_id`}),` matches their user id:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`sql`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`sql`,children:_jsxs(_components.code,{language:`sql`,numberOfLines:`6`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`alter`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` table`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` public`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`lists`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` enable`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` row`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` level`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` security`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`create`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` policy`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"owned lists\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` on`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` public`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`lists`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ALL `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`using`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` auth`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`uid`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` owner_id`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`update-sync-rules`,children:`Update Sync Rules`}),`\n`,_jsx(_components.p,{children:`Currently all lists are synced to all users, regardless of who the owner of the list is. You will now update this so that only a user’s lists are synced to their device:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.a,{href:`https://dashboard.powersync.com/`,children:`PowerSync Dashboard`}),`, select your project and instance and go to the `,_jsx(_components.strong,{children:`Sync Rules`}),` view.`]}),`\n`,_jsx(_components.li,{children:`Edit the Sync Rules in the editor and replace the contents with the below:`}),`\n`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`bucket_definitions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` user_lists`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` parameters`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`select request.user_id() as user_id`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` data`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`select * from lists where owner_id = bucket.user_id`})]}),`\n`]})})}),`\n`,_jsxs(_components.ol,{start:`3`,children:[`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`“Validate”`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`“Deploy”`}),` to deploy your Sync Rules.`]}),`\n`,_jsx(_components.li,{children:`Wait for the deploy to complete.`}),`\n`]}),`\n`,_jsx(Check,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Checkpoint:`}),` Your app should continue running seamlessly as before.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`arrays-json-and-other-types`,children:`Arrays, JSON and Other Types`}),`\n`,_jsx(_components.p,{children:`For column values, PowerSync supports three basic types: Integers, doubles, and strings. These types have been chosen because they’re natively supported by SQLite while also being easy to transport as JSON.`}),`\n`,_jsxs(_components.p,{children:[`Of course, you may want to store other values in your Postgres database as well. When syncing a value that doesn’t fit into the three fundamental types, PowerSync will `,_jsx(_components.a,{href:`/client-sdks/advanced/custom-types-arrays-and-json#custom-types`,children:`encode it as a JSON string`}),`. To use those values in your app, you’ll need to apply a mapping so that you display the correct values and use the correct representation when uploading data.`]}),`\n`,_jsxs(_components.p,{children:[`As an example, let’s consider an added `,_jsx(_components.code,{children:`tags`}),` column on the `,_jsx(_components.code,{children:`lists`}),` table used in this guide. These tags will be encoded as a string array in Postgres:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`sql`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`sql`,children:_jsxs(_components.code,{language:`sql`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`CREATE`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` TABLE`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` public`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.lists (`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` # ... existing columns,`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` tags `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`text`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`[] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`DEFAULT`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '{\"default\", \"tags\"}'`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Like all array values, PowerSync will transport this as a JSON string. For instance, a row with the default tags would be represented as this string: `,_jsx(_components.code,{children:`[\"default\", \"tags\"]`}),`. FlutterFlow does not support extracting a list from that string, so the `,_jsx(_components.a,{href:`#read-data`,children:`custom functions`}),` responsible for mapping SQLite rows to FlutterFlow classes needs to be aware of the transformation and reverse it:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`dart`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`dart`,children:_jsxs(_components.code,{language:`dart`,numberOfLines:`7`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/// MODIFY CODE ONLY BELOW THIS LINE`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` supabaseRows.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`map`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`((r) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` ListsRow`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ...r,`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'tags'`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` jsonDecode`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(r[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'tags'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`as`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`),`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` });`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}).`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`toList`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`This transforms the `,_jsx(_components.code,{children:`'[\"default\", \"tags\"]'`}),` value as it appears into `,_jsx(_components.code,{children:`[\"default\", \"tags\"]`}),`, the list value expected for this row.`]}),`\n`,_jsxs(_components.p,{children:[`A similar approach is necessary when making local writes. The local database should be consistent with the data synced with PowerSync. So all `,_jsx(_components.a,{href:`#create-data`,children:`local writes`}),` should write array and JSON values as strings by encoding them as JSON.`]}),`\n`,_jsxs(_components.p,{children:[`Finally, the PowerSync mapping also needs to be reverted when uploading rows to Postgres. For a `,_jsx(_components.code,{children:`text[]`}),` column for instance, the local string value would not be accepted by Supabase. For this reason, the upload behavior for columns with advanced types needs to be customized.`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`New feature:`}),` This option has been added in version `,_jsx(_components.code,{children:`0.0.7`}),` of the PowerSync FlutterFlow library. Please make sure you’re using that version or later.`]})}),`\n`,_jsxs(_components.p,{children:[`To customize the uploading behavior, create a new custom action (e.g. `,_jsx(_components.code,{children:`applyPowerSyncOptions`}),`). After the default imports, put this snippet:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`dart`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`dart`,children:_jsxs(_components.code,{language:`dart`,numberOfLines:`11`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'package:power_sync_b0w5r9/custom_code/actions/initialize_power_sync.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`Future`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` applyPowerSyncOptions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`async`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Add your function code here!`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` powerSyncOptions.transformData `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (table, data) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` switch`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (table) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` case`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'lists'`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'tags'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` jsonDecode`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(data[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'tags'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`as`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` };`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Also, add this function to your `,_jsx(_components.code,{children:`main.dart`}),` as a final action.`]}),`\n`,_jsxs(_components.p,{children:[`When setting `,_jsx(_components.code,{children:`powersyncOptions.transformData`}),`, a callback is invoked every time a created or updated row is uploaded to Supabase. This allows you to customize how individual values are represented for Postgres. In this case, the `,_jsx(_components.code,{children:`tags`}),` column of the `,_jsx(_components.code,{children:`lists`}),` table is decoded as JSON so that it’s uploaded as a proper array while being stored as a list locally.`]}),`\n`,_jsx(Heading,{level:`2`,id:`custom-backend-connectors`,children:`Custom Backend Connectors`}),`\n`,_jsx(_components.p,{children:`To enable an easy setup, the PowerSync FlutterFlow library integrates with Supabase by default. This means that as long as you use Supabase for authentication in your app, PowerSync will automatically connect as soon as users log in, and can automatically upload local writes to a Supabase database.`}),`\n`,_jsxs(_components.p,{children:[`For apps that don’t use Supabase, you can disable this default behavior and instead rely on your own backend connectors. For this, create your own custom action (e.g. `,_jsx(_components.code,{children:`applyPowerSyncOptions`}),`). It’s important that this action runs before anything else in your app uses PowerSync, so add this action to your `,_jsx(_components.code,{children:`main.dart`}),` as a final action.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`26`,language:`dart`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`dart`,children:_jsxs(_components.code,{language:`dart`,numberOfLines:`26`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'package:power_sync_b0w5r9/custom_code/actions/initialize_power_sync.dart'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'package:powersync/powersync.dart'`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ps;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`Future`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` applyPowerSyncOptions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`async`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Disable the default Supabase integration`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` powerSyncOptions.useSupabaseConnector `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` final`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` db `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` getOrInitializeDatabase`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // TODO: Write your own connector and call connect/disconnect when a user logs`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // in.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` db.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`connect`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(connector`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` _MyCustomConnector`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`());`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`final`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` class`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` _MyCustomConnector`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` extends`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ps.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`PowerSyncBackendConnector`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` @override`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` Future`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003cps.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`PowerSyncCredentials`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`?> `}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`fetchCredentials`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`() {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // TODO: implement fetchCredentials`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` throw`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` UnimplementedError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` @override`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` Future`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`void`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`> `}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`uploadData`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(ps.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`PowerSyncDatabase`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` database) {`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // TODO: implement uploadData`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` throw`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` UnimplementedError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`();`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`For more information on writing backend connectors, see `,_jsx(_components.a,{href:`/client-sdks/reference/flutter#3-integrate-with-your-backend`,children:`integrating with your backend`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`known-issues-limitations-and-gotchas`,children:`Known Issues, Limitations and Gotchas`}),`\n`,_jsx(_components.p,{children:`Below is a list of known issues and limitations.`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Deploying to the Apple App Store currently requires some workarounds due to limitations in FlutterFlow:`,`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Download the code from FlutterFlow.`}),`\n`,_jsxs(_components.li,{children:[`Open the `,_jsx(_components.code,{children:`Podfile`}),` located in the `,_jsx(_components.code,{children:`ios/`}),` directory.`]}),`\n`,_jsxs(_components.li,{children:[`The following option in the `,_jsx(_components.code,{children:`Podfile`}),` needs to be updated from `,_jsx(_components.code,{children:`use_frameworks! :linkage => :static`}),` to `,_jsx(_components.code,{children:`use_frameworks!`}),` (remove everything after the exclamation sign).`]}),`\n`,_jsx(_components.li,{children:`After removing that option, clean the build folder and build the project again.`}),`\n`,_jsx(_components.li,{children:`You should now be able to submit to the App Store.`}),`\n`]}),`\n`]}),`\n`,_jsx(_components.li,{children:`Exporting the code from FlutterFlow using the “Download Code” action in FlutterFlow requires the same workaround listed above.`}),`\n`,_jsxs(_components.li,{children:[`The PowerSync FlutterFlow Library does not currently support `,_jsx(_components.a,{href:`/client-sdks/advanced/data-encryption`,children:`encryption at rest`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Other common issues and troubleshooting techniques are documented here: `,_jsx(_components.a,{href:`/debugging/troubleshooting`,children:`Troubleshooting`}),`.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"FlutterFlow + PowerSync","description":"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.","sidebarTitle":"Overview","href":"/integrations/flutterflow/guide","hidden":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Guide Overview","slug":"guide-overview","depth":2,"children":[]},{"title":"Configure Supabase","slug":"configure-supabase","depth":2,"children":[]},{"title":"Configure PowerSync","slug":"configure-powersync","depth":2,"children":[{"title":"Create a PowerSync Cloud Instance","slug":"create-a-powersync-cloud-instance","depth":3,"children":[]},{"title":"Connect PowerSync to Your Supabase","slug":"connect-powersync-to-your-supabase","depth":3,"children":[]},{"title":"Enable Supabase Auth","slug":"enable-supabase-auth","depth":3,"children":[]},{"title":"Configure Sync Rules","slug":"configure-sync-rules","depth":3,"children":[]}]},{"title":"Initialize Your FlutterFlow Project","slug":"initialize-your-flutterflow-project","depth":2,"children":[]},{"title":"Build A Sign-In Screen","slug":"build-a-sign-in-screen","depth":2,"children":[]},{"title":"Read Data","slug":"read-data","depth":2,"children":[{"title":"Prepare Supabase Tables for Reads","slug":"prepare-supabase-tables-for-reads","depth":3,"children":[]},{"title":"1. Auto-Updating Queries for Layout Elements with Dynamic Children","slug":"1-auto-updating-queries-for-layout-elements-with-dynamic-children","depth":3,"children":[]},{"title":"Create a Component to Display List Items","slug":"create-a-component-to-display-list-items","depth":4,"children":[]},{"title":"Display the List Component and Populate it with Data","slug":"display-the-list-component-and-populate-it-with-data","depth":4,"children":[]},{"title":"Test Your App","slug":"test-your-app","depth":4,"children":[]},{"title":"2. Auto-Updating Queries for Basic Layout Elements","slug":"2-auto-updating-queries-for-basic-layout-elements","depth":3,"children":[]},{"title":"Create a Page Parameter","slug":"create-a-page-parameter","depth":4,"children":[]},{"title":"Create a Local Page State Variable","slug":"create-a-local-page-state-variable","depth":4,"children":[]},{"title":"Bind the Page Title to the Page State","slug":"bind-the-page-title-to-the-page-state","depth":4,"children":[]},{"title":"Make the ListView Component Clickable","slug":"make-the-listview-component-clickable","depth":4,"children":[]},{"title":"Test Your App","slug":"test-your-app-2","depth":4,"children":[]},{"title":"3. Once-Off Reads for Static Data","slug":"3-once-off-reads-for-static-data","depth":3,"children":[]}]},{"title":"Create Data","slug":"create-data","depth":2,"children":[]},{"title":"Update Data","slug":"update-data","depth":2,"children":[]},{"title":"Delete Data","slug":"delete-data","depth":2,"children":[]},{"title":"Sign Out","slug":"sign-out","depth":2,"children":[]},{"title":"(Optional) Display Connectivity and Sync Status","slug":"optional-display-connectivity-and-sync-status","depth":2,"children":[]},{"title":"Secure Your App","slug":"secure-your-app","depth":2,"children":[{"title":"Enable RLS in Supabase","slug":"enable-rls-in-supabase","depth":3,"children":[]},{"title":"Update Sync Rules","slug":"update-sync-rules","depth":3,"children":[]}]},{"title":"Arrays, JSON and Other Types","slug":"arrays-json-and-other-types","depth":2,"children":[]},{"title":"Custom Backend Connectors","slug":"custom-backend-connectors","depth":2,"children":[]},{"title":"Known Issues, Limitations and Gotchas","slug":"known-issues-limitations-and-gotchas","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/powersync/490dc2634d86290c/inkeep.js","/_mintlify/custom/powersync/31782de1dd38c713/scroll-restoration.js"],"subdomain":"powersync","siteName":"PowerSync","title":"FlutterFlow + PowerSync - PowerSync","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-26T11:00:34.311Z","originalFileLocation":"integrations/flutterflow/guide.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.\">\u003cmeta data-mint-head name=\"application-name\" content=\"PowerSync\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"noindex\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"FlutterFlow + PowerSync - PowerSync\">\u003cmeta data-mint-head property=\"og:description\" content=\"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"PowerSync\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.powersync.com/integrations/flutterflow/guide\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://powersync.mintlify.app/_mintlify/api/og/v2?division=FlutterFlow\u0026amp;title=FlutterFlow+%2B+PowerSync\u0026amp;description=Build+local-first+apps+with+FlutterFlow+and+PowerSync+using+Supabase+as+the+backend.\u0026amp;theme=a61a6b78fff5638e61ee1809\u0026amp;signature=d7f7f77998730185d8e66c020d2a7bf2cc0df825fc58d83c955f35e87c71adee\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"FlutterFlow + PowerSync - PowerSync\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://powersync.mintlify.app/_mintlify/api/og/v2?division=FlutterFlow\u0026amp;title=FlutterFlow+%2B+PowerSync\u0026amp;description=Build+local-first+apps+with+FlutterFlow+and+PowerSync+using+Supabase+as+the+backend.\u0026amp;theme=a61a6b78fff5638e61ee1809\u0026amp;signature=d7f7f77998730185d8e66c020d2a7bf2cc0df825fc58d83c955f35e87c71adee\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/powersync/dhIUAAc0qIG0PJBM/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"PowerSync\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#4e89ff\">\u003cmeta data-mint-head name=\"og:locale\" content=\"en_US\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.powersync.com/integrations/flutterflow/guide\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/integrations/flutterflow/guide.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://www.powersync.com/#organization\",\"name\":\"PowerSync\",\"url\":\"https://www.powersync.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://docs.powersync.com/images/logo.png\"},\"sameAs\":[\"https://github.com/powersync-ja\",\"https://x.com/powersync_\",\"https://www.linkedin.com/showcase/journeyapps-powersync/\",\"https://bsky.app/profile/powersync.com\"]},{\"@type\":\"WebSite\",\"@id\":\"https://docs.powersync.com#website\",\"name\":\"PowerSync\",\"url\":\"https://docs.powersync.com\",\"publisher\":{\"@id\":\"https://www.powersync.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.powersync.com/integrations/flutterflow/guide#webpage\",\"url\":\"https://docs.powersync.com/integrations/flutterflow/guide\",\"name\":\"FlutterFlow + PowerSync\",\"description\":\"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.\",\"dateModified\":\"2026-10-26T11:00:34.311Z\",\"isPartOf\":{\"@id\":\"https://docs.powersync.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.powersync.com/integrations/flutterflow/guide#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.powersync.com/integrations/flutterflow/guide#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Integrations\",\"item\":\"https://docs.powersync.com/integrations/overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"FlutterFlow + PowerSync\",\"item\":\"https://docs.powersync.com/integrations/flutterflow/guide\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.powersync.com/integrations/flutterflow/guide#article\",\"headline\":\"FlutterFlow + PowerSync\",\"name\":\"FlutterFlow + PowerSync\",\"description\":\"Build local-first apps with FlutterFlow and PowerSync using Supabase as the backend.\",\"url\":\"https://docs.powersync.com/integrations/flutterflow/guide\",\"mainEntityOfPage\":{\"@id\":\"https://docs.powersync.com/integrations/flutterflow/guide#webpage\"},\"dateModified\":\"2026-10-26T11:00:34.311Z\",\"publisher\":{\"@id\":\"https://www.powersync.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.powersync.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"PowerSync\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"PowerSync","nav":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/powersync-ja"},{"anchor":"Community Discord","icon":"discord","href":"https://discord.com/invite/powersync"},{"anchor":"PowerSync Website","icon":"browser","href":"https://www.powersync.com/"}]},"tabs":[{"tab":" ","groups":[{"group":"Get Started","icon":"rocket","pages":[{"title":"PowerSync Docs","sidebarTitle":"Introduction","href":"/intro/powersync-overview"},{"title":"PowerSync Setup Guide","sidebarTitle":"Setup Guide","href":"/intro/setup-guide"},{"group":"Understand PowerSync","pages":[{"title":"PowerSync Philosophy","href":"/intro/powersync-philosophy"},{"group":"Architecture","pages":[{"title":"Architecture Overview","href":"/architecture/architecture-overview"},{"title":"PowerSync Service","href":"/architecture/powersync-service"},{"title":"Client Architecture","href":"/architecture/client-architecture"},{"title":"PowerSync Protocol","href":"/architecture/powersync-protocol"},{"title":"Consistency","href":"/architecture/consistency"}]}]},{"title":"Demo Apps \u0026 Example Projects","sidebarTitle":"Examples","href":"/intro/examples"},{"title":"Self-Hosting","href":"/intro/self-hosting"},{"group":"Migration Guides","pages":[{"title":"MongoDB Atlas Device Sync Migration Guide","sidebarTitle":"MongoDB Atlas Device Sync","href":"/migration-guides/atlas-device-sync"},{"title":"Electric Cloud Migration Guide","sidebarTitle":"Electric Cloud","href":"/migration-guides/electric"}]}]},{"group":"Configuration Details","icon":"gear","pages":[{"group":"Source Database","pages":[{"title":"Source Database Setup","href":"/configuration/source-db/setup"},{"title":"Source Database Connection","href":"/configuration/source-db/connection"},{"title":"Security \u0026 IP Filtering","href":"/configuration/source-db/security-and-ip-filtering"},{"title":"Private Endpoints","href":"/configuration/source-db/private-endpoints"},{"title":"Postgres Maintenance","href":"/configuration/source-db/postgres-maintenance"},{"title":"Advanced SQL Server Configuration","sidebarTitle":"Advanced SQL Server Config (Self-Hosted)","href":"/configuration/source-db/sql-server-additional-configuration"}]},{"group":"PowerSync Service Setup","pages":[{"title":"PowerSync Cloud Instances","sidebarTitle":"Cloud Instances","href":"/configuration/powersync-service/cloud-instances"},{"title":"Self-Hosted Instance Configuration","sidebarTitle":"Self-Hosted Instances","href":"/configuration/powersync-service/self-hosted-instances"}]},{"group":"App Backend","pages":[{"title":"App Backend Setup","sidebarTitle":"Server-Side Setup","href":"/configuration/app-backend/setup"},{"title":"Client-Side Integration With Your Backend","sidebarTitle":"Client-Side Integration","href":"/configuration/app-backend/client-side-integration"},{"title":"CloudCode for MongoDB Backends","href":"/configuration/app-backend/cloudcode"}]},{"group":"Authentication","pages":[{"title":"Authentication Setup","sidebarTitle":"Overview","href":"/configuration/auth/overview"},{"title":"Development Tokens","href":"/configuration/auth/development-tokens"},{"title":"Custom Authentication","sidebarTitle":"Custom Auth","href":"/configuration/auth/custom"},{"group":"Provider Specifics","pages":[{"group":"Supabase Auth","pages":[{"title":"Supabase Auth","sidebarTitle":"Overview","href":"/configuration/auth/supabase-auth"},{"title":"Stytch + Supabase","href":"/configuration/auth/supabase-auth/stytch"}]},{"title":"Firebase Auth","href":"/configuration/auth/firebase-auth"},{"title":"Auth0","href":"/configuration/auth/auth0"}]}]}]},{"group":"Sync Streams","icon":"arrows-rotate","pages":[{"title":"Sync Streams","sidebarTitle":"Overview","href":"/sync/streams/overview"},{"title":"Sync Streams Quickstart","sidebarTitle":"Quickstart","href":"/sync/streams/quickstart"},{"group":"Usage","pages":[{"title":"Writing Queries","sidebarTitle":"Writing Queries","href":"/sync/streams/queries"},{"title":"Using Parameters","href":"/sync/streams/parameters"},{"title":"Common Table Expressions (CTEs)","href":"/sync/streams/ctes"},{"title":"Bucket Count and Limits","sidebarTitle":"Bucket Count","href":"/sync/streams/bucket-count"},{"title":"Client-Side Usage","href":"/sync/streams/client-usage"},{"title":"Prioritized Sync","href":"/sync/streams/prioritized-sync"},{"title":"Examples, Patterns \u0026 Demos","sidebarTitle":"Examples \u0026 Demos","href":"/sync/streams/examples"}]},{"group":"Reference","pages":[{"title":"Supported SQL","href":"/sync/supported-sql"},{"title":"Grammar Reference","href":"/sync/grammar/sync-streams/index"},{"title":"Types","sidebarTitle":"Type Mapping","href":"/sync/types"}]},{"group":"Advanced","pages":[{"title":"Advanced Topics","sidebarTitle":"Overview","href":"/sync/advanced/overview"},{"title":"Reducing Bucket Count","sidebarTitle":"Reducing Buckets","href":"/sync/advanced/reducing-bucket-count"},{"title":"Client ID","href":"/sync/advanced/client-id"},{"title":"Case Sensitivity","href":"/sync/advanced/case-sensitivity"},{"title":"Compatibility","href":"/sync/advanced/compatibility"},{"title":"Storage Version 4","href":"/sync/advanced/storage-version-4"},{"title":"Sync Data by Time with Sync Streams","sidebarTitle":"Sync Data by Time","href":"/sync/advanced/sync-data-by-time"},{"title":"Schemas and Connections","href":"/sync/advanced/schemas-and-connections"},{"title":"Multiple Client Versions","href":"/sync/advanced/multiple-client-versions"},{"title":"Partitioned Tables (Postgres)","href":"/sync/advanced/partitioned-tables"},{"title":"Sharded Databases","href":"/sync/advanced/sharded-databases"}]},{"group":"Sync Rules (Legacy)","pages":[{"title":"Migrate to Sync Streams","href":"/sync/rules/migrate-to-sync-streams"},{"title":"Sync Rules (Legacy)","sidebarTitle":"Overview \u0026 Key Concepts","href":"/sync/rules/overview"},{"title":"Organize Data Into Buckets","href":"/sync/rules/organize-data-into-buckets"},{"title":"Global Buckets","href":"/sync/rules/global-buckets"},{"title":"Parameter Queries","href":"/sync/rules/parameter-queries"},{"title":"Data Queries","href":"/sync/rules/data-queries"},{"title":"Many-to-Many Relationships and Join Tables in Sync Rules","sidebarTitle":"Many-to-Many and Join Tables","href":"/sync/rules/many-to-many-join-tables"},{"title":"Client Parameters","href":"/sync/rules/client-parameters"},{"group":"Reference","pages":[{"title":"Supported SQL with Sync Rules","sidebarTitle":"Supported SQL","href":"/sync/rules/supported-sql"},{"title":"Grammar Reference (Sync Rules)","href":"/sync/grammar/sync-rules/index"},{"title":"Types","sidebarTitle":"Type Mapping","href":"/sync/rules/types"}]},{"group":"Advanced","pages":[{"title":"Prioritized Sync with Sync Rules","sidebarTitle":"Prioritized Sync","href":"/sync/rules/prioritized-sync"},{"title":"Client ID","href":"/sync/rules/client-id"},{"title":"Case Sensitivity","href":"/sync/rules/case-sensitivity"},{"title":"Storage Version 4 with Sync Rules","sidebarTitle":"Storage Version 4","href":"/sync/rules/storage-version-4"},{"title":"Sync Data by Time with Sync Rules","sidebarTitle":"Sync Data by Time","href":"/sync/rules/sync-data-by-time"},{"title":"Schemas and Connections","href":"/sync/rules/schemas-and-connections"},{"title":"Multiple Client Versions with Sync Rules","sidebarTitle":"Multiple Client Versions","href":"/sync/rules/multiple-client-versions"},{"title":"Partitioned Tables (Postgres) with Sync Rules","sidebarTitle":"Partitioned Tables (Postgres)","href":"/sync/rules/partitioned-tables"},{"title":"Sharded Databases","href":"/sync/rules/sharded-databases"}]}]}]},{"group":"Client SDKs","icon":"code","pages":[{"title":"Client SDKs Overview","sidebarTitle":"Overview","href":"/client-sdks/overview"},{"group":"JavaScript","icon":"js","pages":[{"group":"JavaScript Web","icon":"js","pages":[{"title":"JavaScript Web SDK","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/javascript-web"},{"title":"JavaScript Web SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-js/web-sdk","href":"/client-sdks/reference/javascript-web-api"}]},{"group":"React Native \u0026 Expo","icon":"react","pages":[{"title":"React Native \u0026 Expo SDK","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/react-native-and-expo"},{"title":"React Native Web Support","sidebarTitle":"Web Support","href":"/client-sdks/frameworks/react-native-web-support"},{"title":"React Native SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-js/react-native-sdk","href":"/client-sdks/reference/react-native-api"}]},{"group":"Capacitor","icon":"c","pages":[{"title":"Capacitor SDK (beta)","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/capacitor"},{"title":"Capacitor SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-js/capacitor-sdk","href":"/client-sdks/reference/capacitor-api"}]},{"group":"Node.js","icon":"node-js","pages":[{"title":"Node.js Client SDK","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/node"},{"title":"Node.js SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-js/node-sdk","href":"/client-sdks/reference/node-api"}]},{"group":"Tauri","icon":"/logo/tauri_sidebar.svg","pages":[{"title":"Tauri SDK (alpha)","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/tauri"}]},{"group":"Frameworks/Integrations","pages":[{"title":"React Hooks","href":"/client-sdks/frameworks/react"},{"title":"Next.js + PowerSync","sidebarTitle":"Next.js","href":"/client-sdks/frameworks/next-js"},{"title":"Vue Composables","href":"/client-sdks/frameworks/vue"},{"title":"Nuxt Integration","sidebarTitle":"Nuxt","href":"/client-sdks/frameworks/nuxt"},{"title":"TanStack Query \u0026 TanStack DB","href":"/client-sdks/frameworks/tanstack"},{"title":"Expo Go Support","sidebarTitle":"Expo Go","href":"/client-sdks/frameworks/expo-go-support"}]},{"group":"JavaScript ORMs","pages":[{"title":"JavaScript ORMs Overview","sidebarTitle":"Overview","href":"/client-sdks/orms/js/overview"},{"title":"Kysely","href":"/client-sdks/orms/js/kysely"},{"title":"Drizzle","href":"/client-sdks/orms/js/drizzle"},{"title":"TanStack DB","url":"https://tanstack.com/db/latest/docs/collections/powersync-collection","href":"/client-sdks/orms/js/tanstack-db"}]}]},{"group":"Dart/Flutter","icon":"flutter","pages":[{"title":"Dart/Flutter SDK","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/flutter"},{"title":"Dart/Flutter Web Support (Beta)","sidebarTitle":"Web Support","href":"/client-sdks/frameworks/flutter-web-support"},{"title":"Dart/Flutter ORM Support","sidebarTitle":"ORM Support","href":"/client-sdks/orms/flutter-orm-support"},{"title":"Flutter SDK API Reference","sidebarTitle":"API Reference","url":"https://pub.dev/documentation/powersync/latest/powersync/powersync-library.html","href":"/client-sdks/reference/flutter-api"},{"title":"Dart \u0026 Flutter DevTools Extension","sidebarTitle":"Dart \u0026 Flutter DevTools","href":"/tools/dart-devtools-extension"}]},{"group":"Kotlin","icon":"android","pages":[{"title":"Kotlin SDK","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/kotlin"},{"group":"Kotlin SQL Libraries","pages":[{"title":"Kotlin SQL Libraries","sidebarTitle":"Overview","href":"/client-sdks/orms/kotlin/overview"},{"title":"SQLDelight (Beta)","href":"/client-sdks/orms/kotlin/sqldelight"},{"title":"Room (Beta)","href":"/client-sdks/orms/kotlin/room"}]},{"title":"Kotlin SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-kotlin/","href":"/client-sdks/reference/kotlin-api"}]},{"group":"Swift","icon":"swift","pages":[{"title":"Swift SDK","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/swift"},{"title":"GRDB (Alpha)","sidebarTitle":"GRDB Library","href":"/client-sdks/orms/swift/grdb"},{"title":"Swift SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-swift/documentation/powersync/","href":"/client-sdks/reference/swift-api"}]},{"group":".NET","icon":"microsoft","pages":[{"title":".NET SDK (beta)","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/dotnet"},{"title":".NET SDK API Reference","sidebarTitle":"API Reference","url":"https://powersync-ja.github.io/powersync-dotnet/api/PowerSync.html","href":"/client-sdks/reference/dotnet-api"}]},{"group":"Rust","icon":"rust","pages":[{"title":"Rust SDK (beta)","sidebarTitle":"SDK Reference","href":"/client-sdks/reference/rust"}]},{"title":"ORM Support Overview","sidebarTitle":"ORM Support","href":"/client-sdks/orms/overview"},{"group":"Reading Data","pages":[{"title":"Reading Data","sidebarTitle":"Overview","href":"/client-sdks/reading-data"},{"title":"Live Queries / Watch Queries","href":"/client-sdks/watch-queries"},{"title":"Experimental: High Performance Diffs","sidebarTitle":"High Performance Diffs","href":"/client-sdks/high-performance-diffs"},{"title":"Full-Text Search","href":"/client-sdks/full-text-search"},{"title":"Infinite Scrolling","href":"/client-sdks/infinite-scrolling"}]},{"group":"Writing Data","pages":[{"title":"Writing Data","sidebarTitle":"Overview","href":"/client-sdks/writing-data"},{"title":"Cascading Delete","href":"/client-sdks/cascading-delete"}]},{"title":"Sync Catch-Up with Checkpoint Requests","sidebarTitle":"Sync Catch-Up","href":"/client-sdks/checkpoint-requests"},{"title":"Usage Examples","href":"/client-sdks/usage-examples"},{"group":"Advanced","pages":[{"title":"Attachments / Files","href":"/client-sdks/advanced/attachments"},{"title":"JSON, Arrays and Custom Types","href":"/client-sdks/advanced/custom-types-arrays-and-json"},{"title":"Querying JSON Data in SQLite","href":"/client-sdks/advanced/query-json-in-sqlite"},{"title":"Sequential ID Mapping","sidebarTitle":"Sequential ID Mapping","href":"/client-sdks/advanced/sequential-id-mapping"},{"title":"Raw SQLite Tables to Bypass JSON View Limitations","sidebarTitle":"Raw SQLite Tables","href":"/client-sdks/advanced/raw-tables"},{"title":"Pre-Seeding SQLite Databases","href":"/client-sdks/advanced/pre-seeded-sqlite"},{"title":"State Management Libraries","href":"/client-sdks/advanced/state-management"},{"title":"CRDT Data Structures","href":"/client-sdks/advanced/crdts"},{"title":"GIS Data: PostGIS","href":"/client-sdks/advanced/gis-data-postgis"},{"title":"Unit Testing","href":"/client-sdks/advanced/unit-testing"},{"title":"Local-Only Usage","href":"/client-sdks/advanced/local-only-usage"},{"title":"Background Syncing","href":"/client-sdks/advanced/background-syncing"},{"title":"Data Encryption","href":"/client-sdks/advanced/data-encryption"},{"title":"Using SQLite Extensions","href":"/client-sdks/advanced/sqlite-extensions"},{"title":"SQLite Performance Optimization","href":"/client-sdks/advanced/performance-optimization"},{"title":"Multi-Process Access","href":"/client-sdks/advanced/multi-process"}]}]},{"group":"Handling Writes","icon":"pen","pages":[{"group":"Upload Queue/Uploads","pages":[{"title":"Writing Client Changes","href":"/handling-writes/writing-client-changes"},{"title":"Handling Write / Validation Errors","href":"/handling-writes/handling-write-validation-errors"}]},{"group":"Conflicts","pages":[{"title":"Handling Update Conflicts","href":"/handling-writes/handling-update-conflicts"},{"title":"Custom Conflict Resolution","href":"/handling-writes/custom-conflict-resolution"}]},{"group":"Advanced","pages":[{"title":"Data Pipelines","sidebarTitle":"Data Pipelines","href":"/handling-writes/custom-write-checkpoints"}]}]},{"group":"Maintenance \u0026 Ops","icon":"screwdriver-wrench","pages":[{"group":"Debugging","pages":[{"title":"Troubleshooting","href":"/debugging/troubleshooting"},{"title":"Error Codes Reference","sidebarTitle":"Error Codes","href":"/debugging/error-codes"},{"title":"Log Reference","href":"/debugging/log-reference"},{"title":"Sync Diagnostics Client","url":"https://github.com/powersync-ja/powersync-js/tree/main/tools/diagnostics-app#readme","href":"/tools/diagnostics-client"},{"title":"Understanding the SQLite Database","href":"/maintenance-ops/client-database-diagnostics"}]},{"title":"Monitoring and Alerting","href":"/maintenance-ops/monitoring-and-alerting"},{"title":"Replication Lag","href":"/maintenance-ops/replication-lag"},{"title":"Production Readiness Best Practices Guide","sidebarTitle":"Production Readiness Best Practices","href":"/maintenance-ops/production-readiness-guide"},{"title":"Compacting Buckets","href":"/maintenance-ops/compacting-buckets"},{"group":"Handling Schema Changes","pages":[{"title":"Implementing Schema Changes","href":"/maintenance-ops/implementing-schema-changes"},{"title":"Deploying Schema Changes","sidebarTitle":"Deploying Schema Changes","href":"/maintenance-ops/deploying-schema-changes"}]},{"group":"Self-Hosting","pages":[{"title":"Self-Hosting Maintenance \u0026 Ops","sidebarTitle":"Overview","href":"/maintenance-ops/self-hosting/overview"},{"title":"Deployment Architecture","sidebarTitle":"Deployment Architecture","href":"/maintenance-ops/self-hosting/deployment-architecture"},{"group":"Deployment Platforms","pages":[{"title":"Railway + PowerSync","sidebarTitle":"Railway","href":"/maintenance-ops/self-hosting/railway"},{"title":"Deploy PowerSync Service on Coolify","sidebarTitle":"Coolify","href":"/maintenance-ops/self-hosting/coolify"},{"title":"Deploy PowerSync on AWS ECS","sidebarTitle":"AWS ECS","href":"/maintenance-ops/self-hosting/aws-ecs"},{"title":"Deploy PowerSync on AWS EKS","sidebarTitle":"AWS EKS","href":"/maintenance-ops/self-hosting/aws-eks"}]},{"title":"Update Sync Streams (Sync Config)","href":"/maintenance-ops/self-hosting/update-sync-rules"},{"title":"Health Checks","href":"/maintenance-ops/self-hosting/healthchecks"},{"title":"Securing Your Deployment","href":"/maintenance-ops/self-hosting/securing-your-deployment"},{"title":"Monitoring","href":"/maintenance-ops/self-hosting/monitoring"},{"title":"Usage Reporting","href":"/maintenance-ops/self-hosting/usage-reporting"},{"title":"Diagnostics","href":"/maintenance-ops/self-hosting/diagnostics"},{"title":"Multiple PowerSync Instances","href":"/maintenance-ops/self-hosting/multiple-instances"},{"title":"Migrating Between Instances","href":"/maintenance-ops/self-hosting/migrating-instances"}]}]},{"group":"Integrations","icon":"plug","pages":[{"title":"Integrations Overview","sidebarTitle":"Overview","href":"/integrations/overview"},{"group":"Supabase","pages":[{"title":"Supabase + PowerSync","sidebarTitle":"Overview","href":"/integrations/supabase/guide"},{"title":"PowerSync and Supabase Realtime","href":"/integrations/supabase/realtime-streaming"},{"title":"RLS and Sync Streams","href":"/integrations/supabase/rls-and-sync-streams"},{"title":"Local Development with Supabase and PowerSync","sidebarTitle":"Local Development","href":"/integrations/supabase/local-development"},{"title":"Improve Supabase Connector","description":"Optimize Supabase connector performance in PowerSync apps.","href":"/integrations/supabase/connector-performance"}]},{"group":"FlutterFlow","hidden":true,"pages":[{"title":"FlutterFlow + PowerSync","sidebarTitle":"Overview","href":"/integrations/flutterflow/guide"},{"title":"Handling Attachments","description":"Sync file attachments between PowerSync, FlutterFlow, and Supabase Storage.","href":"/integrations/flutterflow/attachments"},{"title":"FlutterFlow + PowerSync Legacy Guide","description":"Legacy integration guide for building offline-first apps with FlutterFlow and PowerSync using Supabase, for projects on older SDK versions.","sidebarTitle":"Legacy Guide","href":"/integrations/flutterflow/legacy-guide"}]},{"title":"Neon + PowerSync","description":"Build apps on Neon with PowerSync that use client-side SQLite for real-time updates across users and devices, instant interactions and continued functionality when offline.","sidebarTitle":"Neon","href":"/integrations/neon"},{"title":"Serverpod + PowerSync","sidebarTitle":"Serverpod","href":"/integrations/serverpod"}]},{"group":"Tools","icon":"toolbox","pages":[{"title":"Tools","sidebarTitle":"Overview","href":"/tools/overview"},{"title":"CLI","href":"/tools/cli"},{"title":"PowerSync Dashboard","href":"/tools/powersync-dashboard"},{"title":"Sync Diagnostics Client","url":"https://github.com/powersync-ja/powersync-js/tree/main/tools/diagnostics-app#readme","href":"/tools/diagnostics-client"},{"group":"DevTools","pages":[{"title":"PowerSync DevTools","sidebarTitle":"Overview","href":"/tools/devtools-overview"},{"group":"Set Up","pages":[{"title":"PowerSync DevTools for Vite","sidebarTitle":"Vite","href":"/tools/devtools/vite"},{"title":"PowerSync DevTools for Nuxt","sidebarTitle":"Nuxt","href":"/tools/devtools/nuxt"},{"title":"PowerSync DevTools for Node.js","sidebarTitle":"Node.js","href":"/tools/devtools/node"}]},{"title":"Using PowerSync DevTools","sidebarTitle":"Using DevTools","href":"/tools/devtools/using-devtools"},{"title":"PowerSync DevTools MCP Tools","sidebarTitle":"MCP Tools","href":"/tools/devtools/mcp"}]},{"title":"Run PowerSync Locally with Docker and the CLI","sidebarTitle":"Local Development","href":"/tools/local-development"},{"title":"Terraform Provider","href":"/tools/terraform"},{"title":"AI Tools","href":"/tools/ai-tools"}]},{"group":"Resources","icon":"book","pages":[{"group":"Usage \u0026 Billing","pages":[{"title":"Usage \u0026 Billing","sidebarTitle":"Overview","href":"/resources/usage-and-billing"},{"title":"Pricing Example","href":"/resources/usage-and-billing/pricing-example"},{"title":"Reducing Usage","sidebarTitle":"Reducing Usage","href":"/resources/usage-and-billing/reducing-usage"},{"title":"FAQ \u0026 Troubleshooting","href":"/resources/usage-and-billing/usage-and-billing-faq"}]},{"title":"Performance and Limits","href":"/resources/performance-and-limits"},{"title":"Supported Platforms","href":"/resources/supported-platforms"},{"title":"Feature Status","href":"/resources/feature-status"},{"title":"FAQ","href":"/resources/faq"},{"title":"Local-First Software","href":"/resources/local-first-software"},{"group":"Alternatives","pages":[{"title":"Alternatives Overview","sidebarTitle":"Overview","href":"/resources/alternatives/overview"},{"title":"PowerSync vs Neon Realtime","sidebarTitle":"PowerSync vs Neon Realtime","href":"/resources/alternatives/neon-realtime"}]},{"group":"Security \u0026 HIPAA","pages":[{"title":"Security \u0026 HIPAA","sidebarTitle":"Overview","href":"/resources/security"},{"title":"HIPAA Compliance","href":"/resources/hipaa"}]},{"title":"Contact Us","href":"/resources/contact-us"}]}]}]},"title":"FlutterFlow + PowerSync - PowerSync","buildId":"dpl_2xiSHD9XEvLsPGPcfoMtkLTB3dy9","deploymentId":"dpl_2xiSHD9XEvLsPGPcfoMtkLTB3dy9","dynamics":["07c022d89b","a74be98ba7"],"chunks":["Frame-DYplxqhs.js","DynamicMarkdown-Cc6AuSHS.js","zoom-image-lightbox-BNnMwe0F.js","lightbox-handle-r17bVUz3.js"]}