Skip to content

How to build in FF: consolidated articles from the folder "how to build in FF" in to the … #442

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
123 changes: 123 additions & 0 deletions docs/ff-concepts/advanced/custom-login-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
keywords: ['firebase', 'custom', 'routing']
slug: /custom-login-routing
title: Custom Login Routing
---

# Custom Login Routing

This article explains how to configure custom routing logic for users after they log in, using a mission control (checkup) page. You can route users differently based on their admin status or whether they’ve completed onboarding.

:::info[Prerequisites]
- A FlutterFlow project with **Firebase** set up.
- Authentication configured in the project.
- The following app pages created:
- `LoginPage`
- `OnboardingPage`
- `AdminHomePage`
- `UserHomePage`
- `CheckupPage` (Mission Control Page)
:::

**Create a Local State Variable**

Create a local state variable to track whether the user is logging in for the first time.

1. Go to **Local State** > **+ Add State Variable**.
2. Name the variable `firstTime`.
3. Set the type to `Boolean` and enable **Persist**.

:::tip
The **Persist** setting retains the value locally on the device until the app is uninstalled. It will reset on every refresh when testing in a web browser.
:::

![](imgs/20250430121414406250.png)

![](imgs/20250430121414639307.png)

**Add a User Field for Admin Check**

1. Open **Firebase** > **User Collection** > **+ Add Field**.
2. Create a field called `isAdmin` and set the type to `Boolean`.

This allows conditional routing based on the admin role.

![](imgs/20250430121414890408.png)

![](imgs/20250430121415192057.png)

**Configure Initial Pages**

1. Go to **Settings & Integrations** > **App Details** > **Initial Page**.
2. Set:
- **Entry Page** to `LoginPage`
- **Logged In Page** to `CheckupPage`

:::tip
**Entry Page** appears when no user is logged in.
**Logged In Page** is used when a user is already authenticated.
:::

![](imgs/20250430121415472919.png)

**Define Actions on the Checkup Page**

1. **Check If User Is Logged In**

1. Open the **CheckupPage** in the **Action Flow Editor**.
2. Under **On Page Load**, add a **Conditional Action**.
3. Set source to `Global Properties` > `Is User Logged In`.

- If `FALSE`:
- Add action: **Navigate To** `LoginPage`, disable **Back Navigation**, then **Add Terminate**.

![](imgs/20250430121434550471.png)

![](imgs/20250430121434823464.png)

![](imgs/20250430121435145067.png)

2. **Check If User Is New (First Time Login)**

1. Under the `TRUE` branch of "Is User Logged In", add another **Conditional Action**.
2. Set condition: `Local State` > `firstTime`.

- If `TRUE`:
- Add action: **Navigate To** `OnboardingPage`, disable **Back Navigation**, then **Add Terminate**.

![](imgs/20250430121435792377.png)

3. **Check If User Is an Admin**

1. Under the `FALSE` branch of `firstTime`, add a **Conditional Action**.
2. Set condition: `Authenticated User` > `isAdmin`.

- If `TRUE`:
- Navigate to `AdminHomePage`, disable back navigation, then **Terminate**.

- If `FALSE`:
- Navigate to `UserHomePage`, disable back navigation, then **Terminate**.

![](imgs/20250430121436144376.png)

**Update `firstTime` After Onboarding**

To avoid showing the onboarding page again, update the `firstTime` variable after onboarding:

1. On the `OnboardingPage`, select the **Start** button.
2. Open the **Action Flow Editor**.
3. Add action: **Update Local State** > `firstTime` → set value → `False`.
4. Add navigation: **Navigate To** `CheckupPage`, disable back navigation.

![](imgs/20250430121436460665.png)

![](imgs/20250430121436751661.png)

:::tip
You can reuse the `CheckupPage` to add more advanced routing conditions, such as checking if the user has completed their profile or enabled certain settings.
:::

To skip onboarding for admins as well, extend your logic by nesting onboarding logic inside the admin check condition.

![](imgs/20250430121437067417.png)

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions docs/ff-concepts/animations/custom-loading-bottom-sheet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
keywords: ['make', 'custom', 'indicator', 'bottom sheet', 'loading']
slug: /custom-loading-bottom-sheet
title: Create a Custom Loading Animation Using a Bottom Sheet
---

