Skip to content

Generated Code update: secure keys #283

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/generated-code/component-gen-code.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Components
title: Component Model
slug: /generated-code/component-model
sidebar_position: 6
sidebar_position: 5
---

# Generated Code: Components
Expand Down
2 changes: 1 addition & 1 deletion docs/generated-code/ff-app-state.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: FFAppState
sidebar_position: 2
sidebar_position: 4
---

# FFAppState
Expand Down
2 changes: 1 addition & 1 deletion docs/generated-code/pages-generated-code.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Pages
title: Page Model
slug: /generated-code/page-model
sidebar_position: 5
---
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
---
slug: /concepts/state-management/generated-code
title: Generated Code
slug: /generated-code/state-management
title: FlutterFlow State Management
description: Learn about the state management used in FlutterFlow's generated code.
tags: [Generated Code, Concepts, State Management]
toc_max_heading_level: 5
sidebar_position: 2
toc_max_heading_level: 4
sidebar_position: 3
keywords: [FlutterFlow, Generated Code, State Management, Concepts]
---

# State Management
# FlutterFlow State Management

:::warning[Correct topic?]
This document explains the generated code behind the state management approaches used in FlutterFlow. If you're looking for guidance on adding state variables in FlutterFlow, refer to the **[State Variables](../ff-concepts/state-management/state-variables.md)** documentation.
:::

FlutterFlow manages state in several ways, depending on the scope.