# Create a Custom Loading Animation Using a Bottom Sheet

Use a custom `Bottom Sheet` to display a loading animation while performing long-running actions such as API calls, database writes, or chained workflows. This guide walks through how to build a non-blocking custom loading indicator.

![](animation_gifs/20250430121406506215.gif)

:::info[Prerequisites]
- A `Bottom Sheet` component with a loading animation (e.g., Lottie, GIF, or static image)
- A page where you want to trigger the loading sequence
:::

1. **Create a Bottom Sheet Component**

1. Go to the **UI Builder** and create a new `Component`.
2. Select the **Bottom Sheet** layout.
3. Add a loading animation:
- Use a **Lottie** animation, **GIF**, or any custom UI for the loading indicator.
- You can also include a `Text` widget to display a status message.

![](animation_gifs/20250430121406885071.png)

This component will serve as the visual loading indicator during your action chain.

2. **Set Up the Action Workflow**

On the page where you want to trigger the loading sequence:

1. **Trigger the workflow** (e.g., on button press).
2. Add a `Delay` action to simulate a task (optional).
3. Add the `Open Bottom Sheet` action and configure it to be **non-blocking**.

![](animation_gifs/20250430121407233519.png)

![](animation_gifs/20250430121407654843.png)

:::warning
Enable the **Non Blocking** option in the `Open Bottom Sheet` action. This allows the workflow to continue running while the bottom sheet is visible.
:::

3. **Add the Main Actions**

1. Add the primary actions you want to perform while the loading indicator is active.
- These could include `API Calls`, `Create Document`, `Update Document`, or chained actions.
2. For demonstration, a `Delay` of 5 seconds is used to simulate long-running tasks.

4. **Dismiss the Bottom Sheet**

Once all actions are complete:

1. Add a `Close Bottom Sheet` action to remove the loading indicator.

![](animation_gifs/20250430121407938780.png)

5. **Show a Confirmation Message**

1. Add a `Show SnackBar` action to display a success message to the user.

This confirms that the actions are complete and the bottom sheet has been dismissed.

![](animation_gifs/20250430121408203472.gif)

You can test this implementation in the public project:
- Navigate to the **CustomLoading** page
- Tap **Login** on the login screen using the test account
- Select **Custom Loading** from the home page to view it in action

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
keywords: ['custom', 'navbar', 'navigation', 'app bar']
slug: /custom-navbar-setup
title: Custom Navigation Bars
---

# Custom Navigation Bars

Build a custom `Navigation Bar` (NavBar) to support dynamic views, role-based access, or complex widget layouts such as embedded cart counters or animated icons. Unlike the default NavBar widget, this approach gives full control over design and visibility.

![](imgs/20250430121449657102.png)

:::info[Prerequisites]
- A component to be used as the custom NavBar.
- Pages with `Stack` layout to allow overlay positioning.
- Local State variable or conditional logic to control visibility.
:::

Follow the steps below:

1. **Build the NavBar Component**

1. Create a **Component** and design your NavBar layout.
2. Add widgets as needed: icons, labels, counters, conditional containers, etc.
3. Ensure the NavBar’s height is consistent across screens (e.g., `100px`).

2. **Add the NavBar to Your Pages**

1. Wrap the page layout in a `Stack`.
2. Place the NavBar component inside a `Container` widget.
- Set the container’s vertical alignment to `1` (bottom).
- Set its width and height to match screen width and desired NavBar height.

```plaintext
Page
└─ Stack
├─ Main Page Content
└─ Container (height: 100px, align: bottom)
└─ NavBar Component
```

3. **Configure NavBar Behavior**

1. Add `Bottom Padding` to your main page content equal to the NavBar’s height. This prevents the NavBar from overlapping other widgets.

![](imgs/20250430121450015102.png)

2. Use `Local State`, `App State`, or conditional logic from a database (e.g., `is_admin`) to control:
- Which version of the NavBar appears.
- Whether the NavBar is visible at all.

:::warning
Avoid placing the custom NavBar on subpages. NavBar components should only be used on top-level pages. Adding back navigation (e.g., `Pop` actions) to these pages may result in routing issues.
:::

**Example: Conditional NavBar Logic**

You can conditionally display different layouts depending on the user’s role:
- **Admin** users may see extra items or a different layout.
- **Standard** users may have limited options.
- Use the `is_admin` field from the `Users` collection to control this logic dynamically.

**Sample Project:**

A public sample project is available demonstrating:
- A basic custom NavBar
- A conditional NavBar that changes layout based on user role

**How to Use the Sample:**

1. Launch the project.
2. Tap **Login** using the pre-configured test user.
3. Navigate to:
- **Custom NavBar/AppBar** to view a static NavBar layout.
- **Conditional NavBar** to explore role-based NavBar behavior.
- Toggle the `is_admin` field to test both states.

![](imgs/20250430121450326812.png)

![](imgs/20250430121450591399.png)

![](imgs/20250430121450801118.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,55 @@ If you prefer watching a video tutorial, here's the one for you:
allowFullScreen
allow="clipboard-write">
</iframe>
</div>
</div>

## Use Case: Image Carousel with Auto-Scroll

You can build an image carousel using the `PageView` widget combined with the `Control Page View` action. This allows users to scroll through images either manually or automatically.

**Steps Overview:**

1. **Add a PageView Widget**
- From the **Widget Panel**, drag the `PageView` widget onto the canvas.
- Populate it with your image widgets or bind it to a dynamic image list.

2. **Set Up Page Load Action**
- Select the `Scaffold` or main container.
- Add a `Page Load` action to trigger carousel behavior.

3. **Add `Control Page View` Action**
- Use the `Control Page View` action to control transitions:
- `Next`, `Previous`, `First`, or `Last`.

4. **Auto-Scroll Behavior (Optional)**
- Add a sequence of:
- `Control Page View` → `Wait` → `Control Page View` (Next)
- Loop this logic to create a smooth, timed carousel experience.

![Carousel Example](imgs/20250430121318472792.gif)

## Use Case: Image Slider from List of Image URLs

This example demonstrates how to build a dynamic image slider using a list of image URLs—ideal for product detail screens or galleries.

Follow the steps below:

1. **Add a PageView Widget**
- Place a `PageView` on your screen.

2. **Bind to the Image List**
- Generate dynamic children from your list of image URLs.

3. **Add a Repeating Child**
- Use a single `Image` widget inside the `PageView`.
- Bind the `Image URL` to the current list item.

:::tip
You only need one child inside the PageView. When bound to a list, it automatically repeats for each item.
:::

:::tip
- Use horizontal scroll for carousels and onboarding pages.
- Combine with indicators or swipe gestures for a richer UX.
- Use `Wait` and `Control Page View` actions to create auto-scroll behavior.
:::
25 changes: 25 additions & 0 deletions docs/ff-concepts/notifications/push-notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,31 @@ In this action, you can decide who should receive the push notification by setti

![trigger push notifications](imgs/trigger-pn.avif)

### Send Notifications to Multiple Users (Dynamic)

To notify a group of users when a document is created (e.g., group chat, announcement, or event), follow this flow:

1. **Add a Backend Query**
- Add an **Action** → **Backend Query** before sending the notification.
- Set **Query Type** to `Query Collection` and select your users collection (e.g., `users`).
- Set **Return Type** to `List of Documents`.

2. **Create a Document**
- Add an **Action** → **Create Document** to store the submitted content (e.g., a post or message).

3. **Trigger Notification**
- Add an **Action** → **Trigger Push Notification**.
- Set the **audience** to **Multiple Recipients**.
- Under **Recipients**:
- Select **Filter List Items** → **Items in List > Document Exists** to apply conditions.
- Then choose **Map List Items** → `Document Properties` → `Reference` to get user document references.

The notification will be sent to all users matching your filters, using the queried list.

:::tip
Use this approach for dynamic group-based notifications tied to app activity, like chat, announcements, or tasks.
:::

## Testing Push Notifications Cloud Function

You can also test the Push Notifications Cloud Function directly from the Google Cloud console, without needing to trigger from FlutterFlow. This is especially useful for debugging purposes. For step-by-step instructions, including an example and how to structure the request, refer to the [Testing Cloud Functions in Google Cloud Console](../../ff-concepts/adding-customization/cloud-functions.md#testing-cloud-functions-in-google-cloud-console) section.
Expand Down
Loading
Loading