Generally, state management is handled using the Provider package, which facilitates the provisioning of data models for components, pages, and the overall app state.
Generally, state management is handled using the [Provider](https://pub.dev/packages/provider) package, which facilitates the provisioning of data models for components, pages, and the overall app state.

![state-management.avif](../../../static/img/state-management.avif)
![state-management.avif](../../static/img/state-management.avif)

## Page & Component Models

Expand All @@ -24,13 +28,13 @@ Additionally, they provide space for action blocks, which are a set of actions t

## Page State

[Variables](../../resources/ui/pages/page-lifecycle.md) used exclusively within a page — such as a text field validator or the value of a checkbox — are stored in the `Model` of each page. These variables can be accessed by other component children on the same page. For instance, on a page with a form, tapping a button in one component may need to access the value of a text field in a different component.
[Variables](../resources/ui/pages/page-lifecycle.md) used exclusively within a page — such as a text field validator or the value of a checkbox — are stored in the `Model` of each page. These variables can be accessed by other component children on the same page. For instance, on a page with a form, tapping a button in one component may need to access the value of a text field in a different component.

Variables within a page are tracked through `StatefulWidget` and are encapsulated into that page’s Model.

## Component State

Similar to page state, [**Component State variables**](../../resources/ui/components/component-lifecycle.md) are accessible within the component where they are defined. Each component has a corresponding `Model` and `Widget` class. Variables may be passed in from their parent as parameters. Additionally, you can access component state values from its parent Page widget.
Similar to page state, [**Component State variables**](../resources/ui/components/component-lifecycle.md) are accessible within the component where they are defined. Each component has a corresponding `Model` and `Widget` class. Variables may be passed in from their parent as parameters. Additionally, you can access component state values from its parent Page widget.

This accessibility is possible because the Model of a component is instantiated within the parent Page model. It utilizes the Provider method `context.read()`, which returns any existing model in the tree before instantiating a new one. Thus, any updates to the state in the component model will reflect in the parent’s instance of that component model.

Expand All @@ -40,6 +44,13 @@ For example, if a page includes a component with a text field and later on the p

It’s important to note that components cannot directly access variables of other components on the same page. However, you can pass a variable from ComponentA as a parameter to ComponentB in their parent Page. This ensures that ComponentB receives all updates from ComponentA as expected.

## App State

:::info[FFAppState]
The generated code behind FlutterFlow's App State class is explained in the **[FFAppState](ff-app-state.md)** documentation.

:::

## Variables

Variables required across multiple pages of the app, such as a username, should be added to the App State. Refer to `lib/app_state.dart`.
Expand All @@ -50,9 +61,18 @@ On each page that requires access to app state variables, the method ```context.

## Persisting App State

When an app state variable is created, selecting the "Persisted" option enables FlutterFlow to save it on the device using the [shared_preferences package](https://pub.dev/packages/shared_preferences). This ensures the variable remains available even after the app is restarted, making it ideal for persisting settings such as login status or a user's choice between light and dark modes.
When an app state variable is created, selecting the "Persisted" option enables FlutterFlow to save it on the device using the [**Shared Preferences**](https://pub.dev/packages/shared_preferences) package. This ensures the variable remains available even after the app is restarted, making it ideal for persisting settings such as login status or a user's choice between light and dark modes.

If the "**Secure Persisted Fields**" option is enabled in the app state settings, FlutterFlow utilizes the [**Flutter Secure Storage**](https://pub.dev/packages/flutter_secure_storage) package to encrypt the data.

:::tip[Platform Differences]
If the platform is **Android**, then `flutter_secure_storage` stores data in [**`encryptedSharedPreference`**](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences), which are shared preferences that encrypt keys and values. It handles [**AES Encryption**](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) to generate a secret key encrypted with [**RSA**](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) and stored in [**KeyStore**](https://developer.android.com/reference/java/security/KeyStore).

For the **iOS** platform, it uses the [**KeyChain**](https://developer.apple.com/documentation/security/keychain_services) which is an iOS-specific secure storage used to store and access cryptographic keys only in your app.

In the case of the **Web**, it uses the [**Web Cryptography**](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) (Web Crypto) API.
:::

If the "Secure Persisted Fields" option is enabled in the app state settings, FlutterFlow utilizes the [flutter_secure_storage package](https://pub.dev/packages/flutter_secure_storage) to encrypt the data. This package leverages platform-specific implementations for data encryption, utilizing Keychain on iOS, KeyStore on Android, and libsecret on Linux.

## Global State

Expand Down
2 changes: 1 addition & 1 deletion docs/marketplace/creators-hub/submission-criteria.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ Building a solid app template goes beyond surface-level design. It's about creat
- **Criteria:** Implement state management effectively to ensure data is updated and reflected correctly across your application.
- **Why it Matters:** Proper state management is crucial for building responsive and dynamic Flutter apps. It helps prevent data inconsistencies, improves performance, and makes your code easier to maintain.
- **What To Do:**
- **Choose the right state management scope:** FlutterFlow supports (1) [App State](../../resources/data-representation/app-state.md) (2) [Page State](../../resources/ui/pages/page-lifecycle.md#page-state) and (3) [Component State](../../ff-concepts/state-management/generated-code.md#component-state) variables. Familiarize yourself with these options and scope any state variables to where they are needed. For instance, do not use App State to control the value of a checkbox within a component.
- **Choose the right state management scope:** FlutterFlow supports (1) [App State](../../resources/data-representation/app-state.md) (2) [Page State](../../resources/ui/pages/page-lifecycle.md#page-state) and (3) [Component State](../../resources/ui/components/component-lifecycle.md#creating-a-component-state) variables. Familiarize yourself with these options and scope any state variables to where they are needed. For instance, do not use App State to control the value of a checkbox within a component.
- **Rebuild efficiently:** Ensure changes to state rebuild only the necessary scope for efficiency.

#### 5.10 Organized Widget Tree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ The PUT and PATCH API calls can be defined similarly; make sure you enter a vali
You can create a group of API calls that share the same base URL. Grouping the API calls helps you add all request headers (e.g., auth token) at once, and they will be automatically added for all the API calls inside the group.

:::warning
For [**private APIs**](rest-api.md#making-an-api-call-private), headers defined within the group will not be automatically included. You'll need to manually add headers for APIs marked as private.
For [**private APIs**](rest-api.md#private-api-calls), headers defined within the group will not be automatically included. You'll need to manually add headers for APIs marked as private.
:::

To create the API Group:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions docs/resources/control-flow/backend-logic/api/rest-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,16 +639,16 @@ To use a predefined JSON Path, first, select your API response. Then, set the **

You can make the API call private and change the proxy settings using advanced settings.

### Making an API call private
### Private API Calls

Making an API call private is helpful if it uses tokens or secrets you don't want to expose in your app. Enabling this setting will route this API call securely via the Firebase Cloud Functions.

To make the API call private, open the **Advanced Settings** tab, turn on the **Make Private** toggle, Click **Save,** and then **Deploy APIs**.
![private-cloud-func.png](imgs/private-cloud-func.png)

Optionally, you can force a user to be authenticated via the Firebase authentication to make this API call. To do so, turn on the **Require Authentication** toggle.
To make an API Call Private, open the **Advanced Settings** tab, turn on the **Make Private** toggle, Click **Save,** and then **Deploy APIs**.

Optionally, you can force a user to be authenticated via the Firebase authentication to make this API call. To do so, turn on the **Require Authentication** toggle.

:::info

Private APIs are deployed as [**Cloud Functions**](https://firebase.google.com/docs/functions) within your Firebase project. While deploying, you can configure the following options:

Expand All @@ -659,7 +659,7 @@ Private APIs are deployed as [**Cloud Functions**](https://firebase.google.com/d

**Note**: To minimize costs, you can set the **Min Instances** value to 0. For detailed pricing information, refer to the [**Cloud Functions Pricing page**](https://cloud.google.com/functions/pricing-overview).

:::


<div style={{
position: 'relative',
Expand Down
4 changes: 2 additions & 2 deletions docs/resources/data-representation/app-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ App state variables are specific variables that hold the current state of an app

App state variables should be used in scenarios where the same data needs to be accessed and modified from multiple locations within the app. For instance, in a shopping cart app, items in a user's cart are usually accessible across different pages.

App state variables should not be used for temporary data that doesn't impact the overall state of the application. For instance, a user's temporary input in a form should not be stored in an app state variable. It would be more appropriate to use a [page state](../../resources/ui/pages/page-lifecycle.md#page-state) or [component state](../../ff-concepts/state-management/generated-code.md#component-state) variable instead.
App state variables should not be used for temporary data that doesn't impact the overall state of the application. For instance, a user's temporary input in a form should not be stored in an app state variable. It would be more appropriate to use a [page state](../../resources/ui/pages/page-lifecycle.md#page-state) or [component state](../../generated-code/state-mgmt-gen-code.md#component-state) variable instead.

## App State Variables

Expand Down Expand Up @@ -58,7 +58,7 @@ Head over to the left-side navigation menu and follow the steps below to create
- **Persisted:** Whether this app state is saved to disk so that it can be loaded when the app is restarted. Otherwise the field will be reset on restart.

:::tip[Generated Code]
Curious about what happens when the **Persisted** toggle is on? Check out the [**Generated Code**](../../ff-concepts/state-management/generated-code.md#persisting-app-state) guide.
Curious about what happens when the **Persisted** toggle is on? Check out the [**Generated Code**](../../generated-code/state-mgmt-gen-code.md#persisting-app-state) guide.
:::


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/data-representation/global-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ A list of all the available global properties is as follows:
- **Current Environment**: Gives you the current [development environment](../../testing-deployment-publishing/development-environments/development-environments.md) value.

:::tip[Generated Code]
Learn more about the [**Generated Code**](../../ff-concepts/state-management/generated-code.md#global-state) behind Global Properties.
Learn more about the [**Generated Code**](../../generated-code/state-mgmt-gen-code.md#global-state) behind Global Properties.
:::

### Current Time
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/projects/libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ To set library values, navigate to **Settings and Integrations > Project Setup >
<p></p>

:::tip
For different [**development environments**](../../testing-deployment-publishing/development-environments/development-environments.md) (e.g., development vs. production), you can bind Library Values to [**environment values**](../../testing-deployment-publishing/development-environments/development-environments.md#use-environment-values). For instance, you could have two different Library Values for an API key, such as `DEV_OPENAI_API_KEY` and `PROD_OPENAI_API_KEY`, and bind them to the development and production environments to track API usage separately.
For different [**development environments**](../../testing-deployment-publishing/development-environments/development-environments.md) (e.g., development vs. production), you can bind Library Values to [**environment values**](../../testing-deployment-publishing/development-environments/development-environments.md#environment-values). For instance, you could have two different Library Values for an API key, such as `DEV_OPENAI_API_KEY` and `PROD_OPENAI_API_KEY`, and bind them to the development and production environments to track API usage separately.
:::

## Libraries with Firebase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ title: Development Environments
description: Learn how to create and leverage development environments in FlutterFlow.
tags: [Dev Environments, Backend, Testing]
sidebar_position: 2
toc_max_heading_level: 4
keywords: [Dev, Development, Environments, FlutterFlow, Backend]
---

Expand Down Expand Up @@ -54,14 +55,15 @@ You can create and switch environments in the **Dev Environments** page in **App
</div>
<p></p>

The selected environment is used to generate the proper app code when you run, test, deploy or export your app. The only things that change between environment are the [Firebase Project](#configuring-firebase-or-supabase-for-each-environment) or variables that are tied to [Environment Values](#use-environment-values)
The selected environment is used to generate the proper app code when you run, test, deploy or export your app. The only things that change between environment are the [Firebase Project](#configuring-firebase-or-supabase-for-each-environment) or variables that are tied to [Environment Values](#environment-values)


### Use Environment Values
### Environment Values
Environment Values can be used to dynamically change parts of your app's code based on the environment that is being used.

For example, in an e-commerce app, you might define an `apiUrl` Environment Value that points to different API URLs for Development, Staging, and Production. This allows you to test new features without affecting the live production environment, where real customer orders are processed.

#### Use Environment Value
Let's see an example of creating and using `apiUrl`:

<div style={{
Expand Down Expand Up @@ -90,16 +92,32 @@ Let's see an example of creating and using `apiUrl`:
</div>
<p></p>

:::info
After switching to an environment, FlutterFlow generates code specific to that environment, for any of the following interactions:
:::tip[Generated Code]
When you switch to an environment, FlutterFlow generates code specific to that environment, for any of the following interactions:
- Test / Run mode sessions
- Local Run
- Code export
- Deployment

You also may see different project errors depending on which environment you have selected.
You may also encounter different project errors depending on the selected environment.

In the generated code, FlutterFlow creates two files:

- `environment.json` – Stores the environment values defined by the user in FlutterFlow.
- `FFDevEnvironmentValues` class – A singleton class that holds a single instance of the `FFDevEnvironmentValues` object. It includes initialization logic and getters for accessing these environment values. They can also be referenced in your custom code resources. See **[Common Custom Code Examples](../../ff-concepts/adding-customization/common-examples.md)**.
:::

#### Private Environment Values

You can mark environment values as private when they contain sensitive information that should not be exposed in the client-side code. **Private** environment values are not included in the generated code.

Currently, the only way to use a private environment value is as a variable in a private API call. Since private API calls are routed through a Cloud Function, the variable value remains hidden from any client-side requests made by the app.

:::tip[Generated Code]
For private environment values, the generated code does not include these values in the `environment.json` file, and no getter logic is created in the `FFDevEnvironmentValues` class.
:::


### Configuring Firebase or Supabase for each Environment
A single FlutterFlow project can have **multiple environments**, each mapped to its **own Firebase or Supabase project**. This ensures that environments like `Development`, `Staging`, and `Production` remain independent, giving you better control over your app's data and behavior throughout different stages of development.

Expand Down Expand Up @@ -159,6 +177,8 @@ It's recommended that you keep schemas consistent between the different Supabase





### FAQ

<details>
Expand Down
5 changes: 5 additions & 0 deletions firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -2322,6 +2322,11 @@
"source": "/firebase-content-manager",
"destination": "/integrations/database/cloud-firestore/firestore-content-manager/",
"type": 301
},
{
"source": "/concepts/state-management/generated-code",
"destination": "/generated-code/state-management",
"type": 301
}
]
}
Expand Down