diff --git a/docs/accounts-billing/imgs/add-domain-team.avif b/docs/accounts-billing/imgs/add-domain-team.avif
new file mode 100644
index 00000000..70711269
Binary files /dev/null and b/docs/accounts-billing/imgs/add-domain-team.avif differ
diff --git a/docs/accounts-billing/imgs/add-domain.avif b/docs/accounts-billing/imgs/add-domain.avif
new file mode 100644
index 00000000..70820173
Binary files /dev/null and b/docs/accounts-billing/imgs/add-domain.avif differ
diff --git a/docs/accounts-billing/imgs/pricing-timeline-2025-dark.png b/docs/accounts-billing/imgs/pricing-timeline-2025-dark.png
new file mode 100644
index 00000000..521f6422
Binary files /dev/null and b/docs/accounts-billing/imgs/pricing-timeline-2025-dark.png differ
diff --git a/docs/accounts-billing/imgs/pricing-timeline-2025-light.png b/docs/accounts-billing/imgs/pricing-timeline-2025-light.png
new file mode 100644
index 00000000..8f34e71b
Binary files /dev/null and b/docs/accounts-billing/imgs/pricing-timeline-2025-light.png differ
diff --git a/docs/accounts-billing/imgs/remove-domain-team.avif b/docs/accounts-billing/imgs/remove-domain-team.avif
new file mode 100644
index 00000000..4782a8b1
Binary files /dev/null and b/docs/accounts-billing/imgs/remove-domain-team.avif differ
diff --git a/docs/accounts-billing/imgs/renew.png b/docs/accounts-billing/imgs/renew.png
new file mode 100644
index 00000000..a0a2027d
Binary files /dev/null and b/docs/accounts-billing/imgs/renew.png differ
diff --git a/docs/accounts-billing/manage-custom-domains.md b/docs/accounts-billing/manage-custom-domains.md
index 49d2b682..6c85c302 100644
--- a/docs/accounts-billing/manage-custom-domains.md
+++ b/docs/accounts-billing/manage-custom-domains.md
@@ -2,29 +2,29 @@
# Manage Custom Domains
-Only *Pro* and *Teams* plans include **one** free custom domain. The *Teams* plan comes with one custom domain for the whole team. If you are on the *Standard* plan, you will need to purchase a custom domain, as it is not included in the plan for free.
+All paid plans include one free custom domain, with the option to purchase more if needed.
### How do I purchase additional custom domains?
-To purchase domains:
+To purchase domains, paid users can go to their [**account**](https://app.flutterflow.io/account) page, find the **Custom Domains** section, and click the **Add Domains** button.
-1. *Standard* and *Pro* users can go to their [**account**](https://app.flutterflow.io/account) page, find the **Custom Domains** section, and click the **Add Domains** button.
-2. The *Team* owner can buy from the My Organization page.
-3. Click **Add Domains** to buy a new one.
+
+
+
+The **Team** owner can purchase domains from the **My Team** page. Under the **Custom Domains** section, click **Add Domains** to add one for the team.
+
+
:::note
Note that purchasing a domain is not possible during the trial period. If you're interested in obtaining a domain, please reach out to our support team for further assistance.
:::
-
### How do I remove custom domains?
-To remove the custom domain:
+To remove the custom domain, paid users can go to their [**account**](https://app.flutterflow.io/account) page, find the **Custom Domains** section, and click **Remove Domains** to remove the existing custom domain.
-1. *Standard* and *Pro* users can go to their [**account**](https://app.flutterflow.io/account) page, find the **Custom Domains** section, and click the **Add Domains** button.
-2. The *Team* owner can buy from the My Organization page.
-3. Click **Remove Domains** to remove the existing custom domain.
+The **Team** owner can remove domain from the **My Team** page. In the **Custom Domains** section, click **Remove Domains**.
-
\ No newline at end of file
+
diff --git a/docs/accounts-billing/new-pricing-comparison.md b/docs/accounts-billing/new-pricing-comparison.md
new file mode 100644
index 00000000..20d496f1
--- /dev/null
+++ b/docs/accounts-billing/new-pricing-comparison.md
@@ -0,0 +1,757 @@
+---
+slug: plan-comparison
+title: "Plan Comparison"
+description: "Compare FlutterFlow plans and features to find the right plan for your needs"
+hide_table_of_contents: true
+sidebar_position: 3
+---
+
+
Visual Development Environment Drag & drop builder for creating apps visually
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
1K+ Prebuilt Templates Ready-to-use app templates and components
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Project Count Number of projects you can create
+
2 projects
+
Unlimited
+
Unlimited
+
Unlimited
+
Custom
+
+
+
AI Generation AI-powered assistance for building and coding
+
5 requests/lifetime
+
50 requests/mo
+
200 requests/mo
+
500 requests/mo
+
Custom
+
+
+
+
Data & Integrations
+
+
+
Firebase Integration Connect to Firestore, Firebase Auth, and more
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Supabase Integration Connect to Supabase for database and auth
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
AI Agents Create AI agents with OpenAI, Anthropic, and Google
+
0
+
1
+
Unlimited
+
Unlimited
+
Unlimited
+
+
+
API Endpoints Connect to external APIs and services
+
2
+
Unlimited
+
Unlimited
+
Unlimited
+
Custom
+
+
+
Swagger/OpenAPI Imports Import API specifications automatically
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Development Environments Separate databases and configuration values for testing and production
+
1 (default only)
+
1 (default only)
+
Up to 1 additional (+default)
+
Up to 2 additional (+default)
+
Custom
+
+
+
+
Development Features
+
+
+
Code Extensibility Add custom code to extend functionality
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Live Debugging Test your app in the browser and hot reload
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Visual Logic Builder Create app logic with a visual editor
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
State Management Manage app data and user interface states
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Custom Code Expressions Write custom expressions and logic
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
One-Click Localization (i18n) Automatically translate your app using Google Translate API
+
❌
+
❌
+
✅
+
✅
+
✅
+
+
+
Push to GitHub Push your project code to GitHub
+
❌
+
❌
+
✅
+
✅
+
✅
+
+
+
VS Code Extension Sync custom code files back and forth between FlutterFlow and VS Code
+
❌
+
❌
+
✅
+
✅
+
✅
+
+
+
Automated Testing Run automated tests on your applications
+
❌
+
❌
+
1 test per project
+
Up to 3 tests per project
+
Unlimited tests
+
+
+
Custom Classes Bring custom Dart classes into your app
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
YAML Editing Refactor your project with by editing the YAML representation
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Project API Programmatic access to project data
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
MCP Server (Experimental) Model Context Protocol server integration
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Cloud Functions Write and deploy Firebase Cloud Functions directly from FlutterFlow
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
CLI Command-line interface for downloading code and project management
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Configuration File Snippets Directly modify Info.plist, main.dart, Android manifest, and other config files
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Local Run Desktop Emulator Run code locally with automatic environment setup
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
+
Design Features
+
+
+
Design Systems Consistent color schemes, typographic, icons, and more
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Animations & Haptic Touch Add animations and haptic feedback to your app
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Custom Fonts & Icons Upload and use custom fonts and icons
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Custom Typography Presets Create reusable text styles and presets
+
❌
+
❌
+
❌
+
✅
+
✅
+
+
+
Screenshot Generator Generate app screenshots automatically for App Store review
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Figma Theme Import Import color and typography themes from Figma
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Figma Frame Import AI-powered import of Figma frames to FlutterFlow
+
❌
+
❌
+
❌
+
100 requests/mo
+
Custom
+
+
+
+
Advanced App Features
+
+
+
Push Notifications Send notifications to app users
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Payments Integration Integrate Stripe and other payment providers
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Ads Integration Monetize your app with advertisements
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Third-Party Package Imports Add pub.dev packages and GitHub dependencies
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Debug Panel Advanced debugging tools and console
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
+
Collaboration Features
+
+
+
Number of Editors Team members who can edit projects
+
1
+
1
+
Up to 2
+
Up to 5*
+
Custom
+
+
+
Single Project Collaborator Add-Ons Allow non-team members to collaborate on a single project
+
None
+
None
+
Up to 4 collaborators available for purchase
+
Up to 10 collaborators available for purchase
+
N/A
+
+
+
Real-Time Collaboration Work together on projects simultaneously
+
❌
+
❌
+
✅
+
✅
+
✅
+
+
+
Project Commenting Add comments and feedback to projects
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Manual Commits Make explicit named commits to the current branch for version control
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Number of Branches Create and manage multiple project branches (all plans include main branch)
+
1 (main only)
+
1 (main only)
+
Up to 2 open branches (+main)
+
Up to 5 open branches (+main)
+
Custom
+
+
+
Automated Snapshot Backups Automatic project backups and version control
+
Up to 1 hour prior
+
Up to 1 day prior
+
Up to 3 days prior
+
Up to 7 days prior
+
Custom
+
+
+
Activity Logging Track project changes and user activity
+
❌
+
❌
+
❌
+
❌
+
✅
+
+
+
Project Level Access Control Manage permissions for individual projects
+
Manage view-only collaborators only
+
Manage view-only collaborators only
+
✅
+
✅
+
✅
+
+
+
Centralized Billing Manage team billing from one account
+
❌
+
❌
+
✅
+
✅
+
✅
+
+
+
+
Library Features
+
+
+
Library Imports Add FlutterFlow libraries to your projects
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Library Publishing Publish your projects as reusable libraries
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
+
Deployment
+
+
+
Web Deployment Deploy your app as a web application
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Free Subdomains Deploy your web app to FlutterFlow subdomains
+
Up to 2
+
Up to 20
+
Up to 20
+
Up to 20
+
Unlimited
+
+
+
Custom Domains Deploy to your own custom domain
+
❌
+
Connect 1 domain for free, additional connections will be charged
+
Connect 1 domain for free, additional connections will be charged
+
Connect 1 domain for free, additional connections will be charged
+
Custom
+
+
+
Custom Web Favicon Set custom favicon for web publishing
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
FlutterFlow Watermark Removal Remove FlutterFlow branding from published apps
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
Code Download Download your project's source code
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
APK Download Download Android APK files
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
One-Click Apple & Google Store Deployment Deploy directly to app stores with one click
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
+
Support
+
+
+
Account and Billing Support Help with account management and billing questions
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Community Support Access to FlutterFlow community forums
+
✅
+
✅
+
✅
+
✅
+
✅
+
+
+
Email Support Get help via email from our support team
+
❌
+
✅
+
✅
+
✅
+
✅
+
+
+
In-App Support Chat support directly within FlutterFlow
+
❌
+
❌
+
✅
+
✅
+
✅
+
+
+
Dedicated Live Support Direct access to dedicated support specialists
+
❌
+
❌
+
❌
+
❌
+
✅
+
+
+
+
+ );
+};
+
+# Plan Comparison
+
+Choose the plan that fits your development needs and team size.
+
+
+
+ ← Scroll horizontally to see all plans →
+
+
+
+
+
+## Business Plan Extensions
+
+### *Agencies Expansion
+Includes all Business features, plus the ability to add up to 7 additional seats (12 total per team) at **$85/seat/month** (USD) or **₹2,850/seat/month** (INR) and collaborate with up to 20 other paid users at the project level via Single Project Collaborator Passes. Must be approved as an Expert Agency via [Contra](https://contra.com/opportunity/rWlmk2Yv-become-a-flutter-flow-agency).
+
+### Localized Pricing
+INR pricing reflects localized rates adjusted for local purchasing power, providing the same features and plan structures as USD pricing. All plans include the same comprehensive feature set regardless of currency.
\ No newline at end of file
diff --git a/docs/accounts-billing/payments-billing.md b/docs/accounts-billing/payments-billing.md
index a712e574..b92af815 100644
--- a/docs/accounts-billing/payments-billing.md
+++ b/docs/accounts-billing/payments-billing.md
@@ -5,7 +5,7 @@ This section contains information on the payment methods we accept and how to ch
## Invoices
#### Can I Add A Tax ID (e.g. VAT) to my invoice?
-Unfortunately, at this time we are not able to process Tax IDs.
+If you need to include VAT in your invoices, please reach out to our support team at support@flutterflow.io, and we’ll be happy to assist you with the process.
## Payment Methods
diff --git a/docs/accounts-billing/plan-pricing.md b/docs/accounts-billing/plan-pricing.md
index e187fee8..180d3313 100644
--- a/docs/accounts-billing/plan-pricing.md
+++ b/docs/accounts-billing/plan-pricing.md
@@ -4,13 +4,598 @@ title: Plans & Pricing
tags: []
toc_max_heading_level: 5
sidebar_position: 2
+hide_table_of_contents: true
---
+import Head from '@docusaurus/Head';
+import ThemedImage from '@theme/ThemedImage';
+
+
+
+
+
# Plans & Pricing
-:::note
+:::info
For our most up-to-date information, please visit **[FlutterFlow pricing](https://flutterflow.io/pricing)**.
-:::
-
-:::note
Regional discounts are available, please **[log in to FlutterFlow](https://app.flutterflow.io/)** to see the pricing for your region.
:::
+
+## Pricing Update [June 2025]
+
+FlutterFlow has evolved significantly, from a visual builder to a complete development environment with features like code export, GitHub integration, branching, AI agents, and app deployment tools. As the platform has matured, so have the ways people use it. To better reflect how teams build and scale today, we're introducing updated pricing plans. These updates will help us continue improving the platform, supporting your workflows, and delivering the advanced features needed for building production-ready apps.
+
+
+### What's Changing?
+
+As part of broader improvements to the platform, FlutterFlow is updating its pricing and packaging model effective **August 18, 2025**. The update introduces new plan tiers aligned with team size, simplifies billing, and ensures better alignment between user needs and platform capabilities.
+
+**Key Changes**
+
+- We're retiring our legacy plans: **Standard**, **Pro**, and **Teams** and introducing a new, simplified lineup: **Free**, **Basic**, **Growth**, **Business**. Our Enterprise offering will continue as is, providing advanced features and support for larger teams.
+- If you're already using FlutterFlow, you'll be automatically moved to the new plan that best fits your current team size. No action needed on your part.
+- That said, feature access will look a little different. Some users will gain powerful new capabilities, while others might see a few features move to higher tiers.
+
+
+To understand how each new plan compares, **[view the detailed plan comparison](new-pricing-comparison.md).**
+
+
+
+## FAQS
+
+### General / Timeline
+
+
+
+Who is affected by this pricing change?
+
+
+All current Free, Standard, Pro, and Teams plan users will move to the new structure.
+
+Enterprise customers on custom contracts are not affected by these changes.
+
+
+
+
+
+
+When does the new pricing take effect for me?
+
+
+- For new users, the pricing and packaging will apply immediately on August 18, 2025. After this date, no legacy plans (Standard, Pro, Teams) can be purchased or updated.
+- For existing Free, Standard, Pro, and Teams plan users, billing and feature access will remain unchanged during a **30-day transition period** where you will have the ability to select a new plan. On September 18, 2025, your account will be moved to one of the new plans if no action is taken.
+ - **Important exception:** If you're currently on a Teams plan, you will no longer be able to use your team features on personal projects starting August 18, 2025. To maintain existing Teams plan feature access on those projects, you must either:
+ - Move your personal projects into your Team, or
+ - Convert your current Teams plan to a new Growth or Business plan and purchase a separate Basic plan for your personal work.
+
+- **Note:** All plan updates will take effect at 12:00 AM local time on the specified effective date.
+
+
+
+
+
+
+
+
+Why is FlutterFlow updating its pricing?
+
+
+When we launched FlutterFlow, we had one goal: make it radically easier to build beautiful, powerful digital products. Four years later, we’re a full development platform that goes from idea to app store. We now have collaboration features, AI tools, lots of integrations, branching, development environments, and more, built in.
+
+Now our plans are evolving to reflect that growth. We’ve introduced new features across every tier and restructured our plans to better align with the way people build today and how their needs change as they move from MVP to scaling production apps.
+
+
+
+
+### Plans
+
+
+
+How do the new plans differ from the current plans?
+
+
+The new plans introduce pricing by team size, differentiation between team and personal projects, and more structured feature access to support different types of users and teams as they grow.
+
+
Key changes include:
+
+
New plan tiers based on team size, with clearer limits of number of developers that can work together.
+
Collaboration primarily at the team level to support scalable workflows and controls, with a new option to enable single-project collaboration as an add-on.
+
Updated feature access, with certain advanced features now only available in higher tiers.
+
Plan-based Support levels, with availability varying by plan.
+
Revised pricing structure, with updated USD and INR rates.
+
+
+For a detailed comparison of the current and new plans, including feature breakdown and pricing, please see the **[Detailed Plan Changes](new-pricing-comparison.md)** table above.
+
+
+
+
+
+What is the difference between team projects and personal projects?
+
+
Give you access to all the features of your Growth or Business plan
+
Can be shared with your whole team, or restricted to specific members
+
The team owner always has access to every project in the team
+
+
**Personal projects:**
+
+
Belong only to you; team owners cannot access them
+
Only include the features available in your personal plan
+
Note: If you want to use Growth or Business features by yourself, you can create a team of one
+
+
+To update the collaboration type of a project, go to the Collaboration tab in your project settings and choose from one of the following options: Team Project, Personal Project, or Restricted Team Project
+
+
+
+
+
+Which plan is best suited for different types of users?
+
+
The tiers are designed as a general guide to help highlight which plans tend to work best for different types of use cases, but we know that every user’s needs are different and you’re always welcome to choose the one that works best for you. That said, here’s how we generally recommend thinking about the tiers based on common usage patterns:
Growth: Solo developers or small teams needing advanced functionality.
+
Business: Established teams (3–5 users) ready for advanced development workflows.
+
Enterprise: Larger teams needing advanced security, governance, and collaboration features.
+
+
+
+
+
+How do I know which plan I will be moved to if I do not make a selection before September 18, 2025?
+
+
+If you do not make a selection during the election period (August 18, 2025 - September 17, 2025), your new plan will be automatically determined based on your current **team size**. For example:
+
+
+
Users on the Free plan will remain in the Free plan, but with new feature restrictions.
+
Solo users in Standard will move to the **Basic** plan.
+
Pro plan users and Teams of 2 will move to the **Growth** plan.
+
Teams of 3-5 will move to the **Business** plan.
+
Teams with 6+ users will move to the Business plan and retain their current seat count as of September 18, 2025 for up to 12 months. During this period, no additional seats can be added. After 12 months, you will need to upgrade to an Enterprise plan to continue building with more than 5 team seats.
+
We highly encourage you to begin evaluating your team’s resourcing and expansion needs early, as this plan will not support usage growth beyond the feature limits of the Business tier. Early planning and engaging with our sales team can help ensure a smooth migration, avoid disruption, and prevent any risk of project or data access issues at the 12-month cut-off. To start the conversation, please reach out to sales@flutterflow.io to explore the best solution package for your team.
+
Expert Agencies (approved via **Contra**) will move to the Business plan with Agencies Expansion included.
+
+
+
+
+
+We'll notify you directly in the app and by email before the September 18, 2025 migration, so you'll have a chance to review or adjust your plan if needed. If you're unsure, contact us and we'll help you confirm your new plan
+
+
+
+
+
+Are there any benefits to electing into a new plan vs. being auto-migrated?
+
+
+Yes! By proactively choosing to move to any of the new plans with annual billing during the election period (before September 18, 2025), you will receive **20% off your first year**.
+
+
+
+
+
+Can I stay on my old plan?
+
+
+No. All existing plans will be retired on September 18, 2025, and users will be automatically transitioned to the new plans based on their current team size. This helps us simplify billing, improve feature alignment, and deliver a more consistent experience across all teams.
+
+
+If you’re currently a paying user and would prefer not to be part of the migration to one of the new paid plans, you have two paths:
+
+
+
**Continue building on the Free plan**: you can downgrade your plan to Free, where you will be able to view, edit, and run any 2 existing projects of your choosing inside the editor, but paid‑tier features, deployments, and team seats will be disabled until you upgrade.
+
**Export your code**: download the full Flutter source and assets for each project before September 18, 2025 and continue building locally to retain full ownership of your codebase.
+
+
+If you’d like to review your options or adjust your usage ahead of time, our support team is here to help. You will receive an email confirming the plan your account will move to, but can also confirm by logging into your account after August 18, 2025 to see how your team maps to the new tiers.
+
+
+
+
+
+What's included in the Enterprise plan?
+
+
+The Enterprise plan is built for organizations that need advanced security, scale, and white-glove support while managing production-grade apps across teams. In addition to all features available in lower tiers, Enterprise includes:
+
+
+
Controlled FlutterFlow upgrades through version pinning
+
Unlimited access to automated snapshot backups for project history and rollback
+
Single Sign-On (SSO) and Activity Logging for secure, centralized access
+
Unlimited development environments to mirror staging, QA, and production workflows
+
Advanced accessibility features to meet regulatory requirements
+
No automatic right for FlutterFlow to use your logo
+
Live and dedicated technical support, plus access to custom engineering solutions when needed
+
+
+To learn more or explore a custom Enterprise solution for your team, please reach out to sales@flutterflow.io – we'd be happy to walk you through options that match your scale and needs.
+
+1. No, your current apps will continue to function and remain deployed, though access to certain features may change depending on your new plan tier starting September 18, 2025\.
+2. If you elect into a new plan during the election period before September 18, 2025, those feature changes will take effect as soon as your new plan becomes active.
+
+
+
+
+
+
+What happens to features I already use but are not part of my new plan?
+
+
+
+ Access to features will be updated according to your new plan beginning September 18, 2025. If you're currently using a feature that is moving to a higher tier, there are two possible outcomes:
+
+
+ Build-time features (like activity logging, automated testing, or Figma Frame imports) will no longer be accessible. You’ll see an upgrade prompt if you attempt to use them.
+
+
+ Run-time features (like API endpoints, branching, GitHub integration, or dev environments) will be grandfathered and continue to work as-is, but you won’t be able to create additional instances beyond what you already have. For example:
+
+
+ If you are currently building on a Free plan with 3 API endpoints, you can continue editing them, but won’t be able to add a 4th without upgrading to a paid plan.
+
+
+ If you’ve used branching or added multiple development environments and currently exceed your new plan limits, those remain active but you’ll be prompted to upgrade if you try to add more.
+
+
+
+
+
+
+ This approach ensures existing work isn’t disrupted, while still aligning future access with your selected plan.
+
+
+
+
+
+
+### Free Users
+
+
+
+I am a Free user and I will lose access to technical support. Where else can I look to for help when building?
+
+
+
+ Starting August 18, 2025 for new users and September 18, 2025 for existing users, 1:1 support will no longer be included with the Free plan. However, we offer a collection of self-serve resources to help you continue building with confidence:
+
+
+ Our Help Center at docs.flutterflow.io offers a free collection of step-by-step guides on how to build, get started, and make the most of FlutterFlow’s features.
+
+
+ We are also launching new troubleshooting guides to help you resolve common issues and workflows.
+
+
+ Plus, a new AI-powered assistant will help you quickly find answers and relevant resources within the Help Center.
+
+
+
+
+ You can turn to our Community Forum to ask questions, share learnings, and get help from other FlutterFlow builders.
+
+
+ We also offer free educational content via our YouTube channel to support your learning and skill development.
+
+
+
+
+ These resources are designed to help all users succeed without needing to rely on 1:1 technical support.
+
+
+ Our Support team will still be available at support@flutterflow.io to all users to assist with billing or account-related issues.
+
+
+
+
+
+
+
+
+
+I am a Free user and have more than 2 projects – what will happen to them?
+
+
+
+ Starting September 18, 2025, all personal Free plan projects will be archived until you actively select two to keep editable. This selection is permanent and cannot be changed afterwards. All other projects will be archived – they'll still appear on your dashboard, and published apps will remain live, but you won't be able to open, edit, or publish updates unless you upgrade.
+
+
+ **Marketplace exception:** Existing Free plan projects published to the Marketplace prior to August 18, 2025 will not count toward your 2-project limit. If a project is later removed from Marketplace and you exceed the limit, it will be automatically archived.
+
+
+
+
+ For users on a team-based plan but not on a personal paid plan, this 2-project selection requirement only applies to your personal projects. You will still be able to edit any projects that belong to your team.
+
+
+ We've set this policy to ensure everyone can explore FlutterFlow for free while keeping heavy usage sustainable. We won't remove any of your existing projects. They're safe and accessible whenever you decide to upgrade.
+
+
+
+
+
+
+Can I still deploy my existing FlutterFlow apps if I stay on the Free Plan with >2 projects?
+
+
+Any existing projects already live will remain deployed, even if you have more than 2 projects currently deployed. However, on the new Free plan, you’ll be limited to editing and publishing updates to at most 2 active projects. All other projects will remain deployed, but you won’t be able to make changes or redeploy them unless you upgrade to a paid plan.
+
+
+
+
+
+What if I delete one of my 2 active projects?
+
+
+If you delete one of your active projects, we’ll automatically unarchive your most recently edited archived project to replace it.
+
+
+If you only had 2 projects total and delete one, you’ll be able to create a new project instead.
+
+
+
+### Teams (Growth/Business)
+
+
+
+What happens to projects with multiple collaborators?
+
+
+Starting September 18, 2025, all project collaboration must occur within a team (Growth or Business). This means:
+
+
+
Team projects. Everyone on your team keeps full edit access. Any project collaborator who is not a paid seat on your team will be switched to view-only access at the project level until they’re added as a paid team member.
+
Projects not associated with a team. The project owner keeps full edit access and all other project collaborators become view-only members on that project. To keep editing together, move the project into a team and invite those collaborators as team members.
+
Solo projects: If you are the only editor, nothing changes. You retain full edit access.
+
+
+Note: If you choose to migrate to a new paid plan before September 18, 2025, any collaborators not on your team will immediately move to view-only access at the time of conversion.
+
+
+
+
+
+
+I’m currently on a Teams plan and want to change the number of users. Can I still do this on or after August 18, 2025?
+
+
+No. As a part of the existing Teams plan retirement, team size will be locked on August 18, 2025. To adjust your team size after that date, please transition to one of the new plans (Growth or Business).
+
+
+
+
+
+I am currently on a Teams plan with 6+ users and do not want to migrate to the Enterprise plan – how do I stay on the Business tier and how will I be charged?
+
+
+- Teams with more than 5 users who do not wish to move yet to an Enterprise contract can continue on the Business tier under a transitional pricing structure. These teams will be billed at the standard Business tier seat pricing and then $85/seat/month for each additional seat over 5. Pricing will be based on the number of users in the team as of September 18, 2025 and billed on a monthly basis.
+
+
+- This option allows larger retail teams to continue operating under the Business feature set without immediate contract negotiation, but will be available only to existing 6+ seat teams for 12 months from September 18, 2025 through September 18, 2026 to ensure continuity without immediate contract negotiation.
+
+
+- Note: Your seat count will be locked based on your team size as of September 18, 2025. You may reduce seats later, but will not be able to add more or expand beyond the feature set and usage limits of the current Business tier (except for any run-time features already in use that are grandfathered).
+
+
+However, if you would like to maintain a single account, collaboration across all of your team members, enterprise level features and support, please reach out to sales@flutterflow.io.
+
+
+
+
+
+Can I belong to multiple teams? How will that be billed?
+
+
+Yes, starting August 18, 2025, users will be able to belong to multiple teams in FlutterFlow in the new plans – this is a new capability as part of our updated team and collaboration structure. Each team is treated as a separate billing entity, with its own plan, users, and usage limits.
+
+
+If you are added as an editor on more than one team, you will count toward the seat total on each of those teams, and each team will manage your seat and billing as part of their own subscription. You will not be billed individually – all billing remains centralized at the team level.
+
+
+Note: you can also be added as a view-only collaborator on projects that are a part of different teams. View-only collaborators do not count toward any seat limits or billing.
+
+
+
+
+
+Can I share projects across multiple teams?
+
+
+- No, projects cannot be shared across multiple teams. Each project belongs to at most one team, and access is managed within that team’s structure.
+- If you want someone from another team to collaborate on a project, they must be invited into your team as an editor or granted access using a Single Project Collaborator Pass.
+
+
+
+
+
+What if I want to continue collaborating with project collaborators who are not on a Teams plan with me?
+
+
+- With the new pricing model, collaboration is only supported within shared Teams plans. This means that to work together on a project, all collaborators must be part of the same Growth, Business, or Enterprise team. However, users can now be members of multiple teams at the same time, which allows you to create separate teams for different projects, depending on who you need to collaborate with.
+- Project-level collaboration (where individuals outside your team could be added to specific projects) is being phased out to simplify permissions, ensure security, and support shared billing.
+- If you would like to continue collaborating:
+ - You can invite others to join your team (additional seats may require an upgrade depending on your plan).
+ - Or, they can create a new team and invite you, depending on who should own billing and project access.
+ - **New:** If you're on a Growth or Business plan, you may also purchase Single Project Collaborator passes, which allows you to grant another paid user access to a single project without adding them to your full team. Each pass is $15/month and can be reassigned to different collaborators or projects as needed. You can purchase up to 4 (Growth) or up to 10 (Business). This collaborator must also be on a paid plan to be eligible to be a single project collaborator.
+- This change ensures that every project has clear ownership, consistent permissions, and a scalable path for team-based collaboration.
+
+
+
+
+
+
+I build apps for clients (agency/freelancer). What plan should I choose?
+
+
+
+ We will now offer multiple plan options to support agencies of all sizes – whether you’re a solo freelancer, a fast-growing studio, or an established consultancy. We believe the best path depends on your team size and how you prefer to work with your clients:
+
+
+ Solo freelancers or small agencies (1-5 developers)
+
+
+ We recommend the Business plan, which supports up to 5 team members with advanced features like branching and access control.
+
+
+
+
+ Agencies with more than 5 developers:
+
+
+ If your client plans to manage the code:
+
+
+ We recommend encouraging your client to purchase their own Business or Enterprise plan and then invite your agency developers to join, either as Team members or as collaborators (with a collaborator pass). To learn more about our Enterprise offering, they can reach out to sales@flutterflow.io.
+
+
+
+
+ If you intend to maintain the code on behalf of your client:
+
+
+ You may qualify for our new Agencies Expansion package, coming out with the Business plan and available to all verified FlutterFlow Expert Agencies.
+
+
+ As part of the add-on, you can:
+
+
Continue to purchase additional seats beyond the 5 included in Business at $85/seat/month
+
And, continue to invite additional paid users to specific projects without requiring them to be team members via Single Project Collaborator Passes.
+
+
+
+ To become eligible now, you can apply to be an Expert Agency on our Contra page. Existing Expert Agencies listed on Contra will be pre-approved to select the Agencies Expansion package starting August 18, 2025.
+
+
+
+
+
+
+
+
+
+
+
+You can transfer ownership of projects between yourself and your client. To transfer a project to a client, simply add them as a collaborator using a pass, transfer ownership, and then remove them and the pass if no longer needed after the handoff.
+
+
+
+
+
+### Billing
+
+
+
+How will my billing cycle be affected when I move to the new plan?
+
+
+To ensure a smooth transition, billing changes will align with your existing billing cycle:
+
+
+
You will stay on your current pricing until your next billing renewal (monthly or annual). For example:
+
+
If your monthly billing date is September 3, 2025, your features will switch to the new plan on September 18, 2025 (or earlier if you elect to switch), but new pricing will apply starting your next billing cycle on October 3, 2025.
+
If you’re on an annual plan, your price won’t change until your next annual renewal. After that, the new pricing will apply for the following 12 months.
+
+
You will have the option to upgrade early to the new pricing plan if you choose, with any remaining credit from your current plan applied toward the new plan.
+
+
+If you are currently on an annual plan and choose to cancel your subscription during the transition period (August 18, 2025 - September 17, 2025), you will be eligible for a pro-rated refund. This is to account for any features you may have prepaid for under your current plan that will no longer be available once the new plans take effect.
+
+
+If you have questions about your billing, please contact support at support@flutterflow.io
+
+
+
+
+
+Will there still be a discount for paying annually on the new plans?
+
+
+Yes, we will continue offering a meaningful discount on all new plans when billed annually instead of monthly – typically around 25%. This discount remains available regardless of your location or currency and reflects 12 months of service at a reduced monthly rate.
+
+
+Note: Annual billing is not available for Business teams with greater than 5 seats on transitional pricing, as this is intended to support existing users during their migration period.
+
+
+
+
+
+How will prices change with respect to country discounts?
+
+
+Localized pricing will continue where applicable. If you’re in a supported region, your billing will reflect adjusted rates at existing discounts based on your location.
+
+
+
+
+
+What if I am billed in INR right now?
+
+
+If your account is billed in INR, your pricing will follow our localized rates:
+
+
+
**Basic Plan:** ₹1,300 INR per seat per month.
+
**Growth Plan:** ₹2,650 INR for the first seat, and ₹1,850 INR for the second seat per month.
+
**Business Plan:** ₹5,100 INR for the first seat, and ₹2,850 INR each for seats 2–5 per month.
+
Agencies Expansion: Each additional seat beyond 5 at ₹2,850 INR/month.
+
+
+All INR pricing reflects the same features and plan structures as USD pricing, with adjustments for local purchasing power.
+
+
+
+### Miscellaneous
+
+
+
+I have special access. How will this change impact me?
+
+
+- If you currently have Special Access (such as through a community program, academic use, or other exception), your FlutterFlow experience will remain unchanged. You will continue to have the same benefits provided under your existing Special Access status, which is separate from the new plan structure.
+- **Note:**
+ - Users with Special Access can collaborate with an unlimited number of users, but those collaborators must also have either Special Access or be on a paid teams (Growth or Business) plan.
+ - Special Access may be granted at either the individual or team level. If only the individual has Special Access, they will not have full feature access when working on team projects unless the team also has Special Access.
+
+
+
+
+
+
+Will the referral program still exist with the new plans, now that the Pro plan is going away?
+
+
+- With the retirement of the Pro plan, our current referral program will also be sunset. This means any active referral discounts will end at your next renewal. However, any earned referral credits will remain in your account and can be redeemed for equivalent free months of the new Growth plan.
+- We’re actively exploring what a future referral or incentive program could look like under the new pricing model, with the goal of better supporting and rewarding our community as we grow.
+
+
+
+
+
+
+Are there any changes to DreamFlow plans as well?
+
+
+Dreamflow is a separate product and Dreamflow plans are not affected by this plan update.
+
+
diff --git a/docs/accounts-billing/privacy-terms-of-service.md b/docs/accounts-billing/privacy-terms-of-service.md
index 0adeadbc..2e956362 100644
--- a/docs/accounts-billing/privacy-terms-of-service.md
+++ b/docs/accounts-billing/privacy-terms-of-service.md
@@ -12,7 +12,7 @@ To request deletion of your personal data, please reach out to our support team
To unsubscribe from FlutterFlow emails, please click the “Unsubscribe” link in the footer of our emails.
### Where can I view your Privacy Policy?
-You can review the most recent version of our Privacy Policy here.
+You can review the most recent version of our Privacy Policy [on the website](https://www.flutterflow.io/privacy).
### Where can I view your Terms of Service (ToS)?
-You can review the most recent version of our Terms of Service here.
\ No newline at end of file
+You can review the most recent version of our Terms of Service [linked on the website](https://www.flutterflow.io/tos).
\ No newline at end of file
diff --git a/docs/accounts-billing/referral-program.md b/docs/accounts-billing/referral-program.md
index c6203012..45c091da 100644
--- a/docs/accounts-billing/referral-program.md
+++ b/docs/accounts-billing/referral-program.md
@@ -1,37 +1,8 @@
# Referral Program
-Everyone with a FlutterFlow account has a personal referral code to share with friends and colleagues. For every referral that subscribes, you will receive one month of FlutterFlow Pro credited to your account.
+:::warning[Discontinued]
+With the retirement of the Pro plan, the existing referral program has been discontinued. Any active referral discounts will end at your next renewal. However, referral credits you’ve already earned will remain in your account and can be redeemed for free months on the new Growth plan.
-In order to receive this reward, the person you referred will need to:
-
-1. Click your referral link and create a FlutterFlow account.
-2. Complete purchase of a FlutterFlow Standard or Pro Plan (after their trial period ends).
-
-You are only eligible for one referral reward per individual. If your referral has already signed up for FlutterFlow, this will not be eligible for a reward.
-
-:::info
-In order to account for refunds and cancellations, referral credits will be processed 45 days after your referral's first payment.
+We are also exploring new referral and incentive programs to better support and reward our community under the updated pricing model.
:::
-
-### How To Find And Share Your Referral Code
-
-Your personal referral code is listed on your [My Account Page](https://app.flutterflow.io/account).
-
-1. Navigate to the [My Account Page](https://app.flutterflow.io/account) and scroll down to the **Referrals** section.
-2. To copy your referral code, press the copy icon.
-
-
-
-### How To Track How Many People Have Signed Up Using Your Referral Code
-
-You can track your referrals in the **Referrals** section on the [My Account Page](https://app.flutterflow.io/account). Here you will see:
-
-* **Signed Up:** How many people have signed up for FluterFlow using your referral link.
-* **Subscribed:** How many people have subscribed to FlutterFlow Pro or Standard using your referral link.
-
-
-
-### I forgot to sign-up using the referral link, can I add this after creating account?
-
-Unfortunately, we are unable to retroactively change this after your account has been created.
\ No newline at end of file
diff --git a/docs/accounts-billing/subscriptions/flutterflow-for-teams.md b/docs/accounts-billing/subscriptions/flutterflow-for-teams.md
deleted file mode 100644
index 536b2cd0..00000000
--- a/docs/accounts-billing/subscriptions/flutterflow-for-teams.md
+++ /dev/null
@@ -1,107 +0,0 @@
----
-slug: subscriptions/flutterflow-teams
-title: FlutterFlow for Teams
-tags: []
-toc_max_heading_level: 5
-sidebar_position: 1
----
-
-
-# FlutterFlow For Teams
-
-## How do I upgrade to a Teams plan?
-
-:::info
-Teams plans are annual plans and can have up to 20 team members. For an account with more than 20 members, please reach out to sales@flutterflow.io
-:::
-
-To change your account to a Teams Plan, please follow these steps:
-
-1. After logging into your FlutterFlow account, head to your account [Dashboard](https://app.flutterflow.io/) and select **My Organization** from the top right.
-2. Select **Create Team**.
-
-
-
-
-
-
-
-3. Next, enter your organization name (e.g. FlutterFlow) and your website/email domain (e.g. flutterflow.io) and select **Create Team**.
-
-
-
-## How do I add users to my *Teams* plan?
-
-To add users to your Teams plan, you will need to complete two steps:
-
-### 1. Adding seats to your organization
-
-A seat grants one user the ability to use Flutterflow. You will need to purchase a seat for each team member that you would like to add to your Team. To do so:
-
-1. From the **My Organization** tab, select **Subscribe**.
-
-
-
-2. A popup will appear, select the number of seats (subscriptions) and Billing Cycle Additional users can be added to your team at any time. **You can select from a monthly or annual plan.**
-
-
-
-
-3. A checkout page will appear for you to complete the purchase. **Please note: this can take a few seconds to load.** If you want to add more seats at a later time, you can do so by selecting the Add Seats button.
-
-
-
-:::tip
-You can see how many seats you have used here
-
-
-:::
-
-
-### 2. Inviting users to your Team
-
-:::warning
-If you add an existing Flutterflow user to your Teams plan, they will need to manually cancel their subscription using these [**instructions**](subscriptions.md#cancel-my-plan). Once this is completed, please reach out to support@flutterflow.io or chat to process the refund for any remaining time on your monthly plan. We're working on automating this process soon!
-:::
-
-1. After you've purchased your seats, this will be reflected in the **Seats** section under **My Organization** (example below).
-2. To invite a new user, select the **Invite User(s)** button.
-
-
-
-3. A popup will appear, type the email of the user you would like to add.
-4. If they are not an existing user of FlutterFlow, they will be sent an invitation to join.
-
-:::note
-* Teams plans do not include a trial period.
-* You must verify your email before inviting users.
-:::
-
-
-
-
-## Delete users from Teams plan
-
-To remove a user from the teams, click on the **red cancel button** and select **Yes** in the popup to confirm the removal.
-
-
-
- 
- Delete users from Teams Plan
-
-
-
-
- 
- Confirmation Popup
-
-
----
-
-## FAQs
-
-#### Can I reduce my Teams plan to one seat?
-
-No, you can't. The minimum requirement is two seats, which includes one for the owner's pro plan + an additional team seat.
-
-
diff --git a/docs/accounts-billing/subscriptions/more-subscription-faqs.md b/docs/accounts-billing/subscriptions/more-subscription-faqs.md
deleted file mode 100644
index b3d452a3..00000000
--- a/docs/accounts-billing/subscriptions/more-subscription-faqs.md
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-# Other Subscription Questions
-
-### When Will My Plan Renew / When Will I Be Charged?
-
-You can view the next billing cycle date in the "My Plan" section of the [Flutterflow Account Page](https://app.flutterflow.io/account).
-
-
- 
- The next billing cycle date for this account is August 31, 2021
-
-
-
-
-### Do Subscriptions Renew Automatically?
-
-Yes, our subscriptions renew automatically to avoid disrupting your app development. Monthly subscriptions renew on the same day each month (typically the day you subscribed).
-
-### Can I Pause My Subscription?
-
-We do not currently offer the option to pause your subscription.
-
-### Can I Transfer My Subscription To Another User?
-
-We are unable to transfer a paid FlutterFlow subscription to another FlutterFlow account.
-
-### If I have a paid plan will project collaborators be able to use paid features?
-
-FlutterFlow subscriptions are seat based. A user added to your project will only have access to the features of their account plan. In order to access paid features, each individual user will need to have a paid plan.
-
-### If I upgrade from Standard Plan to Pro Plan in the middle of my billing cycle, will I be charged for both plans?
-
-Upgrades are automatic, so the system will count the remaining days from the Standard, and reduce it from the Pro Plan price.
-
-For example, if you have paid $42 for Standard and you have 15 days remaining in the billing cycle, then on upgrading to Pro(let's say priced at $70) you will eventually pay $(70-21) = $49.
-
-:::info
-FlutterFlow provides different pricing options depending on your region. To see the exact prices for your area, visit the [**Plans & Pricing**](../plan-pricing.md) page in our documentation.
-:::
\ No newline at end of file
diff --git a/docs/accounts-billing/refund.md b/docs/accounts-billing/subscriptions/refund.md
similarity index 88%
rename from docs/accounts-billing/refund.md
rename to docs/accounts-billing/subscriptions/refund.md
index b854f0f8..4c4dde27 100644
--- a/docs/accounts-billing/refund.md
+++ b/docs/accounts-billing/subscriptions/refund.md
@@ -8,6 +8,6 @@ sidebar_position: 4
# Refunds
-If you're not happy with your FlutterFlow subscription, you can [cancel at any time](subscriptions/subscriptions.md#cancel-my-plan).
+If you're not happy with your FlutterFlow subscription, you can [cancel at any time](./subscriptions.md#cancel-my-plan).
However, there are no refunds for cancellation. In the event that the Company suspends or terminates your Account or these Terms, you understand and agree that you shall receive no refund, whether for any unused time on a subscription, any license or subscription fees for any portion of the Service, any content or data associated with your User Account, or for anything else.
\ No newline at end of file
diff --git a/docs/accounts-billing/subscriptions/subscriptions.md b/docs/accounts-billing/subscriptions/subscriptions.md
index 5f95d27a..c757b2cf 100644
--- a/docs/accounts-billing/subscriptions/subscriptions.md
+++ b/docs/accounts-billing/subscriptions/subscriptions.md
@@ -3,76 +3,113 @@ slug: subscriptions
title: Subscriptions
tags: []
toc_max_heading_level: 5
-sidebar_position: 3
+sidebar_position: 0
---
# Subscriptions
-This section contains information on free trials, changing your plan, and other subscription questions.
+This section provides information on free trials, plan changes, and other subscription-related questions.
## Free Trials
-All paid plans come with a free 14-day trial.
-### How do I Start A Free Trial?
-To start a free trial, please follow these steps:
+The first paid plan you purchase will come with a free 14-day trial. For 14 days, you will have access to the features of the plan you selected before you are charged. If you can cancel your subscription during this 14-day trial, you will not be charged.
+
+:::info
-1. From flutterflow.io select Create Account in the top right corner.
-2. Enter your name, email address, and password and select Create Account.
-3. Select Upgrade at the top of the screen.
-4. Enter your billing and payment information and select Subscribe.
+The 14-day trial applies only to your first paid plan. Any later plan (Basic, Growth, or Business) won’t include a trial, even if the first plan is still in trial.
-### What Happens At The End of The Trial Period?
-At the end of your trial period, your payment method will be charged. You cancel at any time during the trial period.
+:::
+### How do I start a free trial?
-## Upgrade Plan
+To start a free trial, please follow these steps:
+
+1. Navigate to [app.flutterflow.io](http://app.flutterflow.io/)
+2. Click the “Create Account” text and enter your name, email address, and password. Then press the “Create Account” button to create your account.
+3. Validate your email address by clicking on the link in the message sent to the email address you provided.
+4. To start trialing on a **Basic** plan, click on your profile picture in the bottom left corner, then click “Upgrade Plan.” Select “Start Free Trial” and fill out and submit the form with your payment information.
+5. To instead start trialing on a **Growth** or **Business** plan, click “My Team”, and create a team. Then press the “Subscribe” button, select your desired plan and number of seats, click on “Start Free Trial”, and fill out and submit the form with your payment information.
+### What happens at the end of the trial period?
+At the end of your trial period, your payment method will be charged. You can cancel at any time during the trial period.
+
+## Upgrade Plan
### How do I upgrade my plan?
-To upgrade your plan type, please follow these steps:
-1. After logging into your FlutterFlow, select “Account” from the top right.
-2. In the My Plan section, select Change Plan.
-3. Select the button under the plan you would like to upgrade to.
-4. Enter your payment information and select Subscribe. The main FlutterFlow page will open.
+If you would like to upgrade from a Basic plan, follow the steps to purchase a new Growth or Business plan, and then cancel your existing Basic plan if you no longer want it.
-### How do I check what plan I am subscribed to?
-To view your plan details, go to the [**FlutterFlow Account Page**](https://app.flutterflow.io/account) and select **Manage Billing.**
+To upgrade a team directly from a Growth plan to a Business plan, please follow these steps:
-The **Current Plan** section will show which plan you are subscribed to.
+1. Click on “My Team” and select the team that has the Growth plan you wish to upgrade.
+2. Click on “Upgrade to Business Plan” near the top right corner.
+3. View the invoice and confirm that you are willing to be charged this amount for the upgrade.
-:::warning[Teams Plan]
-For information on the Teams plan, please use [**this link**](flutterflow-for-teams.md).
-:::
+### How do I check what plan I am subscribed to?
+To view your plan details, go to the [**FlutterFlow Account Page**](https://app.flutterflow.io/account) and select **Manage Billing.** The **Current Plan** section will show which plan(s) you are subscribed to.
## Downgrade Plan
+
### How to downgrade?
-If you wish to downgrade from Pro to Standard or from Teams to Pro or Standard, you should cancel your existing plan and then sign up for the new one after it expires.
-### What happens when I downgrade to the free plan? Will my apps be deleted?
-You will still be able to access the apps you created and make changes inside FlutterFlow.
+If you wish to downgrade from Growth to Basic or from Business to Growth or Basic, you should cancel your existing plan and then sign up for the new one after it expires.
-However, you won't be able to access any premium features such as custom APIs, GitHub integration, and code downloads. Additionally, premium features will no longer work in Preview and Run Mode.
+### What happens when I downgrade to the free plan? Will my projects be deleted?
+On the free plan, you will be restricted to two projects. Any other projects won't be deleted, but will be archived and made accessible if you return to any paid plan.
## Cancel My Plan
+
You can cancel your plan at any time. You will have access to the paid features until your next billing cycle date.
Please follow these steps to cancel your account:
-1. Log in to FlutterFlow and go to the Account page.
-2. Select **Change Plan** from My Plan.
-3. Under your plan type, select **Cancel Plan.**
-4. Complete the Cancellation Survey and select **Cancel Subscription.**
-5. You will be taken to a new page. Under Current Plan select **Cancel**. A popup will appear, select Cancel.
+1. Log in to FlutterFlow and click on your profile picture to go to the Account page.
+2. Find the plan you want to cancel, and select **Cancel Plan**.
+3. Complete the Cancellation Survey and select **Cancel Subscription.**
+
+:::warning
+
+Your FlutterFlow account can have multiple team plans and a personal plan at the same time; you must cancel each plan manually. Canceling one plan does not automatically cancel any other active plan.
-:::note
-When you cancel a paid plan, your account will be converted to a Free account.
:::
-You can confirm your account has been canceled from the My Plan section of the **[Account Page](https://app.flutterflow.io/account)**. Your account will now say **ends at** vs. **renews at.**
+## Other Subscription Questions
+
+### When will my plan renew / When will I be charged?
+
+You can view the next billing cycle date in the "My Plan" section of the [Flutterflow Account Page](https://app.flutterflow.io/account).
+
+
+
+The next billing cycle date for this plan is September 12, 2025.
+
+### Do subscriptions renew automatically?
+
+Yes, our subscriptions renew automatically to avoid disrupting your app development. Monthly subscriptions renew on the same day each month (typically the day you subscribed).
+
+### Can I pause my subscription?
+
+We do not currently offer the option to pause your subscription.
+
+### Can I transfer my subscription to another user?
+
+We are unable to transfer a paid FlutterFlow subscription to another FlutterFlow account.
+
+### If I have a paid plan, will project collaborators be able to use paid features?
+
+No. Having a paid plan yourself does not give your project collaborators access to paid features. Starting **September 17, 2025**, all collaboration must happen within a **Growth, Business, or Enterprise plan**, and every collaborator must have a **paid seat** in that team to have full edit access. Anyone not on your team will be switched to **view-only** until added as a paid team member.
+
+### If I upgrade from the Growth Plan to the Business Plan in the middle of my billing cycle, will I be charged for both plans?
+
+Upgrades are automatic, so the system will count the remaining days from the Growth plan and reduce it from the Business Plan price.
+
+For example, if you paid $80 for Growth and you have 15 days remaining in the billing cycle, then on upgrading to Business (let's say priced at $150), you will eventually pay $(150-40) = $110.
+
+:::info
-
+FlutterFlow provides different pricing options depending on your region. To see the exact prices for your area, visit the [**Plans & Pricing**](../plan-pricing.md) page.
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/adding-customization/cloud-functions.md b/docs/ff-concepts/adding-customization/cloud-functions.md
index 216a8971..fbd34dc3 100644
--- a/docs/ff-concepts/adding-customization/cloud-functions.md
+++ b/docs/ff-concepts/adding-customization/cloud-functions.md
@@ -245,6 +245,44 @@ For this example, we'll use the result (i.e., generated logo image URL) and set
+## Testing Cloud Functions in Google Cloud console
+
+The Google Cloud console has built-in functionality to allow you to trigger a Cloud Function for testing. This means that after deploying Cloud Functions, you can test them without writing to Firestore (either from FlutterFlow or otherwise).
+
+Here's how to test FlutterFlow's `sendUserPushNotificationsTrigger` function in the Google Cloud console:
+
+1. Open your browser and navigate to the following URL:
+`https://console.cloud.google.com/functions/details/us-central1/sendUserPushNotificationsTrigger?env=gen1&project=&tab=testing`
+\
+ In here:
+ - Replace `` with your GCP or Firebase project.
+ - If you want to test a different Cloud Function, update `sendUserPushNotificationsTrigger` with the relevant cloud function name.
+2. Paste the following JSON into the Configure Triggering Event text area.
+ - If you want to test a different Cloud Function, update `sendUserPushNotificationsTrigger` with the relevant cloud function name.
+ ```json
+ {
+ "value": {
+ "name": "projects//databases/(default)/documents/sendUserPushNotificationsTrigger/",
+ "fields": {
+ "scheduled_time": { "stringValue": "" },
+ "initial_page_name": { "stringValue": "" },
+ "notification_title": { "stringValue": "Your friends are missing you!" },
+ "notification_text": { "stringValue": "Please come back to Nanochat" },
+ "user_refs": { "stringValue": "users/VXu6EvFMl5M8KMXriYRvFEWTFHA2" }
+ }
+ }
+ }
+ ```
+3. In the `name` property:
+ - Replace `` with your GCP or Firebase project.
+ - Replace `` with the ID of the document. This document must already exist in Firestore.
+ - If you're testing another function than `sendUserPushNotificationsTrigger`, update `ff_user_push_notifications` with the collection where the document is written.
+4. Update the values under the `fields` property for the message you want to send.
+\
+The `fields` in the example above are for FlutterFlow's built-in `sendUserPushNotificationsTrigger` function. If you're testing a different Cloud Function, you will need to update the `fields` for the code in *that* function.
+5. Click the TEST THE FUNCTION button.
+
+The Cloud Function will now run and gather the relevant entries from Google Cloud Logging.
## FAQs
@@ -282,5 +320,20 @@ If you encounter deployment errors, it may be helpful to check out [this communi
+
+Why am I getting a CORS error when executing my Cloud Function?
+
+The CORS error occurs because the **Access-Control-Allow-Origin** header is missing from the response, preventing your request from being completed. This issue can arise with new Cloud Functions, whether deployed through FlutterFlow or not.
+
+Follow the steps below to fix the issue:
+1. Open your Google Cloud Project's [**Cloud Functions List**](https://console.cloud.google.com/functions/list)
+2. Select the function causing the issue.
+3. Navigate to the **Permissions** tab.
+4. Open the **VIEW BY ROLES** tab.
+5. Ensure there's a row with `Cloud Functions Invoker` with principal set to `allUsers`. If it’s missing, click on the **Grant Access**, add `allUsers` with the `Cloud Functions Invoker` role.
+
+
+
+
diff --git a/docs/ff-concepts/adding-customization/code-file.md b/docs/ff-concepts/adding-customization/code-file.md
new file mode 100644
index 00000000..135b0034
--- /dev/null
+++ b/docs/ff-concepts/adding-customization/code-file.md
@@ -0,0 +1,473 @@
+---
+slug: /concepts/custom-code/code-file
+title: Code File
+description: Learn how to create and use custom classes and enums in FlutterFlow.
+tags: [Code File, Custom Code]
+sidebar_position: 5
+keywords: [FlutterFlow, Custom Classes, Custom Enums, Customizations, Flutter, Dart, Pub.dev]
+---
+
+# Code File
+
+FlutterFlow allows you to add your own custom Dart files with [classes](https://dart.dev/language/classes) and [enums](https://dart.dev/language/enums). This means you can create reusable building blocks to manage your app’s data and logic more easily. Using custom classes, you can create custom data types, use their properties in the UI, call methods in action flows, and much more.
+
+## Key Use Cases
+
+- **Custom Models**: Define your own data models, such as `UserProfile`, `Product`, or `Order`, and use them throughout your app.
+- **Business Logic**: Add reusable utility methods like tax calculations, formatting, or conditional evaluations.
+- **Reusable Enums**: Define enums and use them in UI conditions and dropdowns.
+
+:::warning[Limitations]
+
+- **No Generics:** Classes with generic types (e.g., `class ApiResponse {}`) are currently not supported.
+- **No Function-Typed Parameters:** Methods or fields that have function types as parameters or fields are ignored (e.g., void Function(int) onTap).
+- **No Extensions:** Dart Extensions (e.g., `extension StringX on String { … }`) are not supported yet.
+
+:::
+
+## Create Custom Class
+
+To add a custom class, go to the **Custom Code** from the left navigation menu, click **plus (+)** button, and select **Code File**. Set the name of the file, add your code, and hit the **Save** button. Now, you must **validate** your code in the editor to catch basic syntax errors. If there are no errors, click the **Parse** button. FlutterFlow will scan your code and automatically detect supported classes and enums.
+
+Here’s an example of adding a `Review` custom class:
+
+
+
+
+
+
+Here's the code snippet of the `Review` custom class:
+
+```jsx
+class Review {
+ String id;
+ String productId;
+ String userId;
+ String userName;
+ String comment;
+ double rating; // out of 5
+ ReviewStatus reviewStatus;
+ DateTime date;
+ int helpfulCount = 0;
+
+ Review(
+ this.id,
+ this.productId,
+ this.userId,
+ this.userName,
+ this.comment,
+ this.rating,
+ this.reviewStatus,
+ this.date,
+ );
+
+ // Method: Get a short version of the comment
+ String shortComment() {
+ if (comment.length <= 50) return comment;
+ return comment.substring(0, 47) + "...";
+ }
+
+ // Method: Get formatted date as string (e.g., "2024-05-22")
+ String formattedDate() {
+ return "${date.year}-${_twoDigits(date.month)}-${_twoDigits(date.day)}";
+ }
+
+ String _twoDigits(int n) {
+ return n >= 10 ? "$n" : "0$n";
+ }
+
+ // Method: Check if review is positive (4 stars or more)
+ bool isPositive() {
+ return rating >= 4.0;
+ }
+
+ // Method: Check if review is recent (within last 30 days)
+ bool isRecent() {
+ final now = DateTime.now();
+ return now.difference(date).inDays <= 30;
+ }
+
+ // Method: Mark this review as helpful
+ void markHelpful() {
+ helpfulCount += 1;
+ }
+}
+```
+:::tip
+You can also include import statements and access generated classes within your custom class files. For more details, [**see the examples**](common-examples.md) on how to access generated classes.
+:::
+
+## Create Custom Class Instance
+
+You need to create an instance of a class so you can work with actual data and use the class’s properties and methods in your app. Here’s a simple explanation:
+
+- A **class** is like a blueprint or template. For example, the `Review` class describes what a review is, but doesn’t hold any real review information itself.
+- An **instance** (or “object”) is a real, usable item made from that blueprint. See the code snippet below:
+
+ ```jsx
+ Review review1 = Review(
+ 'r001',
+ 'p123',
+ 'u456',
+ 'Alex Morgan',
+ 'Great quality T-shirt!',
+ 4.5,
+ DateTime(2025, 5, 22),
+ 3,
+ ReviewStatus.approved,
+ );
+ ```
+
+- In FlutterFlow, you will store the instance of the custom class in the [state variables](../../ff-concepts/state-management/state-variables.md#state-variables) of your app, page, or component.
+- You can create multiple instances of the same class, reusing the same structure multiple times, each with different review data.
+
+When you create an instance of a class, you can:
+
+- Store actual review details.
+- Access and update the fields (e.g., `review1.rating` or `review1.comment`).
+- Call methods that do something with that data (e.g., `review1.markHelpful()` or `review1.shortComment()`).
+
+To create an instance of a custom class, first you need to [create a state variable](../../ff-concepts/state-management/state-variables.md#creating-state-variables) (of type Custom Class) that will hold the instance. Then, to create and add the instance to the state variable, open the **Set from Variable** dialog and select **Create Custom Class Instance**. Choose the class you want to use, then select the class name from the **Constructor** dropdown. After that, set values for each of the required fields.
+
+
+
+
+
+
+
+## Using Custom Class
+
+Once the custom class is added successfully, you can access its fields and methods in the Variable Dialog, call its methods in the Action Flow Editor, assign instances to state variables, pass them to page or component parameters, and use enum values in dropdowns or conditionals.
+
+### Custom Class as Data Type
+
+You can select your custom class as a Type for variables, state, or parameters, just like a [Custom Data Type](../../resources/data-representation/custom-data-types.md).
+
+
+
+### Access Fields and Methods
+
+You can use custom class fields to display values directly in the UI, and call its methods in variable dialogs to return a result.
+
+
+
+### Set Field [Action]
+
+Use the **Set Field** action to update a specific property of a custom class instance. For example, you can set `review.comment = 'Great fit and quality!'` when a user updates the review, allowing the UI to reflect the new comment instantly.
+
+
+
+
+
+
+### Call Method [Action]
+
+Use the **Call Method** action to invoke a method defined in your custom class. For instance, if your `Comment` class has a `markHelpful()` method, you can trigger it when a user taps a “Helpful” button to record the interaction.
+
+
+
+
+
+
+## Using Static Members
+
+Sometimes, you may want to define fields and methods that are shared across your app. In such cases, `static` fields and methods are ideal. Because they're tied to the class rather than an instance, static members are accessible globally, for example, utilities for formatting, calculations, or global configuration.
+
+This approach is typically used for **stateless utility classes** where shared functionality is needed across the app. For example, look at the class below:
+
+```jsx
+class Utils {
+ static int square(int x) => x * x;
+}
+```
+
+The `Utils` class contains a static method `square` that returns the square of a number without needing to create an object of the class.
+
+Here are couple more examples to understand it better:
+
+- This `StringFormatter` class below provides reusable static methods to capitalize text, convert it to lowercase, or format it in snake_case.
+
+ ```jsx
+ class StringFormatter {
+ static String lastFormatted = '';
+ static int formatCount = 0;
+
+ static String capitalize(String input) =>
+ input[0].toUpperCase() + input.substring(1);
+
+ static String toLowerCase(String input) => input.toLowerCase();
+
+ static String toSnakeCase(String input) =>
+ input.replaceAll(' ', '_').toLowerCase();
+ }
+ ```
+
+- The `MathHelper` class offers handy static methods to calculate tax, apply discounts, find percentages, and round off numbers.
+
+ ```jsx
+ class MathHelper {
+ static double calculateTax(double amount) => amount * 0.18;
+
+ static double applyDiscount(double amount, double discountPercent) =>
+ amount - (amount * discountPercent / 100);
+
+ static double calculatePercentage(double part, double total) =>
+ (part / total) * 100;
+
+ static int roundOff(double value) => value.round();
+ }
+ ```
+
+:::tip
+
+You can mix both **static** and **instance** members in a single class. Static members are shared across all instances, while instance members hold data specific to each object. For example, look at the class below:
+
+```jsx
+class Review {
+ static List flaggedWords = ['bad', 'spam', 'fake'];
+
+ String id;
+ String userId;
+ String comment;
+ int helpfulCount = 0;
+
+ Review(
+ this.id,
+ this.userId,
+ this.comment
+ );
+
+ static bool isCommentAppropriate(String input) {
+ return !flaggedWords.any((word) => input.toLowerCase().contains(word));
+ }
+
+ void markHelpful() {
+ helpfulCount += 1;
+ }
+}
+```
+
+- `flaggedWords` is a static list used across all reviews.
+- `isCommentAppropriate()` is a static method that can be used without creating a `Review` instance, useful for validating comments before saving them.
+
+:::
+
+:::warning
+
+Using static members are powerful, but they should be used carefully. Overusing static methods can lead to less flexible code and potential issues, especially when the logic requires access to state or needs to evolve over time. Stick to static methods only when the logic is truly independent and doesn’t rely on instance-specific data.
+
+:::
+
+### Access Static Fields and Methods
+
+You can access the static class data and methods directly via the ****Set from Variable**** menu.
+
+
+
+### Set Static Field [Action]
+
+Use the **Set Static Field** action to update a static field on a custom class. For example, if you have a class `MathHelper` with a static field `amount`, you can set it using an input value when a user enters a price. This allows you to store that value globally and use it across different calculations.
+
+
+
+
+
+
+
+### Call Static Method [Action]
+
+Use the **Call Static Method** action to run a static method of your class. For instance, you can call `MathHelper.calculateTax(amount)` to compute tax on a given amount during a checkout action, without needing to create an instance of the class.
+
+
+
+
+
+
+## Custom Enums
+
+Similar to how you add a custom class, you can also add Custom Enums in your app. [Enums](../../resources/data-representation/enums.md) are a great way to define a fixed set of values, such as user roles, order statuses, or content types. Once parsed, these enums become available throughout your app and can be used in dropdowns, conditionals, and UI bindings.
+
+For example, you could define an enum called `ReviewStatus` with values like `pending`, `approved`, and `rejected`. Here's the code snippet for it:
+
+```jsx
+enum ReviewStatus {
+ pending,
+ approved,
+ rejected,
+}
+```
+
+
+
+You can access the custom enums from **Set from Variable** menu > **Custom Enum** section. You’ll see your Dart file listed by name. Select the enum you want to use, such as `ReviewStatus`, and then choose the specific value you want to assign.
+
+
+
+
+
+
+
+## Tips & Best Practices
+
+- Keep your custom class files modular and focused; ideally one class per file for better organization and reusability.
+- Avoid advanced Dart features that are not supported by FlutterFlow’s parser, such as generics or function-typed fields.
+- Re-parse your code after making changes to ensure FlutterFlow updates the parsed structure correctly.
+- Document your code with comments to make your custom classes easier to understand and maintain over time.
+
+## FAQs
+
+
+
+Can I add Custom Classes (Code Files) in a Library Project?
+
+
+Yes, you can. When a Library Project is imported, any custom code files you’ve defined will be parsed, and the resulting classes will be available for use in the consuming project.
+
+
\ No newline at end of file
diff --git a/docs/ff-concepts/adding-customization/common-examples.md b/docs/ff-concepts/adding-customization/common-examples.md
index a54b6b59..34b44218 100644
--- a/docs/ff-concepts/adding-customization/common-examples.md
+++ b/docs/ff-concepts/adding-customization/common-examples.md
@@ -35,7 +35,7 @@ import '/auth/firebase_auth/auth_util.dart';
```
:::
-### Accessing FlutterFlow Generated Classes
+### Access FlutterFlow Generated Classes
FlutterFlow generates a complete Flutter codebase for you as you build apps in its platform. Part of this code includes custom classes that are designed to streamline common tasks and encapsulate reusable properties or logic.
@@ -67,7 +67,7 @@ Use this approach only when the component is a fixed element that does not chang
:::
In a **[Custom Widget](custom-widgets.md)**, you can integrate a previously built **[FlutterFlow Component](../../resources/ui/components/intro-components.md)** directly, saving you from recreating child content in code. For example, if you’re building a Custom Widget to display custom dialog boxes or bottom sheets using a package from
-[pub.dev](custom-code.md#pubdev), you can simply return an existing Component created on the canvas, rather than coding a new one from scratch.
+[pub.dev](https://pub.dev/), you can simply return an existing Component created on the canvas, rather than coding a new one from scratch.
:::tip[Imports]
When referencing a Component class in your code, FlutterFlow will automatically add the necessary import statement.
@@ -78,7 +78,7 @@ When referencing a Component class in your code, FlutterFlow will automatically

-### Accessing FlutterFlow Theme in Custom Widget
+### Get FlutterFlow Theme in Custom Widget
When building custom widgets, you often need to style parts of the widget, such as setting colors. Instead of using hardcoded color values, you can directly access the **FlutterFlow Theme**. This theme provides consistent styling across your app and reflects colors set by you or your project developer.
@@ -128,18 +128,17 @@ class _CustomButtonState extends State {
}
}
```
-:::info
-Find the list of colors,
-### Manipulating AppState from Custom Code
-In FlutterFlow, you can access or update AppState directly from the Action Flow Editor. However, certain scenarios may require you to access or modify AppState within custom code for more control over the operation flow. The FFAppState class also provides additional helper functions to manipulate AppState variables. Let’s look at some examples:
+### Modifying AppState from Custom Code
+
+In FlutterFlow, you can access or update AppState directly from the Action Flow Editor. However, certain scenarios may require you to access or modify AppState within custom code for more control over the operation flow. The `FFAppState` class also provides additional helper functions to modify AppState values. Let’s look at some examples:
:::tip[Imports]
Ensure you import `import '../../flutter_flow/flutter_flow_util.dart';` when accessing `FFAppState` in custom code resources.
:::
-- **Accessing AppState in Custom Code**
+- **Get AppState value in Custom Code**
```js
@@ -218,7 +217,7 @@ final newProduct = ProductStruct(
```
-#### Example 2: Accessing Properties of an Existing `ProductStruct` object
+#### Example 2: Get Properties of an Existing `ProductStruct` object
If you have an existing `ProductStruct` object (e.g., retrieved from a list of products), you can access its properties or return specific values back to the calling Action.
@@ -230,7 +229,7 @@ This function retrieves and returns the product's name. The return type is `Stri
```js
// Function to return the product name from a ProductStruct instance
String? getProductName(ProductStruct product) {
- // Access and return the product name
+ // Get and return the product name
return product.name;
}
```
@@ -346,3 +345,94 @@ Here’s a list of other Firebase Auth variables that can be referenced in Custo
- These variables make it easy to integrate Firebase Auth data into custom functionality, enhancing the user experience.
+
+### Get Dev Environment Values in Custom Code
+
+Similar to `FFAppState`, FlutterFlow generates a singleton `FFDevEnvironmentValues` class in your FlutterFlow generated codebase, if you are using **[Dev Environments](../../testing-deployment-publishing/development-environments/development-environments.md)**. This class can also be accessed from custom code if needed. It is generated based on the environment selected by the user at the time of code generation.
+
+To access any Dev Environment values in custom code, simply use:
+
+```js
+Future getWebhookId() async {
+ // Add your function code here!
+ return FFDevEnvironmentValues().webhookId;
+}
+```
+
+### Access Library Components in Custom Code
+
+When using a library dependency in your project, you can also access its components, such as Library App State, Library Values, and Library Widgets, in the user project's custom code. Here are a few examples:
+
+#### Get Library Values
+
+Similar to `FFAppState` or `FFDevEnvironmentValues` class, FlutterFlow generates a singleton `FFLibraryValues` class for library projects, which provides direct access to **[Library Values](../../resources/projects/libraries.md#library-values)**.
+
+To access Library Values directly in custom code:
+
+```js
+Future getSchema(StateStruct? syncStatus) async {
+ print(FFLibraryValues().schema);
+}
+```
+
+#### Get Library Custom Code
+
+When you add a library dependency to your FlutterFlow project, FlutterFlow automatically includes necessary imports, allowing you to utilize custom code resources from the library project in your user project's custom code files.
+
+For example, if you have a library with project ID `library_hybw3o`, FlutterFlow will add the following import to your project:
+
+```js
+import 'package:library_hybw3o/flutter_flow/custom_functions.dart' as library_hybw3o_functions;
+```
+
+
+Now, let's use the library’s custom functions in the user project's custom function:
+
+```js
+int getRandomIndex(List indexList) {
+ final item = library_hybw3o_functions.getRandomItem(); // Library's custom function
+ // get Random Index
+ final randomNumber = math.Random();
+ return ...
+}
+```
+
+#### Manually Add Library Imports
+If the library import doesn’t appear in your project automatically, you can manually add it and assign a custom alias. For example, to import a library’s custom actions into your project’s Custom Widget resource, add the import yourself as shown below:
+
+For example, let's import the library's custom actions into the user project's Custom Widget resource.
+
+If the import is not already available, you can add it manually as follows:
+
+```js
+// Custom import
+import 'package:library_hybw3o/custom_code/actions/index.dart' as library_hybw3o_actions; // Assigning a custom alias to the import
+
+// Example Widget code
+class CustomDialog extends StatefulWidget {
+ const CustomDialog({
+ super.key,
+ this.width,
+ this.height,
+ });
+
+ final double? width;
+ final double? height;
+
+ @override
+ State createState() => _CustomDialogState();
+}
+
+class _CustomDialogState extends State {
+ @override
+ void initState() {
+ library_hybw3o_actions.getSchema(StateStruct()); // calling library custom action
+ super.initState();
+ }
+ @override
+ Widget build(BuildContext context) {
+ return Container(height: 50, width: 50);
+ }
+}
+```
+
diff --git a/docs/ff-concepts/adding-customization/configuration-files.md b/docs/ff-concepts/adding-customization/configuration-files.md
new file mode 100644
index 00000000..a0067b99
--- /dev/null
+++ b/docs/ff-concepts/adding-customization/configuration-files.md
@@ -0,0 +1,886 @@
+---
+slug: /concepts/custom-code/configuration-files
+title: Configuration Files
+description: Learn how to modify platform-specific files for Android and iOS to extend your app's capabilities.
+tags: [Configuration Files, Custom Code]
+sidebar_position: 5
+keywords: [FlutterFlow, Configuration Files, Customizations, Flutter, Dart, Pub.dev, Edit Native Files, Android, iOS, AndroidManifest.xml, Info.plist, Entitlements.plist, main.dart, proguard]
+---
+
+# Configuration Files
+
+FlutterFlow allows you to modify configuration files for your app, and platform-specific files, without leaving the FlutterFlow interface.
+
+In some cases, you’ll need to tweak the configuration files that FlutterFlow generates. This is usually required when integrating third-party packages such as analytics, ad networks, and payment solutions.
+
+Here are the key configuration files you can edit:
+
+- [**`AndroidManifest.xml`**](#androidmanifestxml-android) – Configures app permissions, metadata, and intent filters for Android.
+- [**`build.gradle`**](#buildgradle-android) – Defines Android specific build configurations such as compile SDK version, dependencies, build types, and signing configurations.
+- [**ProGuard files**](#proguard-file-android) – Used for code shrinking and obfuscation in Android builds.
+- [**`Info.plist`**](#infoplist-ios)– Manages iOS app settings, including permissions and configurations.
+- [**`Entitlements.plist`**](#entitlementsplist-ios) – Defines iOS app privileges such as push notifications and Apple Pay.
+- [**`AppDelegate.swift`**](#appdelegateswift-ios) – Manages iOS app launch behavior and runtime configuration. It registers Flutter plugins, initializes services like Firebase, and handles app lifecycle events and deep linking.
+- [**`main.dart`**](#maindart-flutter) – The entry point of your Flutter app, where you can modify app-level logic.
+
+
+:::warning
+
+While editing configuration files can unlock advanced functionality, it comes with risks. A small mistake (e.g., a missing XML tag or a wrong key) can cause your app to fail compilation or crash at runtime. Incorrect changes might lead to App Store/Play Store rejections. So, it’s important to note your changes and thoroughly test your app after each edit.
+
+In short, edit native code only when necessary, and do so carefully.
+
+:::
+
+## Editing Files
+
+FlutterFlow provides two main ways to modify native files: [**Add Individual Snippets**](#option-1-add-individual-snippets) and [**Manual Edit Mode**](#option-2-manual-edit-mode).
+
+### Option 1: Add Individual Snippets
+
+**Snippets** are small pieces of code that you can inject into the native files at predefined locations. Instead of opening the whole file to edit, you provide just the fragment you want to add, and FlutterFlow merges it into the file in the correct place. This is safer and easier for small additions such as a permission line or a meta-data tag.
+
+#### Snippet Placement for Android
+
+Let’s see how to add a snippet for the `AndroidManifest.xml` file, where you can add the following tags:
+
+- **Activity Tags:** Inserts XML code inside the `MainActivity` block. This is typically used to add child XML elements within the MainActivity, such as `` or `` to control aspects such as deep linking, theme application, or launch mode.
+- **Application Tags**: Used to inject properties or attributes directly on the `` tag itself. For example, you can use this to set values such as `android:icon`, `android:label`, `android:allowBackup`.
+- **App Component Tags**: Inserts complete XML components inside the `...` block. Use this to add additional activities, services, broadcast receivers, or content providers that your app depends on.
+
+To add a snippet to your `AndroidManifest.xml`, navigate to **Custom Code** from the left navigation menu, select **Configuration Files**, then choose `AndroidManifest.xml`. Click the **plus (+)** button next to the tag where you want to insert the snippet. Provide a name (this will be included as a comment in the file) and paste your snippet code.
+
+
+
+
+
+
+#### Snippet Placement for iOS
+
+For iOS, let’s see how to add a snippet for the `Info.plist` and `Entitlements.plist` files. There’s no nested application/activity structure like on Android. Instead, both files are dictionaries of key-value pairs. When you add a snippet, it’s placed directly under the root `` element of these plist files.
+
+To add a snippet to native iOS files, navigate to **Custom Code** (from the left-side menu) > **Configuration Files**, and select the desired file. Click the **plus** (+) button, provide a descriptive name (which will appear as a comment in the file), and paste your snippet code.
+
+
+
+
+
+
+:::tip
+- Snippet insertion isn't available for `main.dart`. Instead, you can directly modify the file using [**Manual Edit Mode**](#option-2-manual-edit-mode).
+- You can also use your Development [**Environment Values**](../../testing-deployment-publishing/development-environments/development-environments.md#environment-values) and [**Library Values**](../../resources/projects/libraries.md#library-values) inside snippets. For more details, refer to the [**Include Variables in Native Code**](#include-variables-in-native-code) section.
+:::
+
+### Option 2: Manual Edit Mode
+
+For more complex changes, you can enable **Manual Edit Mode**, which unlocks the entire file for free-form editing. This is like opening the raw file in a text editor directly within FlutterFlow. **Note that** the manual mode is powerful but should be used carefully.
+
+To manually edit native files, navigate to **Custom Code** (from the left-side menu) > **Configuration Files**, select the file you want to edit, and click the **lock** button to unlock it. You can now freely modify the file.
+
+:::warning
+Once unlocked, the file stays in manual editing mode until you lock it again. Re-locking it will reset the file to a version generated by FlutterFlow, which will overwrite any manual changes you've made.
+:::
+
+
+
+
+
+
+:::tip
+
+- Don’t remove FlutterFlow’s existing entries unless you are sure. It’s safer to only add or modify necessary lines and leave the rest as is.
+- Use Manual Edit Mode for bulk or complex edits that the snippet can’t easily do, such as reordering tags, removing something, or pasting in a large chunk of config. Always verify that the app still builds and runs after such edits.
+- You can also use your Development [**Environment Values**](../../testing-deployment-publishing/development-environments/development-environments.md#environment-values) and [**Library Values**](../../resources/projects/libraries.md#library-values) inside snippets. For more details, refer to the [**Include Variables in Native Code**](#include-variables-in-native-code) section.
+:::
+
+## Include Variables in Native Code
+
+When editing native files in FlutterFlow, you may need to include dynamic values, such as API keys, app configurations, or environment-specific settings. Instead of hardcoding these values directly in **`AndroidManifest.xml`**, **`Info.plist`**, or other native files, you can use FlutterFlow [**Environment Values**](../../testing-deployment-publishing/development-environments/development-environments.md#environment-values) and [**Library Values**](../../resources/projects/libraries.md#library-values) to keep your app flexible and secure.
+
+To include a variable in a configuration file, start by creating a **file-level variable** and assigning it a value from either your **Environment Values** or **Library Values**. Then, reference this variable using a placeholder format (e.g., `{{apiToken}}`) within the configuration file. These placeholders in native files are automatically replaced with their actual values during the code generation process.
+
+Here’s exactly how you do it:
+
+
+
+
+
+
+
+You can also directly insert a variable placeholder (e.g., `{{variableName}}`) into the code using a snippet or manual edit mode and FlutterFlow automatically creates the corresponding file-level variable.
+
+
+
+
+
+
+
+
+:::tip
+You can use the file level variable across different snippets within the same file.
+:::
+
+Here are some examples that utilize variables in native code:
+
+**Example 1: Using API Keys in `AndroidManifest.xml`**
+
+Let’s say you are integrating the Mapbox package in your FlutterFlow app, and it requires an API Key in the form of a token inside the `AndroidManifest.xml` file. Instead of hardcoding the token, you can use a variable like this:
+
+```xml
+
+```
+
+Here, `{{MAPBOX_ACCESS_TOKEN}}` is a file level variable that holds the Environment Value.
+
+
+**Example 2: Configuring `Info.plist` for iOS**
+
+For iOS apps, you might need to configure App Transport Security (ATS) to allow non-HTTPS connections. Instead of manually setting `NSAllowsArbitraryLoads` to `true`, you can use a variable:
+
+```xml
+NSAllowsArbitraryLoads
+<{{ALLOW_HTTP_TRAFFIC}}/>
+```
+
+If `ALLOW_HTTP_TRAFFIC` is set to `true` in FlutterFlow’s Environment Value, the app will allow HTTP connections.
+
+
+**Example 3: Using Library Values**
+
+If you are building a [FlutterFlow Library](../../resources/projects/libraries.md) and need to include public API keys in native code, you can use [Library Values](../../resources/projects/libraries.md#library-values) as placeholders. This ensures that when someone installs your library, they can define their own values.
+
+For example, if your library integrates with a public weather API that requires an API key (such as Open-Meteo or WeatherAPI for general use), it’s best not to add the key directly in the manifest file. Instead, create a file-level variable and assign it a Library Value.
+
+```jsx
+
+
+
+```
+
+The library user will define their own API key under Library Values when importing your library. At build time, FlutterFlow replaces `{{WEATHER_API_KEY}}` with the user-defined key.
+
+## Editable Files
+
+FlutterFlow allows editing several key native files. Below, we cover each file’s role, why you might need to edit it, and examples of real-world use cases.
+
+### `AndroidManifest.xml` (Android)
+
+`AndroidManifest.xml` is the master configuration file for your Android app. It is located in the root directory of the app's `android/app/src/main` folder and declares essential app information to the Android OS and Google Play. This includes your app’s package name, components (activities, services, receivers), and the permissions it needs.
+
+It defines hardware and software features the app depends on, such as Bluetooth, GPS, or sensors. The manifest manages intents and filters, determining how the app responds to system events and deep linking. It also includes metadata and configuration for SDKs and libraries, such as API keys or feature flags.
+
+In short, the manifest is like an app’s identity card and permission sheet for Android.
+
+Here are some scenarios where you may need to modify the `AndroidManifest.xml` file:
+
+**Example 1: Declaring App Components (Activities, Services, Receivers)**
+
+For including additional screens (activities), background processes (services), or listeners (broadcast receivers), you must declare them in `AndroidManifest.xml`.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+```
+
+This registers `NewScreenActivity` so the system knows it exists.
+
+**Example 2: Requesting Permissions**
+
+If your app requires access to restricted resources such as wake locks (to keep the device awake) or audio recording, you must declare the necessary permissions in `AndroidManifest.xml` by [manually editing](#option-2-manual-edit-mode) the file. **Tip:** You can also add custom permissions directly through the [**Permission Settings**](../../resources/projects/settings/project-setup.md#adding-custom-permission) in FlutterFlow.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+Without these, the app cannot keep the device awake or record audio.
+
+**Example 3: Adding Metadata for SDKs and Libraries**
+
+Many third-party packages (Google Maps, Firebase, AdMob, etc.) require `` tag in `AndroidManifest.xml` to pass configuration values. For example, the [**Mapbox Flutter**](https://pub.dev/packages/mapbox_flutter) plugin requires adding your Mapbox access token as a metadata entry for initialization. A real example: to initialize Mapbox, you’d add:
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+**Example 4: Restricting the App to Specific Devices**
+
+You can specify device hardware requirements (e.g., GPS, camera, touchscreen) to ensure the app only installs on compatible devices.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+This prevents installation on devices without a camera.
+
+**Example 5: Enabling Cleartext Traffic**
+
+If your app needs to communicate over HTTP (unencrypted) for testing or legacy reasons, you might need to add `android:usesCleartextTraffic="true"` in the `` tag. This is to relax network security for HTTP URLs.
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+:::tip
+You can modify the `AndroidManifest.xml` file by either [**adding a snippet**](#snippet-placement-for-android) or [**editing it manually**](#option-2-manual-edit-mode).
+:::
+
+### `build.gradle` (Android)
+
+The `build.gradle` file is the main Gradle build script for your Android app module. It resides in the `android/app/` directory and controls how your Android app is compiled, packaged, and built. This file defines critical configuration such as:
+
+- SDK versions (`compileSdkVersion`, `minSdkVersion`, `targetSdkVersion`)
+- Dependencies for third-party libraries
+- Build types (like debug vs. release)
+- Signing configurations for release builds
+- Kotlin and Flutter settings
+- MultiDex and ProGuard rules
+- Android packaging options
+
+In short, the `build.gradle` file acts as the blueprint for how your Android app is built and prepared for distribution.
+
+**Example 1: Changing SDK Versions**
+
+To set which Android SDK your app compiles with, update the following section in `build.gradle`:
+
+```jsx
+android {
+ compileSdkVersion 33
+
+ defaultConfig {
+ applicationId "com.example.myapp"
+ minSdkVersion 21
+ targetSdkVersion 33
+ versionCode 1
+ versionName "1.0"
+ }
+}
+```
+
+Use this when you want to upgrade to a newer Android API level or need compatibility with certain libraries.
+
+
+**Example 2: Adding Third-Party Libraries**
+
+To use Android-specific libraries (such as Play Services or Jetpack), add them in the `dependencies` section:
+
+```jsx
+dependencies {
+ implementation 'com.google.android.gms:play-services-maps:18.1.0'
+ implementation 'androidx.work:work-runtime:2.7.1'
+}
+```
+
+Use this when integrating services like Google Maps, Firebase Messaging, or WorkManager.
+
+
+**Example 3: Adding ProGuard Rules for Release Build**
+
+If your app uses ProGuard (code shrinking/obfuscation), you can define custom rules or reference a rules file:
+
+```jsx
+android {
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+```
+
+Use this to reduce APK size and protect code in production.
+
+**Example 4: Enabling MultiDex for Large Apps**
+
+If your app exceeds the 64K method limit (common when using many dependencies), enable MultiDex support:
+
+```jsx
+defaultConfig {
+ ...
+ multiDexEnabled true
+}
+```
+
+Use this when your build fails with `Too many methods` errors or when integrating large libraries like Firebase.
+
+:::tip
+You can modify the `build.gradle` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
+:::
+
+### ProGuard File (Android)
+
+The **ProGuard file (`proguard-rules.pro`)** is a configuration file used in Android projects to optimize, shrink, and obfuscate the app’s code. It helps reduce APK or AAB size, improves performance, and protects the app’s code from reverse engineering by making it difficult to decompile.
+
+The ProGuard files allow you to specify rules to keep certain classes or methods (prevent them from being removed or renamed), or to tweak the obfuscation behavior. Located in the **`android/app/proguard-rules.pro`** directory of an Android project, the ProGuard rules are applied when code shrinking is enabled in a release build.
+
+Here are some scenarios where you may need to modify the ProGuard file:
+
+**Example 1: Preventing Issues with Third-Party Libraries**
+
+ProGuard can obfuscate critical libraries, breaking their functionality. To prevent this, you need to keep specific classes used by the library.
+
+```jsx
+# Firebase
+-keep class com.google.firebase.** { *; }
+
+# Gson (JSON Serialization)
+-keep class com.google.gson.** { *; }
+-keepattributes *Annotation*
+```
+
+This ensures that Firebase and Gson classes are not obfuscated, preventing serialization errors.
+
+**Example 2: Debugging ProGuard Issues**
+
+If your app crashes in release mode but works in debug mode, ProGuard might be removing important classes. To troubleshoot, you can add logging and keep rules.
+
+```jsx
+-assumenosideeffects class android.util.Log {
+ public static *** d(...);
+ public static *** v(...);
+ public static *** i(...);
+}
+```
+
+This removes debug logs in release builds but retains them for troubleshooting.
+
+**Example 3: Improving Security by Removing Debug Information**
+
+Attackers can decompile APKs and view sensitive debug logs. To remove these debug logs, add:
+
+```jsx
+-dontwarn android.util.Log
+```
+
+
+**Example 4: Keeping Native Libraries (JNI) Safe**
+
+If your app uses native C/C++ libraries (JNI), ProGuard may mistakenly remove required components. To prevent this:
+
+```jsx
+-keep class com.example.native.** { *; }
+-keepclassmembers class * {
+ native ;
+}
+```
+
+This keeps all native methods intact.
+
+**Example 5: Preventing Issues with Reflection-Based Code**
+
+Some libraries rely on reflection to dynamically call methods, which ProGuard may remove.
+
+```jsx
+-keep class * implements android.os.Parcelable { *; }
+-keepclassmembers class ** {
+ @android.webkit.JavascriptInterface ;
+}
+```
+
+This ensures reflection-based code continues working.
+
+### `Info.plist` (iOS)
+
+`Info.plist` (Information Property List) is the configuration file for iOS apps. It’s a structured XML file that provides iOS with essential information about your app’s configuration and requirements.
+
+The `Info.plist`defines things such as your app’s bundle identifier, display name, version, and most importantly, usage descriptions for permissions and other settings iOS needs at runtime. The file is required for every iOS app and is located in the project’s `/ios/Runner/` directory of your FlutterFlow apps.
+
+Essentially, it’s the blueprint for iOS to understand your app’s capabilities and needs.
+
+Here are some scenarios where you may need to modify the `Info.plist` file:
+
+**Example 1: Requesting Permissions**
+
+If your app requires location access both while in use and in the background, you must declare the appropriate permissions in `Info.plist`. **Tip:** You can also add custom permissions directly through the [**Permission Settings**](../../resources/projects/settings/project-setup.md#adding-custom-permission) in FlutterFlow.
+
+```xml
+NSLocationWhenInUseUsageDescription
+This app requires location access while in use to provide location-based services.
+
+NSLocationAlwaysAndWhenInUseUsageDescription
+This app requires background location access to enable continuous location tracking.
+
+```
+
+This ensures the app can access location services even when the user is not actively using it.
+
+**Example 2: Enabling App Transport Security (ATS) for HTTP Requests**
+
+By default, iOS enforces HTTPS connections for security reasons. If your app needs to communicate with **HTTP-only** servers, you must modify `Info.plist`.
+
+```xml
+NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+```
+
+This allows all HTTP requests but should be used with caution
+
+**Example 3: Configuring Background Modes**
+
+If your app requires background functionality (e.g., playing music, location tracking), you must enable background modes in `Info.plist`.
+
+```xml
+UIBackgroundModes
+
+ audio
+ location
+
+```
+
+This allows the app to play audio or track location when running in the background.
+
+**Example 4: Adding Keys**
+
+Many third-party packages require to add keys in the in `Info.plist` file. For example, If you’re using the Mapbox SDK, you need to provide an access token in `Info.plist` to enable map functionality.
+
+```xml
+io.flutter.embedded_views_preview
+
+MGLMapboxAccessToken
+YOUR_MAPBOX_ACCESS_TOKEN
+```
+
+The **`MGLMapboxAccessToken`** key is required for initializing Mapbox maps in your app. Additionally, the **`io.flutter.embedded_views_preview`** key must be set to `true` to support embedding native views inside Flutter widgets.
+
+:::tip
+You can modify the `Info.plist` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
+:::
+
+### `Entitlements.plist` (iOS)
+
+The `Entitlements.plist` file is a property list in iOS applications that defines the app’s security-related capabilities and permissions. It grants specific privileges to an app, allowing it to access Apple services such as iCloud, Push Notifications, App Groups, Background Modes, and Keychain access. It is located in the **`/ios/Runner/`** directory of your FlutterFlow app and is named **`Runner.entitlements`**.
+
+This file ensures that only authorized apps can use these features, maintaining security and preventing unauthorized access to sensitive system functions.
+
+Here are some scenarios where you may need to modify the `Entitlements.plist` file:
+
+**Example 1: Enabling iCloud Storage**
+
+If your app integrates **iCloud services**, such as syncing user data or storing documents, you must add iCloud entitlements.
+
+```xml
+com.apple.developer.icloud-container-identifiers
+
+ iCloud.com.yourcompany.appname
+
+
+com.apple.developer.icloud-services
+
+ CloudDocuments
+
+```
+
+This grants your app access to iCloud storage under the specified container.
+
+**Example 2: Enabling Keychain Access**
+
+If your app needs to store secure credentials, enabling Keychain Sharing is required.
+
+```xml
+keychain-access-groups
+
+ com.yourcompany.appname
+
+```
+
+This allows secure storage of login credentials, API tokens, or encryption keys in the iOS Keychain.
+
+**Example 3: Enabling App Groups for Shared Data**
+
+If your app shares data between multiple apps or an app extension (e.g., a widget or a Siri shortcut), you must enable App Groups.
+
+```xml
+com.apple.security.application-groups
+
+ group.com.yourcompany.shared
+
+```
+
+This allows different apps or extensions to access shared storage and user defaults.
+
+**Example 4: Enabling Wallet (Apple Pay & Passes)**
+
+If your app integrates with Apple Wallet, you need to add Wallet entitlements.
+
+```xml
+com.apple.developer.pass-type-identifiers
+
+ pass.com.yourcompany.appname
+
+```
+
+This enables your app to create, manage, and present passes in Apple Wallet.
+
+:::tip
+You can modify the `Entitlements.plist` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
+:::
+
+### `AppDelegate.swift` (iOS)
+
+The `AppDelegate.swift` file is the entry point for your iOS application. It plays a crucial role in setting up your app’s runtime environment and handling app lifecycle events such as launching, backgrounding, and termination. This file is also where you register Flutter plugins and initialize SDKs like Firebase or Branch.
+
+It’s located at: `ios/Runner/AppDelegate.swift`
+
+**Example: Registering Custom iOS Plugins**
+
+For custom native iOS plugins that aren’t auto-registered, you can manually register them inside `AppDelegate.swift`.
+
+```jsx
+override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+) -> Bool {
+ let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
+ let myPlugin = CustomPlugin()
+ myPlugin.register(with: controller)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+}
+```
+
+Use this for custom iOS integrations that require manual setup.
+
+:::tip
+You can modify the `AppDelegate.swift` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
+:::
+
+### `main.dart` (Flutter)
+
+The `main.dart` file is the entry point of every FlutterFlow app. It is the first file that runs when the app starts and is responsible for initializing the application, configuring dependencies, and defining the root widget. Located in the **`lib/`** directory, `main.dart` contains the `main()` function, which is required for every FlutterFlow app.
+
+If you need to execute any custom Dart code at startup — such as initializing third-party SDKs, setting global configurations, service locators, printing a debug log, or running certain functions once — `main.dart` is the place to do it.
+
+:::info
+[**Adding Snippets**](#option-1-add-individual-snippets) isn't available for `main.dart`. Instead, you can directly modify the file using [**Manual Edit Mode**](#option-2-manual-edit-mode).
+:::
+
+Here are some scenarios where you may need to modify the `main.dart` file:
+
+**Example 1: Initializing Third-Party Packages**
+
+Many packages have initialization calls. For example, if you added a custom package for analytics or error tracking (say Sentry or a logging service), you might need to call `SentryFlutter.init()` or set up an error handler at app startup. By placing that call in `main.dart` (before or right after `runApp`), you ensure it’s executed early.
+
+```jsx
+import 'dart:async';
+
+import 'package:flutter/widgets.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
+
+Future main() async {
+ runZonedGuarded(() async {
+ await SentryFlutter.init(
+ (options) {
+ options.dsn = 'https://example@sentry.io/add-your-dsn-here';
+ },
+ );
+
+ runApp(MyApp());
+ }, (exception, stackTrace) async {
+ await Sentry.captureException(exception, stackTrace: stackTrace);
+ });
+}
+```
+
+This ensures Sentry is ready before the app starts, just like Firebase initialization.
+
+**Example 2: Customizing the Status Bar Appearance**
+
+If you want to change the status bar color and adjust icon brightness for Android and iOS, you need to modify `main.dart` before calling `runApp()`.
+
+```jsx
+
+import 'package:flutter/services.dart';
+
+void main() {
+ SystemChrome.setSystemUIOverlayStyle(
+ SystemUiOverlayStyle(
+ statusBarColor: Colors.redAccent, // Custom status bar color
+ statusBarIconBrightness: Brightness.dark, // Dark icons for Android
+ statusBarBrightness: Brightness.light, // Light icons for iOS
+ ),
+ );
+
+ runApp(MyApp());
+}
+
+```
+
+**Example 3: Locking the Screen Orientation**
+
+Some apps require landscape-only or portrait-only modes. You can enforce screen orientation in `main.dart` before launching the app.
+
+```jsx
+import 'package:flutter/services.dart';
+
+Future main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ await SystemChrome.setPreferredOrientations([
+ DeviceOrientation.landscapeLeft,
+ DeviceOrientation.landscapeRight,
+ ]);
+
+ runApp(MyApp());
+}
+```
+
+This ensures the app only runs in landscape mode.
+
+**Example 4: Observing App Lifecycle Changes**
+
+If your app needs to respond to lifecycle events, such as tracking when the app goes into the background or returns to the foreground, you can attach an observer.
+
+```jsx
+import 'package:flutter/widgets.dart';
+
+void main() {
+ WidgetsFlutterBinding.ensureInitialized();
+ WidgetsBinding.instance.addObserver(AppLifecycleObserver());
+ runApp(MyApp());
+}
+
+class AppLifecycleObserver with WidgetsBindingObserver {
+ @override
+ void didChangeAppLifecycleState(AppLifecycleState state) {
+ if (state == AppLifecycleState.resumed) {
+ print('App is in foreground');
+ } else if (state == AppLifecycleState.paused) {
+ print('App is in background');
+ }
+ }
+}
+```
+
+
+## Best Practices
+
+- **Backup:** Before making native file changes, ensure you have a backup of at least the text of the original file. You could also commit your changes so you can revert if needed. This way, if things go wrong, you can manually restore.
+- **One Change at a Time:** Add or modify one item at a time and then test your app. If you add multiple things and something breaks, it’s harder to pinpoint which change did it.
+- **Consult Package Documentation:** When you’re making changes for third-party packages, follow their instructions exactly. Usually, package docs show a snippet – use that in FlutterFlow’s [snippet](#option-1-add-individual-snippets). Double-check official docs for Android or iOS if you’re unsure about the correct keys or tags. For example, if enabling background fetch, Apple’s docs will list the exact string to use in `Info.plist` (`fetch` in `UIBackgroundModes` array).
+- **Keep it Minimal:** Only add what you truly need. Don’t add a bunch of entitlements or permissions “just in case” as that can bloat and complicate your app, and even trigger store reviews for uses that your app doesn’t actually have.
+- **Use Comments:** As you modify files, annotate them. If six months later you or a team member look at the manifest, a comment like `` is very helpful.
+- **Testing on Devices:** Especially for anything related to `Info.plist` or entitlements, always test on a real iOS device if possible. Some issues (like missing entitlements or background mode usage) won’t show up in the simulator. Similarly, test Android changes on a device or emulator with a release build – because ProGuard rules effects, for example, only show in release mode.
+- **Monitoring Logs and Errors:** After making changes, monitor the Xcode console or Android logcat when running the app. If there are misconfigurations, you often get warnings.
+- **Stay Updated:** FlutterFlow may improve native editing features over time. Keep an eye on FlutterFlow’s docs or community announcements. If they introduce a new easier way, prefer that to manual editing when possible, as it will be more foolproof.
+- **Security Consideration:** Remember that anything in these files (especially `Info.plist`, `AndroidManifest.xml`) is essentially public in the distributed app. Don’t assume an API key in `Info.plist` is hidden – it’s not. For keys you must include (maps, etc.), consider using [private environment values](../../testing-deployment-publishing/development-environments/development-environments.md#private-environment-values) and monitoring their usage.
+
+## FAQs
+
+
+
+My app won’t install on an iOS device. What should I check?
+
+
+Confirm that the entitlements in `Entitlements.plist` match your provisioning profile. If you see a “Missing entitlement” error, it means you added an entitlement not allowed by your profile. Remove it or update the profile in the Apple Developer Portal.
+
+
+
+
+
+How do I fix “Manifest merger failed” on Android?
+
+
+This error indicates a conflict in your `AndroidManifest.xml`. Common issues include **duplicate permissions** or attributes (e.g., two `` entries). The error message usually identifies the conflicting line. Remove the duplicate or ensure each property is set only once to resolve the conflict.
+
+
+
+
+
+Why my app isn't running in Test Mode after editing the `main.dart` file with Supabase enabled?
+
+
+There's a known limitation where editing the `main.dart` file with Supabase enabled prevents Test Mode from running. As a workaround, please use [**Local Run**](../../testing-deployment-publishing/running-your-app/local-run.md) to test your app instead.
+
+
+
+
+
+Can I modify the Configuration Files in a Library project?
+
+
+Yes, you can. When a Library Project is imported, any configuration file snippets, such as those for `AndroidManifest.xml`, `Info.plist`, or `Entitlements.plist` are automatically merged into the importing project's configuration files.
+
+Additionally, your Library Project can pass values (like API keys) into those snippets using [**Library Values**](../../resources/projects/libraries.md#library-values), making it easy to customize.
+
+
+
+This makes Libraries incredibly powerful and enables easy integration of tools like **PostHog** (analytics), **Sentry** (crash reporting), **CleverTap**, **flutter_local_notifications**, **flutter_nfc_kit**, and many more directly from the Marketplace.
+
+
\ No newline at end of file
diff --git a/docs/ff-concepts/adding-customization/custom-code.md b/docs/ff-concepts/adding-customization/custom-code.md
index 8d76ab3a..c0c8414d 100644
--- a/docs/ff-concepts/adding-customization/custom-code.md
+++ b/docs/ff-concepts/adding-customization/custom-code.md
@@ -14,12 +14,14 @@ While FlutterFlow provides a wide range of pre-built components and functionalit
times when you need to extend your app with custom logic or UI components that are not available out of the box.
This is where writing custom code comes into play.
-There are a few different ways to make custom code accessible in FlutterFLow:
+There are a few different ways to make custom code accessible in FlutterFlow:
* **[Custom Functions](custom-functions.md):** Custom Dart functions that can be used to set Widget or Action properties.
* **[Custom Actions](custom-actions.md):** Custom Dart functions that can be triggered by [Action Triggers](https://docs.flutterflow.io/resources/functions/action-triggers/) or used as nodes in an [Action Flow](https://docs.flutterflow.io/resources/functions/action-flow-editor#action-flow-editor). These are usually `async` functions and are able to import [custom package dependencies](#adding-a-pubspec-dependency).
+* **[Code File](code-file.md):** You can define custom classes, enums, and logic to manage your app’s data and behavior.
* **[Custom Widgets](custom-widgets.md):** Custom Flutter widgets that can also import [custom package dependencies](#adding-a-pubspec-dependency) and be used in the same way as [Components](https://docs.flutterflow.io/resources/ui/components) throughout your project.
-* **[Custom Files](custom-files.md):** Within Custom Files, you'll have the ability to edit some parts of the `main.dart` file.
+* **[Configuration Files](configuration-files.md):** You'll have the ability to edit native files for Android and iOS.
+
:::tip[Why Write Custom Code?]
@@ -44,6 +46,12 @@ You can use the In-App Code Editor to view and edit custom code directly in the

+:::tip
+To leverage the capabilities that go beyond our in-app code editor, you can click on the **VS Code icon** to open and edit your custom code directly in VS Code using the FlutterFlow [**VSCode extension**](vscode-extension.md).
+
+
+:::
+
:::warning[Using the In-App Code Editor on Desktop]
Note that the desktop version of the In-App Code Editor is limited. We recommend using the Web editor
or the **[VSCode Extension](vscode-extension.md)**.
@@ -60,7 +68,9 @@ necessary code.
This can significantly speed up the building process and reduce the need for in-depth programming
knowledge, making it especially useful for custom functions and actions.
-**Limitation:** The prompts are limited to 100 characters currently.
+:::info[Limitation]
+Your prompt must be at least 3 words and no more than 500 characters.
+:::
Project Dependencies**, then open the **Custom Dependencies** tab. Click **Add Pub Dependency**, enter the **package name** and **version**, and click **Add** to include it in your project.
-5. Click "Save & **[Compile Code](#compile-code)**" to apply the changes.
+
+
+
+
### Choosing the correct package from pub.dev
@@ -297,6 +331,100 @@ one.
When adding a pubspec dependency to your custom code in FlutterFlow, you’ll need two pieces of [information](#setup-code): the Package name with its Version number and the Import statement.
+### Using Unpublished or Private Packages
+FlutterFlow supports the use of unpublished packages, which allows you to integrate packages that are not yet available on **pub.dev**. This capability is particularly useful when working with custom, forked, or private packages hosted on public or private repositories. By leveraging this, you can enhance your app’s functionality with customized or proprietary libraries tailored to your specific needs.
+
+:::info[Possible Use Cases]
+
+- **Using a Different Branch of a Package**: When you need to test or use features that are only available on a specific branch of a package.
+- **Forked Version for Customizing Features**: When you need to fork a package to customize its functionality or fix issues that the original maintainer hasn’t addressed.
+- **Private Packages for Internal Use**: Companies or enterprises may have internal Flutter libraries that they want to use in their FlutterFlow app but cannot publish publicly due to confidentiality or proprietary restrictions.
+
+:::
+
+#### Add Packages from Public Repositories
+
+For packages hosted on public repositories (e.g., GitHub), you can add them to your FlutterFlow project by specifying the repository URL in the following format.
+
+```js
+ package_name:
+ git:
+ url: https://github.com/username/repository_name.git
+```
+
+You can also fine-tune the dependency by using additional parameters like `ref` and `path` in the given format. Here are some examples:
+
+- **To use a specific branch** (e.g., `development`):
+
+```js
+ package_name:
+ git:
+ url: https://github.com/username/repository_name.git
+ ref: development
+```
+
+- **To use from a specific commit**:
+
+```js
+dependencies:
+ package_name:
+ git:
+ url: https://github.com/username/repository_name.git
+ ref: a1b2c3d4
+
+```
+
+- **To use package located in a subdirectory of the repository**:
+
+```js
+ package_name:
+ git:
+ url: https://github.com/username/repository_name.git
+ path: packages/subpackage_name
+```
+
+Here’s exactly how you do it:
+
+
+
+
+
+
+#### Add Packages from Private Repositories
+
+For packages hosted in private repositories, you’ll need to authenticate access. This can be done using HTTPS with a personal access token.
+
+For GitHub, you can go to your GitHub account’s settings and [generate a token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with the necessary permissions and use it in the following format. You can also create and use a [fine-grained access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token) that only has certain permissions.
+
+```js
+package_name:
+ git:
+ url: https://:@github.com/username/private_repo.git
+```
+
+Replace `` with your GitHub username and `` with the generated token.
+
### Setup Code
To configure your custom code with the package, copy and paste the following items from the package's pub.dev page:
@@ -304,7 +432,7 @@ To configure your custom code with the package, copy and paste the following ite
To use the dependency in your Custom Action or Custom Widget resource file, go to the package's pub.dev page and click the **Copy to Clipboard** icon next to the package name and version. Then, paste it into the **Pubspec Dependency** section (bottom right) of the FlutterFlow code editor.
-
+
See **[example](#add-pubspec-dependency-to-custom-code-example-guide)** for more information.
@@ -349,7 +477,7 @@ FlutterFlow:
width: '100%'
}}>
+
+
:::tip[Choosing a Pubspec Dependency]
For a comprehensive guide on navigating external packages using pub.dev, evaluating packages, and making the best choices for your app, [**follow the guide**](custom-code.md#adding-a-pubspec-dependency).
:::
diff --git a/docs/ff-concepts/adding-customization/imgs/access-fields-methods.avif b/docs/ff-concepts/adding-customization/imgs/access-fields-methods.avif
new file mode 100644
index 00000000..86583213
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/access-fields-methods.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/add-cf-invoker-role.avif b/docs/ff-concepts/adding-customization/imgs/add-cf-invoker-role.avif
new file mode 100644
index 00000000..d031b3b6
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/add-cf-invoker-role.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/adding-description-on-custom-function-action.avif b/docs/ff-concepts/adding-customization/imgs/adding-description-on-custom-function-action.avif
new file mode 100644
index 00000000..035d8f89
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/adding-description-on-custom-function-action.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/code-analyzer.avif b/docs/ff-concepts/adding-customization/imgs/code-analyzer.avif
new file mode 100644
index 00000000..e50f016d
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/code-analyzer.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/code-analyzer.png b/docs/ff-concepts/adding-customization/imgs/code-analyzer.png
deleted file mode 100644
index b8412d9d..00000000
Binary files a/docs/ff-concepts/adding-customization/imgs/code-analyzer.png and /dev/null differ
diff --git a/docs/ff-concepts/adding-customization/imgs/config-values-in-library.avif b/docs/ff-concepts/adding-customization/imgs/config-values-in-library.avif
new file mode 100644
index 00000000..077786d5
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/config-values-in-library.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/custom-class-as-data-type.avif b/docs/ff-concepts/adding-customization/imgs/custom-class-as-data-type.avif
new file mode 100644
index 00000000..a20cc5a2
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/custom-class-as-data-type.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/custom-enums.avif b/docs/ff-concepts/adding-customization/imgs/custom-enums.avif
new file mode 100644
index 00000000..4980b279
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/custom-enums.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/description-in-custom-code.avif b/docs/ff-concepts/adding-customization/imgs/description-in-custom-code.avif
new file mode 100644
index 00000000..b17ae2e4
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/description-in-custom-code.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/lib-values-in-native-code-example-1.avif b/docs/ff-concepts/adding-customization/imgs/lib-values-in-native-code-example-1.avif
new file mode 100644
index 00000000..31b2a269
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/lib-values-in-native-code-example-1.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/open-in-vscode.avif b/docs/ff-concepts/adding-customization/imgs/open-in-vscode.avif
new file mode 100644
index 00000000..e55ecb61
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/open-in-vscode.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/package-dependency-version-copy.avif b/docs/ff-concepts/adding-customization/imgs/package-dependency-version-copy.avif
new file mode 100644
index 00000000..71186c31
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/package-dependency-version-copy.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/static-class-methods.avif b/docs/ff-concepts/adding-customization/imgs/static-class-methods.avif
new file mode 100644
index 00000000..ea817fd9
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/static-class-methods.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/variables-in-native-code-example-1.avif b/docs/ff-concepts/adding-customization/imgs/variables-in-native-code-example-1.avif
new file mode 100644
index 00000000..51b6051b
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/variables-in-native-code-example-1.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/variables-in-native-code-example-2.avif b/docs/ff-concepts/adding-customization/imgs/variables-in-native-code-example-2.avif
new file mode 100644
index 00000000..218f2a87
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/variables-in-native-code-example-2.avif differ
diff --git a/docs/ff-concepts/adding-customization/imgs/view-description-custom-function-and-custom-action.avif b/docs/ff-concepts/adding-customization/imgs/view-description-custom-function-and-custom-action.avif
new file mode 100644
index 00000000..eee94879
Binary files /dev/null and b/docs/ff-concepts/adding-customization/imgs/view-description-custom-function-and-custom-action.avif differ
diff --git a/docs/ff-concepts/adding-customization/vscode-extension.md b/docs/ff-concepts/adding-customization/vscode-extension.md
index c2e2f38c..eaafb6d4 100644
--- a/docs/ff-concepts/adding-customization/vscode-extension.md
+++ b/docs/ff-concepts/adding-customization/vscode-extension.md
@@ -19,6 +19,9 @@ While you can edit custom code inside FlutterFlow's in-app code editor, editing
3. **Leverage Flutter & Dart Tooling**: Using Visual Studio Code allows you to take advantage of existing Flutter and Dart tools, making it easier to develop and refactor your custom code.
4. **Leverage the AI Ecosystem**: Additionally, you can easily utilize AI tools available in the Visual Studio ecosystem, such as Copilot.
+:::info
+The VS Code extension is only available on the Growth plan and higher. Check out our [**pricing**](https://www.flutterflow.io/pricing) section.
+:::
## Installation
@@ -228,6 +231,72 @@ To delete a Custom Action or Widget, delete the associated file.
### Adding New Dependencies
You can add custom [pub.dev](https://pub.dev/) package dependencies with the `Dart: Add Dependency` command from the Visual Studio Code command palette. This will update the `pubspec.yaml` file.
+## Using Flutter Version Management (FVM)
+If you want to manage Flutter versions with [**Flutter Version Management (FVM)**](https://fvm.app/), you need to install it and add it to your system’s PATH. Follow these steps to get started:
+
+### Install FVM
+
+To install **FVM**, run the following command in your terminal. This installs FVM globally using Dart’s package manager.
+
+```
+dart pub global activate fvm
+```
+
+### Add FVM to Your System’s PATH
+
+After installation, you need to add the directory containing FVM’s executables to your **PATH variable** so that it can be accessed globally.
+
+#### For macOS & Linux
+
+1. Open the Terminal and run the following command. It adds the `~/.pub-cache/bin` directory to your system's `PATH` permanently by updating your `~/.zshrc` file. This ensures that the FVM installed in `~/.pub-cache/bin` is accessible from anywhere in the terminal.
+
+ ```bash
+ echo 'export PATH="$PATH":"$HOME/.pub-cache/bin"' >> ~/.zshrc # For Zsh
+ echo 'export PATH="$PATH":"$HOME/.pub-cache/bin"' >> ~/.bashrc # For Bash
+ ```
+
+2. Restart your terminal or run `source ~/.zshrc` (or `source ~/.bashrc`) to apply the changes.
+
+#### For Windows
+
+1. Locate the **FVM executable path**, typically:
+
+ ```
+ C:\Users\YourUsername\AppData\Local\Pub\Cache\bin
+ ```
+
+2. Add this path to your **System’s PATH variable**:
+ 1. Open **System Properties** → **Advanced system settings**.
+ 2. Click **Environment Variables**.
+ 3. Under **System variables**, select **Path** → **Edit**.
+ 4. Click **New** and add the above path.
+ 5. Click **OK** and restart your terminal.
+
+
+### Verify the Installation
+
+To check if FVM is correctly installed and accessible, run:
+
+```bash
+fvm --version
+```
+
+If this command prints the installed version of FVM, it means FVM is successfully installed and added to PATH.
+
+
+### Configure FVM in Your Flutter Project
+
+Once FVM is installed, navigate to your Flutter project folder and set up FVM:
+
+```bash
+cd your-flutterflow-project
+fvm init
+fvm install
+fvm use
+```
+
+*(Replace `` with the required Flutter version.)*
+
## FAQs
diff --git a/docs/ff-concepts/advanced/_category_.json b/docs/ff-concepts/advanced/_category_.json
new file mode 100644
index 00000000..f9e12e8d
--- /dev/null
+++ b/docs/ff-concepts/advanced/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Advanced",
+ "position": 10
+}
\ No newline at end of file
diff --git a/docs/ff-concepts/advanced/imgs/method-channels.avif b/docs/ff-concepts/advanced/imgs/method-channels.avif
new file mode 100644
index 00000000..ee4c2fbf
Binary files /dev/null and b/docs/ff-concepts/advanced/imgs/method-channels.avif differ
diff --git a/docs/ff-concepts/advanced/method-channels.md b/docs/ff-concepts/advanced/method-channels.md
new file mode 100644
index 00000000..41435c02
--- /dev/null
+++ b/docs/ff-concepts/advanced/method-channels.md
@@ -0,0 +1,629 @@
+---
+slug: /concepts/advanced/method-channels
+title: Integrating Native SDKs Using Method Channels
+description: Learn how to integrate third-party native SDKs into your FlutterFlow project using Method Channels. This guide walks through setting up channels, writing native code, and connecting it back to FlutterFlow.
+tags: [Flutter]
+sidebar_position: 1
+keywords: [FlutterFlow, Flutter, Method Channels, Existing Flutter Codebases,]
+---
+
+
+Flutter lets you build one app that runs on mobile, web, desktop, and embedded experiences from a single codebase. You write your app logic in Dart once, which is then compiled natively for the target platform. This is a big advantage for teams that want to reduce duplication between Android and iOS apps while maintaining great performance and flexibility.
+
+For native developers accustomed to Kotlin, Java, Swift, or Objective-C, Flutter provides access to platform-specific functionality. The bridge between Dart and native code is called a **MethodChannel**.
+
+You can think of it as a two-way door: Dart can ask Android or iOS to run some code, and the platform can send results back. The two sides communicate using messages, rather than shared memory, which makes the system simple and secure.
+
+With MethodChannels, you can:
+
+* Call Android and iOS APIs that aren’t built into Flutter.
+* Use advanced third‑party SDKs (e.g., barcode scanners, Bluetooth libraries, custom UI components).
+* Perform operations that need native performance or device-specific access.
+* Return data from the native side into Flutter with low latency.
+
+**Why this matters for native engineers**
+
+| What you need | How MethodChannel helps |
+| :---- | :---- |
+| Reach every platform API | You can call any Android or iOS API from Flutter using familiar native code. |
+| Keep the app smooth | Messages are encoded in binary and handled asynchronously, so the UI remains responsive. |
+| Keep the key code native | You can keep performance-sensitive or secure logic in Kotlin/Swift while building UI in Dart. |
+| Bridge advanced SDKs | Integrate with native libraries that do not have Flutter support, without waiting for a plugin. |
+
+You’re not limited by what Flutter provides out of the box. MethodChannels lets you plug in your native knowledge exactly where needed, so you don’t lose years of platform experience when moving to Flutter.
+
+
+## What is a MethodChannel?
+
+A **[MethodChannel](https://docs.flutter.dev/platform-integration/platform-channels)** or **Platform Channels** is Flutter’s core mechanism for integrating platform-specific functionality. It allows Dart code to send messages to, and receive responses from, the host platform’s native code \- Android (written in Kotlin or Java) or iOS (written in Swift or Objective-C). This enables your Flutter app to access device features and third-party native libraries that are outside the scope of the Flutter framework or its plugin ecosystem. Here is an example of MethodChannel.
+
+```js
+class _BatteryLevelScreenState extends State {
+
+ // Define the MethodChannel with a unique name. This name must match the one used on the native side.
+ static const platform = MethodChannel('com.example.battery');
+
+ // Variable to hold the battery level.
+ String _batteryLevel = 'Unknown battery level.';
+
+ // Method to invoke the native method to get the battery level.
+ Future _getBatteryLevel() async {
+ String batteryLevel;
+ try {
+ // Invoke the method on the native side.
+ final int result = await platform.invokeMethod('getBatteryLevel');
+ batteryLevel = 'Battery level at $result%.';
+ } on PlatformException catch (e) {
+ // Handle exception if the native code fails.
+ batteryLevel = "Failed to get battery level: '${e.message}'.";
+ }
+
+ // Update the UI with the retrieved battery level.
+ setState(() {
+ _batteryLevel = batteryLevel;
+ });
+ }
+
+```
+
+MethodChannels operate over a named channel using a message-passing model. You define a unique **channel name**, such as `'com.example/device'`, and both the Flutter and native sides agree to use it. On the Dart side, you call a method using `invokeMethod()`, sending an optional payload. The platform side sets up a listener (known as a method call handler) that waits for these invocations, runs native logic, and returns a result.
+
+This message flow is asynchronous and decoupled:
+
+* Dart code doesn’t block while the native code runs; it returns a `Future` that resolves when the result is ready.
+* Native code must explicitly return a result using either `success`, `error`, or `notImplemented`, ensuring consistent feedback.
+
+### Key Concepts {#key-concepts}
+
+* **Channel Name**: A unique identifier string that both Flutter and native code must use. Example: `'com.example/platform'`. Naming collisions should be avoided by namespacing based on your app or organization.
+* **Method Invocation**: Flutter calls `invokeMethod('methodName', arguments)`. The method name is a simple string. Arguments can be null or any value supported by Flutter’s `StandardMessageCodec` (bool, int, double, string, List, Map).
+* **Method Handler**: Native code uses a handler (e.g., `setMethodCallHandler` on Android) to listen for calls and run logic when the specified method name is matched.
+* **Result Callback**: The native handler must return a result via `result.success(...)`, `result.error(...)`, or `result.notImplemented()`. These responses are passed back to Dart, completing the `Future`.
+
+### Example Message Flow
+
+
+
+This design ensures clear separation between platform and UI logic, and it keeps the UI thread non-blocking for both Dart and native sides. It also makes the communication extensible—you can define as many methods as you need over a single channel or use multiple channels for modular organization.
+
+
+### When to Use a MethodChannel
+
+MethodChannel is most appropriate when:
+
+* You need to use Android/iOS APIs not available in Flutter or plugins (e.g., access to specific hardware sensors, native storage APIs).
+* You need to integrate a proprietary or vendor SDK (e.g., analytics, payment, OCR) written for the platform.
+* You need to launch a platform-native UI (e.g., a full-screen scanner or a native file picker).
+* You’re bridging a legacy native feature into a Flutter app or gradually migrating a native app to Flutter.
+
+### What MethodChannels Are Not
+
+* They are not **shared memory** \- All data is copied through serialization, not shared by reference. Only standard types are supported (primitives, lists, maps, typed data). Large data transfers require full serialization/deserialization.
+* They are **not synchronous** \- Calls return Futures immediately without blocking. Results arrive asynchronously via the event loop. Platform errors surface as PlatformExceptions when the Future completes.
+* They are **not opinionated** \- You define the API contract (method names, arguments, types) on both sides. There's no compile-time validation across the boundary \- mismatches fail at runtime. Document your contract and validate inputs since type safety isn't enforced.
+
+By understanding these characteristics, you can create robust, maintainable bridges between Dart and native code. You can write minimal, purpose-driven native handlers and keep the rest of your app in Flutter, achieving both deep platform access and cross-platform speed.
+
+## Real-World Use Cases for MethodChannels
+
+While Flutter plugins cover many common platform integrations, there are frequent scenarios where you require direct access to native SDKs or platform-specific APIs. MethodChannels offer a direct path for these integrations without waiting for third-party plugin support.
+
+Ultimately, method channel integration is essentially plugin development \- you're writing the same native bridge packaged for your app instead of as a public package. Once complete, it can be imported into FlutterFlow. The following examples show when building your own native integration is more practical than waiting for or wrestling with existing plugins. The following examples outline situations where MethodChannels are suitable.
+
+### Accessing Device Hardware Not Exposed by Plugins
+
+**Example:** Retrieve mobile network signal strength, advanced battery metrics, or thermal status.
+
+* Low-level APIs like Android's `TelephonyManager` or iOS's `CoreTelephony` are rarely exposed through Flutter plugins.
+* These require direct permission management and native invocation.
+* With MethodChannels, you can call only what you need, without waiting for a plugin update or writing one from scratch.
+
+**Benefit:** Access hardware-level telemetry or diagnostics crucial for field-service apps, testing tools, or enterprise reporting.
+
+### Integrating Proprietary SDKs or Vendor Libraries
+
+**Example:** Use a third-party identity verification SDK, document scanner, or encrypted storage SDK.
+
+* Many vendors distribute Android/iOS SDKs only and have no Flutter wrappers.
+* A minimal native wrapper and MethodChannel interface let you expose only the needed functionality.
+* Native SDK updates remain decoupled from Flutter UI changes.
+
+**Benefit:** Unlocks core business features (KYC, biometrics, payments) without dependency on plugin authors or external wrappers.
+
+### Embedding Native UI Views Temporarily
+
+**Example:** Show a native PDF viewer, a camera UI from a vendor SDK, or an AR interface.
+
+* `PlatformView` allows embedding native UI, but it requires more setup and introduces performance tradeoffs.
+* If the native UI is temporary or full-screen, you can invoke it via MethodChannel and return control to Flutter afterward.
+
+**Benefit:** Delivers platform-native experiences where needed while preserving Flutter’s rendering pipeline elsewhere.
+
+### Background Tasks and Event-Driven Native APIs
+
+**Example:** Respond to geofencing events, push token refresh, or Bluetooth device state changes.
+
+* These use cases originate in native services or background tasks.
+* You can queue or debounce events on the native side and send them to Flutter via MethodChannel when the app is active.
+* For continuous updates, use `EventChannel`, as MethodChannel is ideal for transactional or one-off data transfers.
+
+**Benefit:** Achieves OS-level integration (e.g., location, power, Bluetooth) without polling or Dart-side complexity.
+
+### Secure Device Data Retrieval
+
+**Example:** Fetch IMEI, MAC address, device fingerprint, or system identifiers.
+
+* These APIs often require special entitlements and native-side permission prompts.
+* Native logic can validate permissions, sanitize data, and decide what’s safe to return.
+
+**Benefit:** Ensures security-sensitive operations remain native-controlled, supporting enterprise, regulated, or BYOD environments.
+
+
+## Implementing a MethodChannel
+
+This section walks through the complete implementation of a MethodChannel, showing how to define the channel in Flutter (Dart), connect it to native platform code, and properly exchange messages, arguments, and results. For native developers used to Android or iOS, this breakdown will show how to bridge Dart and native code in a way that is robust, testable, and production-ready.
+
+
+
+### 1. Dart Side (Flutter)
+
+In Flutter, you use the `MethodChannel` class from the `services` package to create a communication path. The Dart side always initiates the call, and the native side responds.
+
+**Define and Use a Channel:**
+
+```js
+import 'package:flutter/services.dart';
+const platform = MethodChannel('com.example/device');
+```
+
+* The channel name `'com.example/device'` must match **exactly** with the one used on the native side.
+* Channel names should follow a reverse-domain convention to avoid collisions.
+
+**Sending a Method Call:**
+
+```js
+Future getBatteryLevel() async {
+ try {
+ final int result = await platform.invokeMethod('getBatteryLevel');
+ return 'Battery level: $result%';
+ } on PlatformException catch (e) {
+ return 'Failed to get battery level: ${e.message}';
+ }
+}
+```
+
+* `invokeMethod` sends a string method name and optional arguments to native code.
+* The result comes back asynchronously via a `Future`.
+* Always wrap the call in a `try-catch` block to handle `PlatformException`, which may occur if:
+ * The native method throws an error
+ * The method is not implemented
+ * Data serialization fails
+
+**Notes:**
+
+* You can pass arguments to `invokeMethod()` as the second parameter (e.g., a `Map`).
+* The result can be any JSON-compatible Dart type: `int`, `String`, `bool`, `double`, `List`, or `Map`.
+
+
+### 2. Android Side (Kotlin)
+
+The Android side handles Dart calls using a `MethodChannel` registered in `MainActivity`. This handler runs on the **main thread** by default, so long-running work should be offloaded to a background thread.
+
+**Setting Up the Channel:**
+
+```js
+import io.flutter.embedding.android.FlutterActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodChannel
+import android.os.BatteryManager
+import android.content.Context
+```
+
+**Handling the Method Call:**
+
+```js
+class MainActivity: FlutterActivity() {
+ private val CHANNEL = "com.example/device"
+ override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
+ call, result ->
+ when (call.method) {
+ "getBatteryLevel" -> {
+ val batteryLevel = getBatteryLevel()
+ if (batteryLevel != -1) {
+ result.success(batteryLevel)
+ } else {
+ result.error("UNAVAILABLE", "Battery level not available.", null)
+ }
+ }
+ else -> result.notImplemented()
+ }
+ }
+ }
+ private fun getBatteryLevel(): Int {
+ val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
+ return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+ }
+}
+```
+
+
+
+**Notes:**
+
+- Always return a result using one of the following:
+ * `result.success(data)` — returns data to Dart
+ * `result.error(code, message, details)` — throws `PlatformException` in Dart
+ * `result.notImplemented()` — throws `MissingPluginException` in Dart
+- Do **not** call `result` multiple times. Flutter expects a one-time, one-result reply per method call.
+- If your native call involves I/O, network, or anything that blocks, use a background thread:
+```js
+ Thread(Runnable {
+ val resultData = longRunningOperation()
+ runOnUiThread {
+ result.success(resultData)
+ }
+ }).start()
+```
+
+
+
+
+
+### 3. iOS Side (Swift)
+
+In iOS, the platform channel is handled via `FlutterMethodChannel` in `AppDelegate.swift`. Similar to Android, the method call handler runs on the **main thread** by default.
+
+**Setting Up the Channel:**
+
+```js
+import UIKit
+import Flutter
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ let controller = window?.rootViewController as! FlutterViewController
+ let batteryChannel = FlutterMethodChannel(name: "com.example/device",
+ binaryMessenger: controller.binaryMessenger)
+```
+
+**Handling the Method Call:**
+
+```js
+ batteryChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
+ if call.method == "getBatteryLevel" {
+ UIDevice.current.isBatteryMonitoringEnabled = true
+ let level = UIDevice.current.batteryLevel
+ if level >= 0 {
+ result(Int(level * 100))
+ } else {
+ result(FlutterError(code: "UNAVAILABLE",
+ message: "Battery level not available.",
+ details: nil))
+ }
+ } else {
+ result(FlutterMethodNotImplemented)
+ }
+ }
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
+```
+
+**Notes:**
+
+* Always return exactly one response per method call.
+* Use `FlutterError` to send detailed error info to Dart.
+* If needed, use `DispatchQueue.global().async` to run long tasks in the background, then return via `DispatchQueue.main.async`.
+
+
+### Best Practices on MethodChannels
+
+To implement **MethodChannels** successfully:
+
+* **Use consistent channel and method names** between Dart and native code.
+* **Use standard types** for data exchange (prefer `String`, `int`, `bool`, `List`, `Map`).
+* **Always handle errors** clearly on both sides.
+* **Offload long-running native logic** to background threads.
+* **Keep the native side minimal and testable**, separating SDK logic from channel code where appropriate.
+
+By following these steps and patterns, you’ll be able to bridge Flutter with native code cleanly—supporting deep platform integrations while maintaining a smooth UI and maintainable codebase.
+
+## Integrating MethodChannels in FlutterFlow
+
+FlutterFlow is a visual development platform that generates complete Flutter applications. While it supports writing custom Dart code through **Custom Actions** and **Custom Functions**, it does not allow direct editing of platform-native code (Kotlin, Swift) through its web UI. This introduces some important considerations when integrating Flutter’s `MethodChannel` API for platform-specific functionality.
+
+**Step 1: Create a Custom Flutter Plugin**
+
+**1.1 Initialize the Plugin**
+
+Use the Flutter CLI to create a new plugin:
+
+```jsx
+flutter create --template=plugin --platforms=android,ios my_custom_plugin
+```
+
+This command sets up a plugin project with the necessary structure for both Android and iOS platforms.
+
+**1.2 Implement Platform-Specific Code**
+
+Within the generated plugin, navigate to the platform-specific directories (`android` and `ios`) to implement the desired functionality. For example, to retrieve the device's battery level:
+
+* **Android (Kotlin):** Modify `MyCustomPlugin.kt` to access the battery information using Android's `BatteryManager`.
+* **iOS (Swift):** Update `MyCustomPlugin.swift` to utilize `UIDevice` for battery level retrieval.
+
+**1.3 Publish to GitHub**
+
+After implementing and testing your plugin:
+
+1. Initialize a Git repository in your plugin directory.
+2. Commit your changes.
+3. Push the repository to GitHub.
+
+Ensure your `pubspec.yaml` is correctly configured, and consider tagging releases for versioning.
+
+
+**Step 2: Add the Plugin as a Dependency in FlutterFlow**
+
+To integrate your custom plugin into a FlutterFlow project:
+
+1. Navigate to **Custom Code \> Custom Actions** or **Custom Widgets** in FlutterFlow.
+2. Create a new Custom Action or Widget.
+3. In the **Settings** panel on the right, scroll to **Dependencies**.
+4. Add your plugin using the Git URL:
+
+ ```yaml
+ my_custom_plugin:
+ git:
+ url: https://github.com/yourusername/my_custom_plugin.git
+ ```
+
+5. In the code editor, import your plugin:
+
+ ```jsx
+ import 'package:my_custom_plugin/my_custom_plugin.dart';`
+ ```
+
+
+
+6. Implement the desired functionality using the plugin's API.
+
+For detailed guidance, refer to FlutterFlow's documentation on [using unpublished or private packages](https://docs.flutterflow.io/concepts/custom-code/#using-unpublished-or-private-packages).
+
+
+**Step 3: Utilize the Plugin via Custom Actions in FlutterFlow**
+
+With the plugin integrated, you can now create Custom Actions to leverage its functionality:
+
+1. Define a new Custom Action in FlutterFlow.
+2. In the code editor, implement the action using your plugin. For example:
+
+ ```jsx
+ Future getBatteryLevel() async {
+ final batteryLevel = await MyCustomPlugin.getBatteryLevel();
+ return batteryLevel;
+ }
+ ```
+
+
+3. Compile the custom code to ensure there are no errors.
+4. Use this Custom Action within your FlutterFlow project's action flows, just like any built-in action.
+
+This approach allows you to encapsulate complex logic within reusable actions, enhancing modularity and maintainability.
+
+
+### Managing Private Repositories
+
+If your plugin repository is private, FlutterFlow needs access to it. As per FlutterFlow's documentation, you may need to provide authentication credentials or use SSH keys. Refer to the [FlutterFlow documentation](../../ff-concepts/adding-customization/custom-code.md#using-unpublished-or-private-packages) for detailed instructions on integrating private packages.
+
+
+
+## Common Pitfalls and Debugging
+
+MethodChannels are powerful but require careful implementation. When the Dart and native sides are not aligned, or error handling is overlooked, it often leads to runtime issues or silent failures. This section outlines the most common problems developers face with MethodChannels, especially in projects generated by tools like FlutterFlow, and provides actionable solutions to help you debug effectively and write resilient platform-channel integrations.
+
+
+### MissingPluginException
+
+ **Symptom:** Flutter throws a `MissingPluginException`, typically saying the plugin or method is not implemented.
+
+ **What it means:** Flutter tried to invoke a method on the MethodChannel, but the native side did not recognize the channel or method name.
+
+ **Common causes:**
+
+ * Dart `MethodChannel` name does not match the native channel name.
+ * Native code handler (`setMethodCallHandler`) was never set up or was incorrectly placed.
+ * Custom native code was overwritten when re-downloading a FlutterFlow project without preserving changes.
+ * The method was invoked before the Flutter engine or the channel was fully initialized.
+ * Hot reload only updates Dart code, but not with native channel implementations.
+
+ **How to fix:**
+
+ * Confirm that the channel name is **identical** in Dart and native code (case-sensitive).
+ * On Android, ensure the channel is registered inside `configureFlutterEngine()`.
+ * On iOS, set up the `FlutterMethodChannel` inside `didFinishLaunchingWithOptions()`.
+ * Log the available channels/methods to confirm registration during app startup.
+ * Native channel implementations require a full restart because the platform-specific code must be recompiled and relinked.
+
+
+
+### Incorrect Argument or Result Types
+
+ **Symptom:** App crashes with type casting errors or returns `null` unexpectedly.
+
+ **What it means:** The data passed between Dart and native does not match expected formats.
+
+ **Common causes:**
+
+ * Dart sends an argument as a Map but native expects a String, or vice versa.
+ * Native code returns a platform object that can't be serialized by Flutter.
+ * The return value is not compatible with `StandardMessageCodec`.
+
+ **How to fix:**
+
+ * Only use standard types: `int`, `double`, `String`, `bool`, `List`, or `Map` with JSON-safe contents.
+ * On Dart side, specify the expected return type with generics: `invokeMethod(...)`.
+ * On native side, validate input types before using them. Consider using try/catch or safe casting.
+ * Avoid sending complex objects like native SDK responses directly—convert to a simple dictionary or string.
+
+
+### No Response or App Hangs
+
+**Symptom:** The Dart call to `invokeMethod()` never returns, or the UI freezes.
+
+**What it means:** The native side didn’t complete the method call correctly, or a long-running task is blocking the UI thread.
+
+**Common causes:**
+
+* Native method handler fails to call `result.success`, `result.error`, or `result.notImplemented`.
+* The method call handler throws an exception that prevents the response from being sent.
+* Heavy logic (e.g., file I/O, network calls) is blocking the main thread.
+
+**How to fix:**
+
+* Always call one—and only one—of the result callbacks.
+* Wrap native code in try/catch blocks to catch and report any exceptions.
+* Offload slow operations to a background thread or coroutine (Kotlin) or dispatch queue (Swift).
+* Use Dart timeouts or loading indicators to keep the UI responsive while waiting.
+
+### Calling `result` Multiple Times
+
+**Symptom:** The app crashes with a runtime error like "Reply already submitted" or shows inconsistent results.
+
+**What it means:** The native code responded more than once for the same method call.
+
+**Common causes:**
+
+* Both success and error branches are executed due to logic errors.
+* Async operations or callbacks race to return multiple responses.
+* A timeout, retry, or exception causes unintended second calls.
+
+**How to fix:**
+
+* Track whether a response has been sent using a flag (e.g., `var responded = false`).
+* Use return statements or guards to prevent multiple result calls.
+* Structure async callbacks carefully to ensure only one callback path runs.
+
+
+### Debugging Tips by Platform
+
+**Flutter/Dart:**
+
+* Use `print()` or `debugPrint()` to log method calls and results.
+* Always wrap `invokeMethod` in `try/catch` and log exceptions.
+* Add logs before and after `invokeMethod()` to verify flow.
+* Use Flutter DevTools to inspect console logs and application state.
+
+**Android (Kotlin/Java):**
+
+* Use `Log.d("MethodChannel", "Received: ${call.method}")` inside the handler.
+* Use `adb logcat | grep flutter` to filter platform logs.
+* Ensure `configureFlutterEngine()` is actually called—older project setups may require manual configuration.
+* Use breakpoints in Android Studio for step-by-step inspection.
+
+**iOS (Swift/Objective-C):**
+
+* Use `print()` or `NSLog()` to trace handler execution.
+* Watch the Xcode console for startup logs or channel registration issues.
+* Ensure you're calling `result(...)` correctly and only once.
+* Check if the `AppDelegate` is properly casting `window?.rootViewController` to `FlutterViewController`.
+
+
+By understanding and anticipating these pitfalls, developers can avoid common errors that derail Flutter-to-native communication. MethodChannels are extremely reliable when implemented correctly, and with structured debugging, most issues can be diagnosed and resolved quickly—even in FlutterFlow-generated apps where visibility into the build system may be limited.
+
+## Performance and Architecture Best Practices
+
+Integrating native functionality through MethodChannels can bring significant value to your app \- but only if it’s done with performance and maintainability in mind. Below are the five most important best practices engineers should apply in real-world production apps, along with deeper insights into why each one matters.
+
+:::info[Important Context for FlutterFlow Users]
+FlutterFlow generates clean Dart code and supports Custom Actions for inserting Dart logic, but it does not currently support inline native (Kotlin/Swift) editing.
+:::
+
+### Don’t Block the Main Thread
+
+* By default, all MethodChannel calls are handled on the **main UI thread**, which is also responsible for rendering the app.
+* Native operations like database access, file I/O, Bluetooth scanning, or network requests **must** be moved off the main thread.
+* Use background threads (e.g., `Executors` or `coroutines` on Android, `DispatchQueue.global()` on iOS) to perform long-running tasks.
+* Return results on the main thread using `runOnUiThread` (Android) or `DispatchQueue.main.async` (iOS).
+
+Blocking the UI thread for even a few milliseconds can cause dropped frames, janky animations, and a visibly unresponsive app, especially on mid-range devices.
+
+:::tip
+While UI interactions and workflows look smooth inside FlutterFlow, once you export and test the app on a real device, slow operations in Kotlin or Swift can still freeze the app. Always delegate those tasks to background threads before calling back into Dart.
+:::
+
+### Keep MethodChannel Code Minimal
+
+* Your MethodChannel handler should act like a **controller**, not a service. It should delegate execution to well-structured, modular native components.
+* This keeps the interface between Dart and native thin and easy to maintain.
+* For example, `getBatteryLevel` in Kotlin should just delegate to `BatteryService().getLevel()`.
+* This separation helps native teams evolve platform code independently of Flutter UI updates.
+
+Clean separation of concerns leads to better test coverage, easier onboarding, and avoids hard-to-debug cross-layer bugs.
+
+
+
+### Use Only JSON-Compatible Data
+
+* The Flutter engine uses `StandardMessageCodec` for MethodChannel communication.
+* It supports only a limited set of Dart-native types: `int`, `double`, `bool`, `String`, `List`, `Map`, and `null`.
+* Any native types (e.g., `Bitmap`, `Bundle`, `NSData`, `UIColor`) must be converted to a JSON-friendly structure first.
+* If data is complex (e.g., a barcode result or device info), serialize it to a flat Map or a JSON string before sending it across.
+
+Type mismatches across the bridge don’t fail at compile time—they crash at runtime. Keeping your types simple prevents hard-to-diagnose issues.
+
+:::tip
+When using Dart Custom Actions that invoke MethodChannels, ensure the return values can be used in FlutterFlow bindings. Only supported types (like `String` or `int`) can be stored in App State or used in conditions or widgets.
+:::
+
+### Validate and Sanitize Dart Inputs
+
+* Treat incoming Dart method calls like external API requests. Assume they can be malformed.
+* Use pattern matching (switch/case or `when`) to route and verify each method call.
+* Validate presence and type of arguments before using them. For example:
+
+```js
+val timeout = call.argument("timeout") ?: return result.error("INVALID", "Missing timeout", null)
+```
+
+* Defensive coding helps avoid unexpected behavior, native crashes, or incorrect hardware usage.
+
+Dart developers might call your method incorrectly. Native code must fail safely and visibly.
+
+:::tip
+Custom Actions in FlutterFlow can include parameters from the UI, but if the parameter isn’t set or passed correctly in a workflow, the Dart code will still execute. Validate these inputs natively before use.
+:::
+
+### Log Clearly on Both Sides
+
+* Add logging on both Dart and native layers for every MethodChannel call:
+ * What method was called?
+ * What were the arguments?
+ * What was returned, and how long did it take?
+* Use structured logs (`Log.d("MethodChannel", "method=... args=... result=...")` on Android, `NSLog` or `print()` on iOS).
+* Align log timestamps across layers to help trace issues during debugging sessions.
+
+When something goes wrong in production, good logs make the difference between a 10-minute fix and a multi-day investigation.
+
+:::tip
+Use `debugPrint()` inside Dart Custom Actions to log output alongside platform logs. In test builds, these logs help verify whether native results are arriving as expected.
+:::
+
+
+
+## Summary & Guidance
+
+MethodChannels are a foundational tool for extending the power of your app beyond what plugins alone can provide. They allow direct access to platform-native APIs and SDKs, enabling teams to solve tough integration challenges and deliver production-grade features with full control.
+
+But like any system boundary, MethodChannels require disciplined design. Misuse can lead to fragile bridges, performance bottlenecks, and increased maintenance overhead. When implemented thoughtfully, MethodChannels provide:
+
+* A clean interface between Dart and native layers
+* Strategic reuse of platform-optimized SDKs and APIs
+* A clear path to ship advanced features without waiting on plugin ecosystems
+* A sustainable integration model that scales with your team and product
+
+Flutter will continue to evolve with innovative solutions for platform interoperability in the future through two key tools: FFIgen and JNIgen. FFIgen automates the creation of Objective-C and Swift API bindings, while JNIgen handles Java and Kotlin API connections, making native code integration more streamlined and maintainable across platforms.
\ No newline at end of file
diff --git a/docs/ff-concepts/alerts-notification/_category_.json b/docs/ff-concepts/alerts-notification/_category_.json
deleted file mode 100644
index 8eee25c8..00000000
--- a/docs/ff-concepts/alerts-notification/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "Alerts & Notifications",
- "position": 8
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/alerts-notification/push-notifications.md b/docs/ff-concepts/alerts-notification/push-notifications.md
deleted file mode 100644
index 8a10cac0..00000000
--- a/docs/ff-concepts/alerts-notification/push-notifications.md
+++ /dev/null
@@ -1,298 +0,0 @@
----
-title: Push Notifications
-slug: /concepts/alerts-notification/push-notifications
-sidebar_position: 2
-tags: [Actions, Alerts & Notifications, Integration]
-keywords: [FlutterFlow, Actions, Alerts & Notifications, Push Notifications]
----
-
-
-# Push Notifications
-
-Push notifications allow you to send timely and relevant information to a user's phone. From this page, you can enable the push notification feature in your app. After enabling it, you can send the push notification instantly or schedule it to be delivered to the user's device at a specific time.
-
-:::info[Behind the scenes]
-FlutterFlow uses [**Firebase Cloud Messaging**](https://firebase.google.com/docs/cloud-messaging) (A Firebase product) to send push notifications.
-:::
-
-
-:::note[General Prerequisites]
-
-Before getting started with this section, ensure you have:
-
-* Completed all steps in the
-[**Firebase Setup**](../../ff-integrations/firebase/connect-to-firebase-setup.md).
-* Upgraded to a [**Blaze plan**](https://firebase.google.com/pricing) for your Firebase project.
-:::
-
-:::note[iOS Prerequisites]
-
-These steps are mandatory if you want to send push notifications to iOS devices:
-
-* Created an [**Apple account**](https://appleid.apple.com/account?appId=632&returnUrl=https%3A//developer.apple.com/account/).
-* [**Purchased an Apple Developer membership**](https://developer.apple.com/programs/enroll/). Please see [this link](https://developer.apple.com/programs/) for more details on the Apple Developer program and how to sign up.
-
-:::
-
-## Add push notifications
-
-Here are the steps to send push notifications:
-
-### Enabling push notification
-
-:::warning
-**Please note, push notifications will not work in these scenarios:**
-
-* Push notifications will not work on an iOS simulator. To test you will need to use a real device.
-* Push notifications will not be delivered to users who are logged out of your app. To send push notifications to users who are not logged in, consider implementing [**Anonymous Firebase Login**](../../ff-integrations/authentication/firebase-auth/anonymous-login.md) within your app
-* Push notifications will not work if you have the app open on your device.
-:::
-
-To enable push notifications:
-
-1. Navigate to the **Settings and Integrations -> App Settings -> Push Notifications** and
-**Enable Push Notifications**.
-2. Now, click on the **Deploy** button. This will create and deploy the *Cloud Functions* in your
- Firebase project that are necessary for push notifications to work.
-
-
-
-:::info
-By default, the **Automatically Prompt Users for Permission** option is enabled, meaning your app will automatically prompt users requesting for permission to receive push notifications when the app is started. However, this may be disruptive to your user sign-in flow.
-
-If you disable it, you can control when the permission is requested. To do so, you will need to manually [**Request Permission**](../../resources/projects/settings/project-setup.md#request-permission-action) at the appropriate point in your app. **It is recommended to keep this option always enabled**.
-:::
-
-### Only for iOS: Configuring iOS app
-
-To receive the push notifications in an iOS app, you need to perform the following additional steps.
-
-#### 1. Creating a key
-
-Apple requires developers to create a key for the push notifications inside the *Apple Developer Console* to verify the push notification's sender.
-
-To create a key:
-
-1. From your Apple developer account, open the [**keys**](https://developer.apple.com/account/resources/authkeys/list) section.
-2. Click on the **(+)** button on the right side of the **Keys** label.
-3. Enter the **Key Name**.
-4. Select the **Apple Push Notifications service (APNs)** from the list below.
-5. Click on **Continue** and then **Register**.
-6. Click **Download** and save the file. It will be needed to add to your Firebase project.
-
-
-
-
-
-#### 2. Add APNs key to Firebase project
-
-To add APNs key to Firebase project:
-
-1. From the Firebase dashboard from your project, navigate to the far left menu. Select Project
- Settings( ) --> Project Settings.
-
-2. Select the **Cloud Messaging** tab.
-
-3. Scroll down and find your iOS app under the **Apple app configuration** section.
-
-4. Under the **APNs Authentication Key** section, click on **Upload**. A popup will appear to
- upload and enter the key details.
-
-5. Click on the **Browse** button to locate and upload the APNs auth key file.
-
-6. Enter the *Key ID*. You can find your Key ID in the Apple Developer Center under [Certificates,
- Identifiers & Profiles](https://developer.apple.com/account/resources) -> [Keys](https://developer.apple.com/account/resources/authkeys/list) -> Click on **Key**.
-
-7. Enter the *Team ID*. You can find your Team ID in the Apple Member Center under the [membership
- tab](https://developer.apple.com/account/#/membership).
-
-
-
-
-
-#### 3. Adding identifier
-
-You must add an Identifier to be able to send the push notifications to the iOS devices after you deploy your app to the app store.
-
-To add an Identifier:
-
-1. From your *Apple developer account* open the [**Identifiers**](https://developer.apple.com/account/resources/identifiers/list) section.
-
-2. Click on the **(+)** button on the right side of the **Identifiers** label.
-
-3. Select the **App IDs** and click **Continue**.
-
-4. Select the *Type* **App** and click **Continue.**
-
-5. Enter the **Description** as **ImageNotification.**
-
-6. Enter the **Bundle ID** as your package name and add **.ImageNotification** in the end.
-
-7. Click **Continue** and then click **Register**.
-
-
-
-
-
-#### 4. Enable push notifications in your App ID
-
-:::note
-Continue with this step only if you have an APP or Bundle ID created in your developer account.
-:::
-
-Add the 'Push Notifications' capability to your existing App ID in order to avoid any issues when you re-deploy your app. Here's how you do it:
-
-1. From your *Apple developer account,* open the [**Identifiers**](https://developer.apple.com/account/resources/identifiers/list) section.
-
-2. Open the identifier with your existing APP ID.
-
-3. Select **Push Notifications** from the list and click **Save**.
-
-
-
-
-
-### Sending push notifications
-
-Use these steps to create and send push notifications:
-
-1. Click on the **Settings and Integrations** -> App Settings -> **Push Notifications**.
-
-2. Find the **Manually Trigger Notifications** section and click on it to expand the section.
-
-3. In the **Notification Title**, enter the text that you want to set as a title for notification.
-
-4. In the **Notification Text**, enter the content of your notification.
-5. Optional: Click on the **Upload Notification Image** to set the image that you want to appear in the notification.
-6. Find the **Target Audience** dropdown. Keep the **All** option selected if you want to send notifications to both *Android* and *iOS* users. You can select **Android** or **iOS** if you wish to target OS-specific users.
-7. Enable **Deliver With Sound** if you wish to.
-8. If you have more than 10K users, you might want to enable the **Batch Notifications**.
-9. To send push notifications to a specific or few users, enter the user document reference (from the 'users' collection in Firestore) into the *User References*.
-10. Find the **Initial Page** dropdown and select a page that you would like to open when a user clicks on the notification.
-11. Click on **Send Notification**.
-12. To confirm you want to send this notification, a popup will appear. You need to enter the text '**Send Notification**' and click on **Send Notification** again.
-
-
-
-
-
-## Push notifications with data
-
-Sometimes you might want to include additional data with your push notifications, which can then be used to display more detailed information on the page when it's opened through a push notification.
-
-For instance, consider a news app that sends push notifications for breaking news. When the user taps the notification, the additional data could include the news article's title, summary, and image.
-
-:::warning[Note]
-Currently we only support sending *Firestore document references* as data.
-:::
-
-To send a push notification with data:
-
-1. You must have a page that accepts a parameter of type 'DocumentReference'.
-2. Build a notification using the instructions [here](#add-push-notifications).
-3. Set the **Initial Page** to the one that accepts the parameter.
-4. Find the **Parameter Data** section, copy the document reference from the Firestore, and paste it into the input box below.
-5. Click on **Send Notification**.
-
-
-
-
-
-## Trigger push notification
-
-You might want to send a push notification when something happens in your app. For example, sending a push notification on a message sent, a push notification on a new appointment booked, a push notification on a price change, etc.
-
-You can send the push notification on such event occurrence by adding the **Trigger Push Notification** action.
-
-For demonstration purposes, consider an example of sending a push notification to a post creator when someone comments on a post.
-
-
-
-
-
-Here are the steps:
-
-### 1. Retrieve the document reference of the user
-
-The document reference of the user is required to send a push notification to a specific user, in this case, it would be the document reference of the post creator.
-
-Normally, you would obtain the user document reference from the Firestore document, where a field like 'created_by' stores the document reference of the post creator. However, for the sake of simplicity, let's assume that we are storing this reference in an app state variable, which looks like this:
-
-
- 
- User document reference in app state variable
-
-
-If you need to send push notifications to multiple users, consider a scenario where you want to notify all users who liked a post when someone comments on it. You can retrieve the list or array of user document references from the Firestore document or any app state variable within your app. Here's what a list of document references in an app state variable might look like:
-
-
- 
- Multiple user document references in app state variable
-
-
-:::info
-Learn more about working with
-[**App State variables**](../../resources/data-representation/app-state.md).
-:::
-
-### 2. Trigger Push Notification [Action]
-
-Using this action, you can trigger the push notification when an event occurs in your app. For example, sending the push notification to the post creator when someone comments on a post.
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., IconButton, Button, etc.) on which you want to add the action.
-
-2. Select **Actions** from the Properties Panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
- 1. Click on the **+ Add Action**.
-
- 2. On the right side, search and select the **Trigger Push Notification** action.
- 3. To set who should receive the push notification, set the **Audience** to **Single
- Recipient** or **Multiple Recipient**.
- * If you want to send a notification to a single user, set it to 'Single Recipient'. For example, sending a notification only to the group creator when someone joins the group.
- * If you want to send a notification to multiple users, set it to 'Multiple Recipients'. For example, sending a notification to all group members when someone joins the group.
- 4. Set the **Source** of user document reference (e.g., app state variable or Firestore document).
- 5. Further options are available based on the selected source.
- 6. To set the specific notification title text, enter the **Notification Title**.
- 7. You can set the **Notification Text** from a variable.
- 8. Optional: Open the **Notification Image** section to set the image that you want to appear in the notification.
- 9. Turn on the **Deliver with Sound** if you want to send a notification with the user's default sound/vibration.
- 10. To set which page to open when a user taps the notification, set the **Initial Page** to the page you would like to open. You can also [pass on the parameters](#push-notifications-with-data) if page requests.
-
-
-
-
-
-
----
-
-## FAQs
-
-
-Push notifications not working; Getting cloud function error: PERMISSION_DENIED: Missing or insufficient permissions
-
-If you encounter an error with push notifications, specifically a cloud function failure due to permission issues, it might be related to your Google Cloud organization's settings. Organizations can disable automatic IAM grants for default service accounts, leading to this error.
-
-To fix this issue, manually grant the Editor role to the default service account used by your project. You can do this by visiting the GCP IAM page and assigning the Editor role to the following service account:
-
-- For App Engine (Gen 1): `{firebase-project-id}@appspot.gserviceaccount.com`
-- For Compute Engine (Gen 2): `{project-number}-compute@developer.gserviceaccount.com`
-
-
-
-Also, ensure that these principals (emails) and their roles are present in the permissions tabs in *App Engine Default service account*, *Default compute service account*, and *firebase-adminsdk*. You can do this by visiting the GCP Service Accounts page, clicking on each service account email, and granting access to these principals in the permissions tab.
-
-Below is a sample image for App Engine Default service account.
-
-
-
-
-
diff --git a/docs/ff-concepts/alerts/_category_.json b/docs/ff-concepts/alerts/_category_.json
new file mode 100644
index 00000000..bbed890b
--- /dev/null
+++ b/docs/ff-concepts/alerts/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Alerts",
+ "position": 8
+}
\ No newline at end of file
diff --git a/docs/ff-concepts/alerts-notification/alert-dialog.md b/docs/ff-concepts/alerts/alert-dialog.md
similarity index 99%
rename from docs/ff-concepts/alerts-notification/alert-dialog.md
rename to docs/ff-concepts/alerts/alert-dialog.md
index 022c69d9..deed8936 100644
--- a/docs/ff-concepts/alerts-notification/alert-dialog.md
+++ b/docs/ff-concepts/alerts/alert-dialog.md
@@ -1,6 +1,6 @@
---
title: Alert Dialog
-slug: /concepts/alerts-notification/alert-dialog
+slug: /concepts/alerts/alert-dialog
sidebar_position: 0
tags: [Actions, Alerts & Notifications]
keywords: [FlutterFlow, Actions, Alerts & Notifications, Alert Dialog]
diff --git a/docs/ff-concepts/alerts-notification/dismiss-custom-dialog.md b/docs/ff-concepts/alerts/dismiss-custom-dialog.md
similarity index 97%
rename from docs/ff-concepts/alerts-notification/dismiss-custom-dialog.md
rename to docs/ff-concepts/alerts/dismiss-custom-dialog.md
index a5b8ba41..c3b3d2b7 100644
--- a/docs/ff-concepts/alerts-notification/dismiss-custom-dialog.md
+++ b/docs/ff-concepts/alerts/dismiss-custom-dialog.md
@@ -1,6 +1,6 @@
---
title: Dismiss Custom Dialog
-slug: /concepts/alerts-notification/dismiss-custom-dialog
+slug: /concepts/alerts/dismiss-custom-dialog
sidebar_position: 1
tags: [Actions, Alerts & Notifications]
keywords: [FlutterFlow, Actions, Alerts & Notifications, Dismiss Custom Dialog]
diff --git a/docs/ff-concepts/alerts-notification/haptic-feedback.md b/docs/ff-concepts/alerts/haptic-feedback.md
similarity index 97%
rename from docs/ff-concepts/alerts-notification/haptic-feedback.md
rename to docs/ff-concepts/alerts/haptic-feedback.md
index aa73b601..095e0307 100644
--- a/docs/ff-concepts/alerts-notification/haptic-feedback.md
+++ b/docs/ff-concepts/alerts/haptic-feedback.md
@@ -1,6 +1,6 @@
---
title: Haptic Feedback
-slug: /concepts/alerts-notification/haptic-feedback
+slug: /concepts/alerts/haptic-feedback
sidebar_position: 4
tags: [Actions, Alerts & Notifications]
keywords: [FlutterFlow, Actions, Alerts & Notifications, Haptic Feedback]
diff --git a/docs/ff-concepts/alerts-notification/imgs/adding-dismiss-custom-dialog-action.png b/docs/ff-concepts/alerts/imgs/adding-dismiss-custom-dialog-action.png
similarity index 100%
rename from docs/ff-concepts/alerts-notification/imgs/adding-dismiss-custom-dialog-action.png
rename to docs/ff-concepts/alerts/imgs/adding-dismiss-custom-dialog-action.png
diff --git a/docs/ff-concepts/alerts-notification/imgs/align-custom-dialog.avif b/docs/ff-concepts/alerts/imgs/align-custom-dialog.avif
similarity index 100%
rename from docs/ff-concepts/alerts-notification/imgs/align-custom-dialog.avif
rename to docs/ff-concepts/alerts/imgs/align-custom-dialog.avif
diff --git a/docs/ff-concepts/alerts-notification/imgs/custom-dialog.avif b/docs/ff-concepts/alerts/imgs/custom-dialog.avif
similarity index 100%
rename from docs/ff-concepts/alerts-notification/imgs/custom-dialog.avif
rename to docs/ff-concepts/alerts/imgs/custom-dialog.avif
diff --git a/docs/ff-concepts/alerts-notification/imgs/img.png b/docs/ff-concepts/alerts/imgs/img.png
similarity index 100%
rename from docs/ff-concepts/alerts-notification/imgs/img.png
rename to docs/ff-concepts/alerts/imgs/img.png
diff --git a/docs/ff-concepts/alerts-notification/imgs/img_1.png b/docs/ff-concepts/alerts/imgs/img_1.png
similarity index 100%
rename from docs/ff-concepts/alerts-notification/imgs/img_1.png
rename to docs/ff-concepts/alerts/imgs/img_1.png
diff --git a/docs/ff-concepts/alerts-notification/imgs/img_2.png b/docs/ff-concepts/alerts/imgs/img_2.png
similarity index 100%
rename from docs/ff-concepts/alerts-notification/imgs/img_2.png
rename to docs/ff-concepts/alerts/imgs/img_2.png
diff --git a/docs/ff-concepts/animations/widget_animations.md b/docs/ff-concepts/animations/widget_animations.md
index 30a4c76f..d25830bf 100644
--- a/docs/ff-concepts/animations/widget_animations.md
+++ b/docs/ff-concepts/animations/widget_animations.md
@@ -208,7 +208,7 @@ If you notice carefully, the items appear in a staggered fashion. This can be ac
Select the item in the list and add the Slide animation.
-In the Delay property, open the variable menu and add a [code expression](../../resources/control-flow/functions/utility-functions.md#code-expressions) to calculate the delay value based on the item's index. For this example, we use the formula `[index] * 100`, where `index` represents the position of the item, and `100` is the delay in milliseconds. This means the first item will slide in after 100 ms, the second after 200 ms, and so on, creating a staggered animation effect.
+In the Delay property, open the variable menu and add a [inline function](../../resources/control-flow/functions/utility-functions.md#inline-function-code-expressions) to calculate the delay value based on the item's index. For this example, we use the formula `[index] * 100`, where `index` represents the position of the item, and `100` is the delay in milliseconds. This means the first item will slide in after 100 ms, the second after 200 ms, and so on, creating a staggered animation effect.
Design System**.
-2. Click **Create Design Library**.
-3. Enter the **Design Library Project Name**.
-4. Now you can configure the Colors, Typography & Icons, App Assets, NavBar & AppBar, and Theme Settings.
-5. To see how the app will look for the new design system, you can open it in preview mode (click the eye icon at the top right side).
+- **Enterprise Applications:** Large organizations can develop a centralized design system as a library to ensure all internal applications maintain a cohesive look and feel, enhancing brand identity and user experience.
+- **Startup MVPs:** Startups can expedite the development of Minimum Viable Products (MVPs) by leveraging a pre-built design system library like [**shadcn**](https://marketplace.flutterflow.io/item/cNlm0zWW1Nfq11cFXBmp), allowing them to focus on functionality and user validation.
+- **Cross-Platform Consistency:** Teams aiming to deploy apps across multiple platforms (iOS, Android, Web) can use a popular platform based design system library to ensure uniformity in design, reducing the effort required for platform-specific adjustments.
-
-
-
-
-
-
-
-
-6. To use the design system, open your project and navigate to **Theme Settings > Design System**.
-7. Click on the **No Design System Selected**.
-8. A pop will open displaying the list of the design systems, click on the newly created design system to add it to your project. **Note** that the design system created in [My Organization](../../resources/projects/how-to-collaborate-on-projects.md#sharing-a-project-with-an-organization) will also be available here.
+:::
-:::info
-After selecting the design system, you can't change the Colors, Typography, and Theme Widgets.
+To add a design system from a library, start by creating the design system in a new FlutterFlow project and [publishing it as a library](../../resources/projects/libraries.md#publishing-a-library). Next, [import](../../resources/projects/libraries.md#importing-a-library) that library into the project where you want to use the design system. Then, navigate to **Theme Settings > Design System** and click **No Design System Selected**. From the dropdown that appears, **Select a library** you’ve just imported to apply its design system to your project.
-:::
----
## Import Figma Theme
-You might use Figma to design your app and build it accordingly in our builder. If you have a lot of colors and text styles, importing them manually can take some time. You can now import the whole Figma theme, which includes the colors and text styles, directly into our builder.
+You can bring your Figma design system directly into your FlutterFlow project. This streamlines the design-to-development process by automatically importing colors and typography from your Figma file, helping you maintain visual consistency and reduce manual effort.
-:::info
+To import a Figma theme into your FlutterFlow project, go to **Theme Settings > Design System** and click **Connect To Figma**. Authenticate your account and grant access to Figma. Once connected, paste your Figma file URL to fetch the theme.
-Before you import the Figma theme, ensure you have access to the Figma design file and [**generate the access token**](https://help.figma.com/hc/en-us/articles/8085703771159-Manage-personal-access-tokens).
+You’ll see a list of all imported colors; start mapping them to your project colors. You can filter these colors by whether they’re mapped or unmapped, and you also have the option to bulk delete any imported colors. After that, you can customize your project typography using the imported text styles.
+:::info
+All imported colors are accessible anytime under **Colors > Custom Colors**.
:::
-To import the Figma theme:
-
-1. Open the **Theme Settings > Design System**.
-2. Click the **Import Figma Theme** button. This will open a new popup.
-3. Enter your **Figma File URL** and **Personal Access Token**. The *Personal access tokens* allow us to access all of your files and data in Figma.
-4. Click **Import Figma Theme**.
- 1. Now, you'll see a list of colors from your Figma file, and here you can decide which one to keep. If everything looks good to you, Click **Import & Continue**.
- 2. You can replace the current theme colors with new/imported ones. Click on any color, and the dropdown will display all imported colors. Click on the new color to replace it. When done, click **Save & Continue**.
- 3. If you have custom text styling in your Figma file, it will be displayed here, and you can choose which one to import. Click **Import & Continue**.
- 4. Replace any existing style with the new one and click **Save & Finish**.
-5. Finally, click **Finish & Close**.
-
+:::tip
+Avoid mis-sized loading indicators or components, which lead to jumping layouts. Ensure loading components match the size and position of the content they replace.
+:::
+
If you prefer watching a video tutorial, here is the guide for you:
-
-
-
-
+You can also create fully custom text styles to match your design needs, going beyond the default styles like Display, Headline, or Title. Simply click the **+ Add Custom Text Style** button, a new text style will be added at the bottom, then edit the style name and customize the style properties.
+
+
+
+:::tip[PLANS]
+Custom Text Styles are available on the **Business** plan and higher. Check our [**pricing plans**](https://flutterflow.io/pricing).
+:::
#### Adding responsive text styles
@@ -675,12 +617,12 @@ You can add the responsive style by following the instructions below:
-### Adding Custom Fonts
+### Custom Fonts
Adding Custom Fonts to your app makes it stand out from others. This section allows you to upload your own fonts. You can upload the custom font files of types `.ttf`, `.otf`, and `.woff.` Once the font is uploaded, you can use it directly from the widget or add it to the text style section to create a general theme.
:::info
-Before you upload the *Custom Fonts*, make sure you have permission to use the font in your application.
+Before you upload the Custom Fonts, make sure you have permission to use the font in your application.
:::
To add the *Custom Fonts*:
@@ -748,17 +690,20 @@ If you prefer watching a video tutorial, here's the one for you:
-### Adding Custom Icons
+### Custom Icons
+
+Custom icons help reinforce your brand identity and add a unique touch to your app. Before uploading icons to FlutterFlow, you’ll first need to generate them using an icon font generator like [FlutterIcon](https://www.fluttericon.com/) or [IcoMoon](https://icomoon.io/).
+
+We’ve also built our **[own SVG to Custom Icon Generator](https://icons.flutterflow.app)** to make the process even easier — feel free to use that instead.
-Adding *Custom Icons* to your app helps you build the brand identity. Before you add the Custom Icons in FlutterFlow, you need to generate them from any icon generation site (like [fluttericon](https://www.fluttericon.com/) and [iconmoon](https://icomoon.io/)) and export them using appropriate settings.
:::info
-Make sure you have permission to use the icons in your application.
+Make sure you have the proper rights or licenses to use the icons in your application.
:::
-To add custom icons:
+**Steps to Generate and Add Custom Icons**
-1. Head over to the [iconmoon](https://icomoon.io/app/#/select).
+1. Head over to the [IcoMoon](https://icomoon.io/app/#/select).
2. Import your custom icon (.svg) or select from the free icons set.
3. Select the **Generate Font** tab.
4. Click on the Settings button (gear icon) beside the download text on the bottom right side.
@@ -799,8 +744,10 @@ To add custom icons:
12. Now click on the **Upload Icon Info** button.
13. Select and upload the `filename.dart` under the downloaded folder (besides the fonts folder).
14. Click **Add Icons**.
-15. To use a custom icon, add the **Icon** widget, move to the properties panel, and scroll down to the **Icon** section.
-16. Click on the already selected icon, select the **Custom Icons** tab, and then select your icon.
+
+#### Use the Custom Icon
+
+To use a custom icon, add the **Icon** widget, move to the properties panel, and scroll down to the **Icon** section. Click on the already selected icon, select the **Custom Icons** tab, and then select your icon.
How is the theme widget different from creating a template and component?
The Theme Widget allows you to customize the visual appearance of a single widget, whereas templates consist of multiple widgets that create a unique UI layout with a specific purpose. On the other hand, components are fully-featured custom widgets that combine multiple widgets and actions to complete a task.
-
\ No newline at end of file
+
diff --git a/docs/ff-concepts/design-system/imgs/typography.avif b/docs/ff-concepts/design-system/imgs/typography.avif
new file mode 100644
index 00000000..6c769fcb
Binary files /dev/null and b/docs/ff-concepts/design-system/imgs/typography.avif differ
diff --git a/docs/ff-concepts/file-handling/audio/_category_.json b/docs/ff-concepts/file-handling/audio/_category_.json
deleted file mode 100644
index 23edcfe2..00000000
--- a/docs/ff-concepts/file-handling/audio/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "Audio",
- "position": 0
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/audio/audio-player.md b/docs/ff-concepts/file-handling/audio/audio-player.md
deleted file mode 100644
index f5645ca4..00000000
--- a/docs/ff-concepts/file-handling/audio/audio-player.md
+++ /dev/null
@@ -1,194 +0,0 @@
----
-title: AudioPlayer
-slug: /concepts/file-handling/audio-player
-sidebar_position: 0
-tags: [Media, Widget]
-keywords: [Media, AudioPlayer, Play Audio File]
----
-
-# AudioPlayer
-
-The AudioPlayer widget plays audio from uploaded assets or the URL link.
-
-## Adding AudioPlayer Widget
-
-Here's how you can add the AudioPlayer widget to your project:
-
-1. Drag the **AudioPlayer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Options** section.
-3. Find the **Title** property and enter the value to display the audio title. You can also set this from the variable, such as the app state variable, API response variable, Firestore document, and more. To do so, click on the **Set from Variable**.
-4. Find the **Path** property and enter the **URL** for the new audio file.
-5. By default, the audio stops when you move to another page using the **Pause on Forward Navigation** property.
-6. When an app goes in the background while the audio player is running, you can control the audio player's behavior using the **Play in Background** property, which has following options:
- 1. **Enabled**: This keeps the audio player running.
- 2. **Disabled, restore on foreground**: This pauses the audio player and starts playing again as soon as the app is visible.
- 3. **Disabled, pause**: This stops the audio player as soon as the app goes in the background.
-
-:::info
-By default, every AudioPlayer widget added to the project will play a sample audio file from a network URL.
-:::
-
-
-
-
-
-
-
-## Use Audio from assets
-
-By default, the widget is set to play audio from the internet. However, you can change this to use the audio uploaded directly to your app.
-
-Here's how you can change the audio type:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Options** section.
-3. Find the **Audio Type** dropdown and select **Asset**.
-4. Now, find the **Asset Audio** property, click the **Upload Audio** button, select the audio and upload it.
-
-
-
-
-
-
-
-:::info
-Once you upload the audio, you can use it throughout your app. You can manage your uploaded audio files with the Project Media Asset Manager.
-:::
-
-To use the uploaded audio:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Options** section.
-3. Find the **Audio Type** dropdown and select **Asset**.
-4. Click on **No asset select** (inside the dropdown) and choose the audio.
-
-
-
-
-
-
-
-
-## Customization
-
-You can customize the appearance of this widget using the various properties available under the properties panel.
-
-### Changing colors
-
-To change the audio tile colors:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Player Properties** section.
-3. To change the background color of the tile, Find the **Fill Color** property click on the box next to the already selected color, select the color, and then click **Use Color** or click on an already selected color and enter a Hex Code directly. You can also choose the color by clicking the **Palette** and **Simple** button.
-4. Similarly, you can change the **Playback Button Color** (play and pause button) and **Active Track Color** (the bar color that shows the progress of the currently playing audio).
-
-### Changing elevation
-
-To change the elevation (depth or Z-axis) of the audio tile:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Player Properties** section.
-3. Find the **Elevation** input box and enter the value to see the drop shadow effect below the badge. The Higher value sets the bigger size of the shadow, whereas the 0 value removes the shadow.
-
-
-
-
-
-
-
-### Styling title text
-
-To change the title text style:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Title Text Style** section.
-3. Find the **Theme Text Style** property and change the style as per instructions [here](../../../resources/ui/widgets/basic-widgets/text.md#common-text-styling-properties).
-
-
-### Styling playback duration text
-
-To change the playback duration text style:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Playback Duration Text Style** section.
-3. Find the **Theme Text Style** property and change the style as per instructions [here](../../../resources/ui/widgets/basic-widgets/text.md#common-text-styling-properties).
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/audio/audio-recroding.md b/docs/ff-concepts/file-handling/audio/audio-recroding.md
deleted file mode 100644
index bcf959c6..00000000
--- a/docs/ff-concepts/file-handling/audio/audio-recroding.md
+++ /dev/null
@@ -1,165 +0,0 @@
----
-title: Audio Recording
-slug: /concepts/file-handling/audio-recording
-sidebar_position: 1
-tags: [Media, Action]
-keywords: [Media, Audio Recording, Action, File Handling]
----
-
-# Audio Recording
-
-This action allows users to record audio. Using this action, you can add functionalities like recording voice notes in a note-taking app or practicing pronunciation in a language app.
-
-
-
-
-
-
-
-## Types of audio recording action
-
-Following are the types of audio recording actions you can trigger:
-
-1. [**Start Audio Recording**](#start-audio-recording-action): This starts the recording. It also provides a name to the recording, which you can use later to stop the recording using the "Stop Audio Recording" **action*.*
-2. [**Stop Audio Recording**](#stop-audio-recording-action): This halts the ongoing recording using the name from the "Start Audio Recording" action. To capture and play the recorded audio, make sure to specify the *Action Output Variable Name*, which can be used with the audio player.
-
-## Start Audio Recording [Action]
-
-Follow the steps below to start the recording:
-
-1. Select the widget (e.g., Button, Page, etc.) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-3. Click on the **+ Add Action**.
-4. First, [request permission](../../../resources/projects/settings/project-setup.md#request-permission-action) for the microphone.
-5. Inside the **TRUE** section, add the **Start Audio Recording** (under *Utilities*) action.
-6. By default, the **Name** is set to any random string. However, you can change it to any friendly name.
-7. Optional: After starting recording, you might want to update the state variables to reflect changes on UI. For instance, you can enable/disable buttons or start recording animations to provide a visual cue of the ongoing process. This step allows you to enhance the user experience and provide real-time feedback during the recording.
-
-
-
-
-
-
-
-## Stop Audio Recording [Action]
-
-Follow the steps below to stop the recording:
-
-1. Select the widget (e.g., Button, Page, etc.) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-3. Click on the **+ Add Action**.
-4. Search and select the **Stop Audio Recording** (under *Utilities*) action.
-5. Choose the **Recorder Name** from the dropdown. This will be the name you provided in the "Start Audio Recording" action.
-6. Specify the **Action Output Variable Name**. This will store the actual audio recording, which you can use with any audio player. It stores recording in an **Audio Path** data type.
-7. To upload the audio recording to Firebase or Supabase, you can use the [Upload file](../upload-save-file.md) action. When you add this action:
- 1. Set the **Upload Type** to the preferred one.
- 2. Set **File Type** to **Uploaded File** because the *Stop Audio Recording* action internally stores recorded audio bytes (inside widget state).
- 3. Set the **File to Upload** to **Widget State > [action_output_variable_name]Bytes**.
-8. For uploading via API, *you don't need to add the Upload file action*. Just directly add the [**API call**](../../../resources/control-flow/backend-logic/api/rest-api.md) and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. You can pass the audio recording via **Widget State > [action_output_variable_name]Bytes** in the API variable. See how to [configure an API for the multipart request body](../../../resources/control-flow/backend-logic/api/rest-api.md#multipart-format).
-9. Optional: After stopping the recording, you might want to update the state variables to reflect changes on the UI. For instance, you can enable/disable buttons or stop recording animations.
-
-:::tip
-It's always a good idea to have a fail-safe mechanism to ensure recordings are properly stopped, even if the user forgets to do so manually. For instance, you can trigger this action when the user closes the app without explicitly stopping it.
-:::
-
-
-
-
-
-
-
-## Playing audio recording
-
-After you have stopped the recording, you can simply provide the *Action Output Variable Name* to the [Audio Player](audio-player.md) widget to start playing the recorded audio.
-
-:::warning
-Currently, recording audio isn't supported in Run or Test modes due to certain limitations. However, for Android and iOS platforms, you can test by downloading the code and following the instructions provided [here](../../../testing-deployment-publishing/exporting-code/ff-cli.md).
-:::
-
-Here's how you do it.
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/audio/play-stop-sound.md b/docs/ff-concepts/file-handling/audio/play-stop-sound.md
deleted file mode 100644
index b9cbc8e5..00000000
--- a/docs/ff-concepts/file-handling/audio/play-stop-sound.md
+++ /dev/null
@@ -1,78 +0,0 @@
----
-title: Play / Stop Sound
-slug: /concepts/file-handling/play-stop-sound
-sidebar_position: 2
-tags: [Media, Action]
-keywords: [Media, Play Sound, Stop Sound, Action]
----
-# Play / Stop Sound
-The Play and Stop Sound actions allow you to enhance your app with audio effects.
-
-## Play Sound
-
-Using this action, you play a sound that notifies users about the action they have taken—for example, playing a sound after refreshing a list or sending a message.
-
-:::tip
-It is advisable to use this action only for short audio. To play the more extended audio, consider adding the [**AudioPlayer**](audio-player.md) widget.
-:::
-
-### Adding Play Sound [Action]
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the properties panel, If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile (inside *Action Flow Editor*) and select **Add Action**.
-3. Search and select the **Play Sound** (under *Alerts/Notifications*) action.
-4. By default, this action will be given a random **Name** so it can be stopped by the [Stop Sound](#adding-stop-sound-action) action.
-5. Find the **Audio Type** dropdown and select **Network** or **Asset**.
-6. If you choose *Network*:
- 1. Inside the **Network Path** section,
- 1. To set the static audio, select the **Value Source > Specific** **Value** and enter the **Value** as a URL that will play the sound.
- 2. To set the dynamic audio, select the **Value Source > From Variable** > click **UNSET** and set the URL from a variable.
-7. If you choose *Asset,* click the **Upload Audio** button, select the sound and upload it.
-8. You can also control the sound volume using the **Volume** slider. It ranges from 0.0 to 1.0, where 0 is mute and 1 is full volume.
-9. By default, this action is 'non-blocking'**,** meaning it will trigger the following/next action (if any) as soon as this one is triggered. If you want to wait until the sound playing is finished before triggering any further action, enable **Await Playback** option.
-
-
-
-
-
-
-
-## Stop sound
-
-Using this action, you can stop a sound that is currently playing, which was started by the [Play Sound](#play-sound) action. For example, If your app is playing any sound effects, you may need to stop them when the app is paused or stopped.
-
-:::info
-This action only works if you have added a [**Play Sound**](#adding-play-sound-action) action on a page.
-:::
-
-### Adding Stop Sound [Action]
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the properties panel (the right menu), If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile (inside *Action Flow Editor*) and select **Add Action**.
-3. Search and select the **Stop Sound** (under *Alerts/Notifications*) action, and then choose the sound *Name* that you want to stop.
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/clear-delete-media.md b/docs/ff-concepts/file-handling/clear-delete-media.md
index 15438d4e..245b67e2 100644
--- a/docs/ff-concepts/file-handling/clear-delete-media.md
+++ b/docs/ff-concepts/file-handling/clear-delete-media.md
@@ -1,125 +1,34 @@
---
-title: Clear or Delete Media
slug: /concepts/file-handling/clear-delete-media
-sidebar_position: 7
-tags: [Media, Action]
-keywords: [Media, Clear Data, Delete Data Firebase Storage, Supabase Storage]
+title: Clear or Delete Media
+description: Learn how to add clear and delete file actions into your FlutterFlow app.
+sidebar_position: 4
+tags: [Media Files, Clear Delete Data]
+keywords: [Media Files, Clear Data, Delete Data, Firebase Storage, Supabase Storage]
---
# Clear or Delete Media
-The Clear and Delete Media actions provide essential functionalities for managing media files efficiently.
-
-## Clear Uploaded Data
+The **Clear** and **Delete** **Media** actions provide essential functionalities for managing media files efficiently.
-By utilizing this action, you can clear the *Uploaded File URL*. This functionality is handy when you want to offer users a straightforward method to remove any uploaded media, such as images or recordings, by providing them with an explicit option to do so.
+## Clear Uploaded Data [Action]
-
-
-
-
-
+When users upload media files, these files are first stored in a local state variable, i.e., *Uploaded File URL* for immediate access and display. This action is helpful when you want to offer users a straightforward method to remove any uploaded media, such as images or recordings.
:::info
-Before you use this action, you must have the [**Upload Data**](upload-save-media.md) action already added.
-:::
-
-### Adding Clear Uploaded Data action
-
-Follow the steps below to add this type of action to any widget:
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **+ Add Action**.
-3. Search and select the **Clear Uploaded Data** (under *Utilities*) **> [Name of uploaded data]** (given in the [Upload Data](upload-save-media.md)) action.
+For this action to work, the [**Upload or Save Media**](uploading-files.md#upload-or-save-media-action) action must already be added to the actions workflow.
-
-
-## Delete Data
-
-Using this action, you can delete the uploaded media, such as photos, videos, and PDF files, from the [Firebase Storage](https://firebase.google.com/docs/storage) or [Supabase Storage](https://supabase.com/storage).
+:::
-
-
-
-
-
+## Delete Data [Action]
-:::info
-Before you add this action, ensure you can access the *Uploaded File URL* of the media. Check out the [**upload media**](upload-data.md) section to see how to get it.
-:::
+The **Delete Data** action permanently removes uploaded media—such as images, videos, and PDF files—from external storage platforms like [Firebase Storage](https://firebase.google.com/docs/storage) and [Supabase Storage](https://supabase.com/storage).
-### Adding Delete Media action
+Inside the **URL** section, provide a valid media URL. This must be either the direct **Uploaded File URL** or a variable that holds the URL.
-Follow the steps below to add this action to any widget.
+:::tip
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **+ Add Action**.
-3. Search and select the **Delete Media** (under *Utilities*) action.
-4. Inside the **URL** section, provide a valid media URL. This must be either the direct **Uploaded File URL** or a variable that holds the URL.
-5. To let users know about the successful deletion of the media, you can [add the snackbar message](../../resources/ui/pages/page-elements.md#snackbar).
+Always prompt users for confirmation before deleting media files to prevent accidental loss of data.
-
-
-
-
-
\ No newline at end of file
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/displaying-media.md b/docs/ff-concepts/file-handling/displaying-media.md
new file mode 100644
index 00000000..7adef3fb
--- /dev/null
+++ b/docs/ff-concepts/file-handling/displaying-media.md
@@ -0,0 +1,321 @@
+---
+slug: /concepts/file-handling/displaying-media
+title: Displaying Media
+description: Learn how to display media in FlutterFlow.
+tags: [Media Files, Widget]
+sidebar_position: 2
+keywords: [Media Files, Media Management, Assets, Network, Display Media, Media Widgets]
+---
+
+# Displaying Media
+
+Displaying media efficiently is crucial for enhancing user experience in your FlutterFlow app. Whether you're working with images, audio, video, or PDFs, FlutterFlow provides flexible options for integrating and managing media. This guide covers how to set media sources, customize playback settings, and implement best practices like lazy loading, caching, and BlurHash to optimize performance.
+
+## Media Types
+To display media on widgets, navigate to the **Properties Panel** and specify the media source under the **[Media] Type** option (e.g., ImageType, AudioType, VideoType). Here are the available options:
+
+### Network
+
+Enter the URL of the media directly into the **Path** input field. This is for media hosted online.
+
+
+
+If your media is uploaded to Firebase or Supabase, click **Set from Variable** on the **Path** input field, and select **Source** as **Widget State > Uploaded File URL**.
+
+
+
+For media uploaded via an API, choose **Source** as **Action Outputs > [Action Output Variable Name] (API Response)**. Ensure that the API response contains the URL of the uploaded file. Learn how to extract the URL using [JSON path](../../resources/control-flow/backend-logic/api/rest-api.md#json-path).
+
+
+
+:::info
+
+To handle scenarios where media takes time to load or fails to load, you can set a placeholder. Click **Set from Variable** on the **Path** field and specify a placeholder URL under the **Default Value** property.
+
+:::
+
+### Asset
+
+You can also display media files uploaded to your **Assets**. Assets are resources such as images, videos, documents, fonts, and other files that you include locally in your project. To upload assets, click on **Media Assets** in the left-side navigation menu and add files directly from your device. Alternatively, you can directly upload and display files when configuring media widgets by clicking the upload icon.
+
+:::tip
+For more details on how assets are stored in your project, see the directory [**Assets**](../../generated-code/directory-structure.md#assets) in the generated code.
+:::
+
+
+
+
+
+### Uploaded File
+
+You can also access media files within your app that are stored temporarily in your application. For example, if you'd like to preview an image before sending it to cloud storage, you can do so by setting the source to **Widget State -> Uploaded Local File**.
+
+
+
+## AudioPlayer
+
+The **AudioPlayer** widget allows you to integrate audio playback into your apps. You can play audio from both uploaded assets and external URLs. Refer to the [**Displaying Media**](#media-types) section for more details on accessing media.
+
+:::tip[Generated Code]
+The AudioPlayer widget in FlutterFlow uses the [**assets_audio_player**](https://pub.dev/packages/assets_audio_player) package for audio playback.
+:::
+
+**Customization Options**
+
+- **Title:** Specify the audio title in the **Title** property. You can set this directly or bind it to a variable, such as an app state variable, API response, or Firestore document.
+- **Pause on Forward Navigation:** By default, the audio stops when navigating to another page.
+- **Play in Background:** Define how the audio behaves when the app moves to the background:
+ - **Enabled:** The audio continues to play.
+ - **Disabled, restore on foreground:** The audio pauses and resumes when the app becomes active again.
+ - **Disabled, pause:** The audio stops immediately when the app goes into the background.
+- **Colors:**
+ - **Background Color:** Customize the background using the **Fill Color** property.
+ - **Playback Button Color:** Adjust the colors of the play and pause buttons.
+ - **Active/Inactive Track Color:** Change the progress bar color that indicates the current playback position.
+- **Elevation:** Use the **Elevation** property to modify the shadow beneath the audio tile. A higher value increases the shadow size, while setting it to 0 removes the shadow.
+- **Text Styling:**
+ - **Title Text:** Personalize the title’s font, size, and color in the **Title Text Style** section.
+ - **Playback Duration Text:** Adjust the style of the playback duration text in the **Playback Duration Text Style** section.
+
+## Audio Recording
+
+You can implement audio recording functionality using the **Start Audio Recording** and **Stop Audio Recording** actions.
+
+:::warning
+
+Currently, audio recording is not supported in **Run** or **Test** modes due to certain limitations.
+
+:::
+
+### Start Audio Recording [Action]
+
+This action starts the recording. It also provides a name to the recording, which you can use later to stop the recording using the [Stop Audio Recording](#stop-audio-recording-action) *action.*
+
+Before adding this action, ensure you [request microphone permission](../../resources/projects/settings/project-setup.md#request-permission-action). Within the **TRUE** block of the permission condition check, add the **Start Audio Recording** action. By default, the **Name** field value is a randomly generated string. You can change it to a more descriptive name for easier identification.
+
+:::tip
+
+After starting recording, you might want to update the state variables to reflect changes on the UI. For instance, you can enable/disable buttons or start recording animations to provide a visual cue of the ongoing process. This step allows you to enhance the user experience and provide real-time feedback during the recording.
+
+:::
+
+
+
+
+### Stop Audio Recording [Action]
+
+If you have multiple audio recording actions, all the Recorder object names (either auto-generated by FlutterFlow or manually set by the user) are listed under the Recorder Name dropdown. Choose the recorder object you want to stop, and it will stop the ongoing recording.
+
+ To capture and play the recorded audio, make sure to specify the *Action Output Variable Name*, which can be used with the audio player.
+
+Here’s how you can setup this action:
+
+1. When you add this action, choose the **Recorder Name** from the dropdown. This will be the name you provided in the Start Audio Recording action.
+2. Specify the **Action Output Variable Name**. This will store the actual audio recording, which you can use with any audio player. It stores recording in an **Audio Path** data type.
+3. If you want to upload the audio recording to Firebase or Supabase, you can use the [Upload file](uploading-files.md#upload-or-save-media-action) action. When you add this action:
+ 1. Set the **Upload Type** to the preferred one.
+ 2. Set **File Type** to **Uploaded File** because the *Stop Audio Recording* action internally stores recorded audio bytes (inside widget state).
+ 3. Set the **File to Upload** to **Widget State > Recorded File**.
+4. For uploading via API, *you don't need to add the Upload file action*. Just directly add the [**API call**](../../resources/control-flow/backend-logic/api/rest-api.md) and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. You can pass the audio recording via **Widget State > Recorded File** in the API variable. See how to [configure an API for the multipart request body](../../resources/control-flow/backend-logic/api/rest-api.md#multipart-format).
+
+:::tip
+
+- After stopping the recording, you might want to update the state variables to reflect changes on the UI. For instance, you can enable/disable buttons or stop recording animations.
+- It's always a good idea to have a fail-safe mechanism to ensure recordings are properly stopped, even if the user forgets to do so manually. For example, you can use the [**On Dispose**](../../resources/ui/pages/page-lifecycle.md#on-dispose-action-trigger) action trigger to stop recording when a user closes the app without manually stopping it.
+
+:::
+
+
+
+
+
+
+
+
+### Playing audio recording
+
+After you have stopped the recording, you can simply provide the *Action Output Variable Name* to the [Audio Player](#audioplayer) widget to start playing the recorded audio.
+
+## Play or Stop Sound
+
+The **Play Sound** and **Stop Sound** actions offer flexibility for enhancing the user experience with audio effects or background sounds.
+
+### Play Sound [Action]
+
+The **Play Sound Action** allows you to play a sound that notifies users about the action they have taken—for example, playing a sound after refreshing a list or sending a message.
+
+:::tip
+
+It is advisable to use this action only for short audio. To play the more extended audio, consider adding the [**AudioPlayer**](#audioplayer) widget.
+
+:::
+
+By default, this action is assigned a random **Name** to be stopped later using the [Stop Sound](#stop-sound-action) action. You can adjust the volume using the **Volume** slider (0.0 = mute, 1.0 = full volume). The action is non-blocking by default, allowing subsequent actions to trigger immediately. To wait until playback finishes before proceeding, enable the **Await Playback** option.
+
+:::info[Use cases]
+
+- **Feedback Sounds:** Play sounds for button clicks, form submissions, or error alerts to improve user interaction and feedback.
+- **Notifications:** Play sound alerts for reminders, messages, or task completion.
+- **Gamification:** Enhance gaming experiences with sound effects for achievements, levels, or interactions.
+
+:::
+
+### Stop Sound [Action]
+
+You can stop a sound that is currently playing, which was started by the [Play Sound](#play-sound-action) action. For example, If your app is playing any sound effects, you may need to stop them when the app is paused or stopped.
+
+:::info
+
+This action is enabled only when you have added a [**Play Sound**](#play-sound-action) action on a page.
+
+:::
+
+## VideoPlayer
+
+The **VideoPlayer** widget is used to show a video from uploaded assets or the URL link. The VideoPlayer widget can play various video formats such as MP4, MOV, WAV, MPEG, and JPEG motion photos. Refer to the [**Displaying Media**](#media-types) section for more details on accessing media.
+
+:::tip[Generated Code]
+The VideoPlayer uses the [**video_player**](https://pub.dev/packages/video_player) package for reliable video playback across different platforms.
+:::
+
+**Customization Options**
+
+The **VideoPlayer** widget includes several options to align with your app's design and functionality:
+
+- **Aspect Ratio:** Set the desired aspect ratio (e.g., 1.7 for a 16:9 ratio) to ensure the video displays correctly.
+- **AutoPlay:** Enable this option to automatically start playing the video when the page loads.
+- **Loop Video:** Choose whether the video should replay automatically after it ends.
+- **Show Controls:** Display playback controls, including play/pause buttons and the seek bar.
+- **Allow Full Screen:** Enable users to expand the video to full-screen mode.
+- **Playback Speed Menu:** Let users adjust the video playback speed.
+- **Load on Page Load:** When enabled, the video will preload when the page loads, reducing buffering time when the user starts playback.
+- **Pause on Forward Navigation:** If enabled, the video will pause automatically when the user navigates away from the page.
+
+## YoutubePlayer
+
+The **YouTubePlayer** widget in FlutterFlow allows you to integrate and play YouTube videos within your app. It offers customizable playback options and an intuitive interface for enhancing the user experience.
+
+:::tip[Generated Code]
+The YoutubePlayer uses a custom version of the [**youtube_player_iframe**](https://pub.dev/packages/youtube_player_iframe) package, hosted on FlutterFlow's GitHub repository.
+:::
+
+**Customization Options**
+
+- **Loop Video:** When enabled, the video will automatically replay after it finishes.
+- **Mute Video:** Starts the video in a muted state.
+- **Show Controls:** Displays playback controls such as play/pause, volume, subtitles, and fullscreen options.
+- **Show Full Screen Control:** This specifically displays the fullscreen toggle button among the controls.
+- **Pause on Forward Navigation:** Automatically pauses the video when the user navigates away from the page.
+- **Strict Related Videos:** Ensures that related videos shown at the end of playback come from the same channel as the currently played video.
+
+## PdfViewer
+
+In FlutterFlow, the **PdfViewer** widget enables you to display PDF files within your app, supporting both network URLs and locally uploaded assets. Refer to the [**Displaying Media**](#media-types) section for more details.
+
+:::tip[Generated Code]
+The PdfViewer in FlutterFlow uses the [**pdfx**](https://pub.dev/packages/pdfx) package for rendering PDFs.
+:::
+
+**Customization Options**
+
+- **Horizontal Scroll:** By default, the PdfViewer allows vertical scrolling through pages. Enable this option to allow horizontal scrolling.
+- **Use Proxy:** By default, FlutterFlow routes PDF fetching through a proxy in **Run Mode** and **Test Mode** to avoid CORS (Cross-Origin Resource Sharing) issues. **Switch this off** if you do not want the PDF request to be routed through the proxy.
+- **Use Custom Proxy URL:** If you need a specific proxy, enable this option and provide your own proxy URL instead of using FlutterFlow’s default proxy.
+
+## Web Access for PDFs and Other Files
+
+Some types of files require additional configuration to be accessed on the web. In particular, the PDF Viewer requires network-hosted files (such as uploaded PDFs) to allow Cross-Origin Resource Sharing (CORS). For a deeper understanding of Cross-Origin Resource Sharing (CORS), you can refer to this guide.
+
+The key takeaway is that to allow users to upload and view PDFs using Firebase Storage, follow the steps below.
+
+
+You'll need to run a few commands to enable CORS for your Firebase project. No programming experience is required, but if you're comfortable with Firebase, you can refer to the official guide here: [Firebase CORS Configuration](https://firebase.google.com/docs/storage/web/download-files#cors_configuration).
+
+**Step 1: Find Your Firebase Project ID**
+
+You can find the Firebase project ID from **FlutterFlow > Settings and Integrations > Firebase**. Copy your **Firebase** **Project ID**.
+
+
+
+**Step 2: Open Cloud Shell in Google Cloud Console**
+
+1. Go to the following link, replacing **FIREBASE_PROJECT_ID** with your actual project ID:
+
+```jsx
+https://console.cloud.google.com/home/dashboard?cloudshell=true&project=FIREBASE_PROJECT_ID
+```
+
+1. If prompted, click **Continue**.
+2. You should see a terminal at the bottom of the screen. If your project ID is not displayed in yellow, click the **down arrow** (🔽) next to the project name and select the correct Firebase project.
+
+
+
+**Step 3: Run the CORS Configuration Command**
+
+1. Click on the **Cloud Shell terminal** (the black screen).
+2. Copy and paste the following command and replace `` with your actual storage bucket. To locate your Firebase Storage bucket name, navigate to Firebase Console > Storage > at top left side, you'll see your bucket's URL, which typically follows the format `your-project-id.appspot.com`.
+
+```jsx
+touch cors.json && \
+echo '[{"origin": ["*"], "method": ["GET"], "maxAgeSeconds": 3600}]' > cors.json && \
+gsutil cors set cors.json gs://
+```
+
+
+
+3. Press **Enter** (or **Return**) to execute the command.
+4. If prompted, click **Authorize** to allow Cloud Shell to access your Firebase project.
+5. Once the command executes successfully, you should see a confirmation message.
+
+
+
+
+## BlurHash
+
+In FlutterFlow, **BlurHash** is a technique used to enhance the user experience by displaying visually appealing placeholders while images are loading. Instead of showing empty spaces or generic loading indicators, BlurHash generates a blurred preview that resembles the actual image, providing users with a smoother and more engaging experience.
+
+
+
+Here are the steps to generate and use the BlurHash:
+
+1. When using the [**Upload/Save Media**](uploading-files.md#upload-or-save-media-action) action to upload images, you can enable the **Include Blur Hash** option. This setting automatically generates a BlurHash string for the uploaded image.
+
+
+
+1. After generating the BlurHash, it's advisable to store it alongside the image URL in your database (e.g., Firestore). The generated BlurHash is accessible via the **Widget State > Uploaded Local File > Media Blur Hash**. This approach ensures that both the image URL and its corresponding BlurHash are readily accessible when needed.
+
+
+
+1. To utilize the BlurHash as a placeholder, in the Image widget's properties, enable the **Use Blur Hash** option and then set the **Blur Hash String** value from a variable.
+
+
+
+## Best Practices
+
+- Enable [infinite scrolling](../../resources/ui/widgets/composing-widgets/list-grid.md#adding-infinite-scroll) (lazy loading) in list views to load additional content as users scroll, rather than loading all data at once.
+- Leverage FlutterFlow's built-in cache manager, which automatically handles image caching.
+- Implement [local caching](../../resources/control-flow/backend-logic/backend-query/backend-query.md#backend-query-caching) to store frequently accessed data on the device, reducing the need for repeated network requests.
+- Reduce the number of network calls by fetching only necessary data and utilizing caching strategies.
+- Ensure that database queries are efficient and retrieve only the data required for display.
+- Use [BlurHash](#blurhash) to display a blurred preview of images while they load, enhancing the user experience.
+- Display loading indicators to inform users that data is being fetched, improving perceived performance.
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/download-file.md b/docs/ff-concepts/file-handling/download-file.md
index 7ed9ca01..81412103 100644
--- a/docs/ff-concepts/file-handling/download-file.md
+++ b/docs/ff-concepts/file-handling/download-file.md
@@ -1,12 +1,13 @@
---
-title: Download File
slug: /concepts/file-handling/download-file
-sidebar_position: 6
-tags: [Media, Download Data, File Management]
-keywords: [Media, Download Data, Firebase Storage, Supabase Storage]
+title: Download File
description: Learn how to add download file action into your FlutterFlow app.
+tags: [Media Files, Download Data]
+sidebar_position: 3
+keywords: [Media Files, Download Data, Firebase Storage, Supabase Storage]
---
+
# Download File
The **Download File** action allows you to enable users to download or save files locally on their devices.
@@ -49,7 +50,7 @@ The **Download File** action allows you to enable users to download or save file
To add a Download File action, select the **Widget** (e.g., button or any interactive widget) where you want users to initiate the file download and set the **Source** to one of the following.
- **From URL**: Use this option for downloading files that are accessible through a direct link and specify the URL of the file that should be downloaded.
-- **From File (Bytes)**: Use this option when the file is uploaded to the device using the [Local Upload (Widget State)](upload-data.md#local-upload-widget-state). You can access the file via ***Widget State > Uploaded Local File***.
+- **From File (Bytes)**: Use this option when the file is uploaded to the device using the [Local Upload (Widget State)](uploading-files.md#local-upload-widget-state). You can access the file via ***Widget State > Uploaded Local File***.
Optionally, you can specify a **Filename** to be used when the file is downloaded.
diff --git a/docs/ff-concepts/file-handling/file-handling.md b/docs/ff-concepts/file-handling/file-handling.md
new file mode 100644
index 00000000..c8149394
--- /dev/null
+++ b/docs/ff-concepts/file-handling/file-handling.md
@@ -0,0 +1,25 @@
+---
+slug: /concepts/file-handling
+title: File Handling
+description: Learn how to handle media files in FlutterFlow.
+tags: [Media Files, Upload Data, Download Data, Clear Delete Data]
+sidebar_position: 0
+keywords: [File Handling, Media Files, Upload Data, Download Data, Clear Delete Data, Media Management, Assets, Display Media, Media Widgets]
+---
+
+# File Handling
+
+FlutterFlow makes it easy to manage, upload, download, and display files within your app. It supports a variety of file types, including images, videos, and documents, and integrates seamlessly with popular storage solutions. Using built-in widgets and actions, you can effectively manage your app's media. This guide covers the following key aspects of file handling in FlutterFlow.
+
+- **Media Assets**: Upload any assets you want to use in your app from the Navigation Menu > Media Assets. This also shows the media assets of the Team.
+- [**Uploading Files**](uploading-files.md): Upload and save different file types, including images, audio, videos, and PDFs to cloud storage.
+- [**Displaying Media**](displaying-media.md): Fetch files from cloud storage or external URLs and display them in your app.
+- [**Download Files**](download-file.md): Allow users to download files directly to their devices.
+- [**Clear or Delete Media**](clear-delete-media.md): Allow users to delete uploaded files from their devices and cloud storage.
+
+:::info[Also see]
+
+- **Stream Media with Mux**: [**Integrate Mux's broadcasting**](../../ff-integrations/streaming/mux/initial-setup.md) services in FlutterFlow by using the MuxBroadcast widget for live streaming.
+- **Request Permissions**: [**Request user permissions**](../../resources/projects/settings/project-setup.md#request-permission-action) when implementing custom widgets or actions that access personal information, such as capturing photos or selecting images, especially if no built-in permission mechanism is available.
+
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/imgs/adding-clear-uploaded-data-action.avif b/docs/ff-concepts/file-handling/imgs/adding-clear-uploaded-data-action.avif
deleted file mode 100644
index f31a208b..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/adding-clear-uploaded-data-action.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/blurhash.avif b/docs/ff-concepts/file-handling/imgs/blurhash.avif
new file mode 100644
index 00000000..7ef74437
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/cloud-shell.avif b/docs/ff-concepts/file-handling/imgs/cloud-shell.avif
new file mode 100644
index 00000000..75704ced
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/cloud-shell.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/compress-image.avif b/docs/ff-concepts/file-handling/imgs/compress-image.avif
new file mode 100644
index 00000000..827a7918
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/compress-image.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/configure-upload-media-action.avif b/docs/ff-concepts/file-handling/imgs/configure-upload-media-action.avif
new file mode 100644
index 00000000..05cb8a05
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/configure-upload-media-action.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/copy-firebase-project-id.avif b/docs/ff-concepts/file-handling/imgs/copy-firebase-project-id.avif
new file mode 100644
index 00000000..247e4f4d
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/copy-firebase-project-id.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/cors-2.png b/docs/ff-concepts/file-handling/imgs/cors-2.png
new file mode 100644
index 00000000..c4375f34
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/cors-2.png differ
diff --git a/docs/ff-concepts/file-handling/imgs/cors-3.png b/docs/ff-concepts/file-handling/imgs/cors-3.png
new file mode 100644
index 00000000..2aa773ff
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/cors-3.png differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-api.avif b/docs/ff-concepts/file-handling/imgs/dm-api.avif
new file mode 100644
index 00000000..c8ae9731
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-api.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-local-upload.avif b/docs/ff-concepts/file-handling/imgs/dm-local-upload.avif
new file mode 100644
index 00000000..e1342a24
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-local-upload.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-network-path.avif b/docs/ff-concepts/file-handling/imgs/dm-network-path.avif
new file mode 100644
index 00000000..1cdc25d4
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-network-path.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-uploaded-file.avif b/docs/ff-concepts/file-handling/imgs/dm-uploaded-file.avif
new file mode 100644
index 00000000..65081f59
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-uploaded-file.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/enable-blurhash.avif b/docs/ff-concepts/file-handling/imgs/enable-blurhash.avif
new file mode 100644
index 00000000..07f7b361
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/enable-blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/full-screen-control-disabled.avif b/docs/ff-concepts/file-handling/imgs/full-screen-control-disabled.avif
deleted file mode 100644
index bf11b98a..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/full-screen-control-disabled.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_1.png b/docs/ff-concepts/file-handling/imgs/img_1.png
deleted file mode 100644
index 01e7719f..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_1.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_10.png b/docs/ff-concepts/file-handling/imgs/img_10.png
deleted file mode 100644
index e46055e0..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_10.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_11.png b/docs/ff-concepts/file-handling/imgs/img_11.png
deleted file mode 100644
index 21d5c2ec..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_11.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_12.png b/docs/ff-concepts/file-handling/imgs/img_12.png
deleted file mode 100644
index f9e1adab..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_12.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_13.png b/docs/ff-concepts/file-handling/imgs/img_13.png
deleted file mode 100644
index 87d14cd2..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_13.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_2.png b/docs/ff-concepts/file-handling/imgs/img_2.png
deleted file mode 100644
index f4712e83..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_2.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_3.png b/docs/ff-concepts/file-handling/imgs/img_3.png
deleted file mode 100644
index d1be800f..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_3.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_4.png b/docs/ff-concepts/file-handling/imgs/img_4.png
deleted file mode 100644
index 75b84083..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_4.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_5.png b/docs/ff-concepts/file-handling/imgs/img_5.png
deleted file mode 100644
index ec8e4a7d..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_5.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_6.png b/docs/ff-concepts/file-handling/imgs/img_6.png
deleted file mode 100644
index 672bd56c..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_6.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_7.png b/docs/ff-concepts/file-handling/imgs/img_7.png
deleted file mode 100644
index 28730fb3..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_7.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_8.png b/docs/ff-concepts/file-handling/imgs/img_8.png
deleted file mode 100644
index af99faf3..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_8.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_9.png b/docs/ff-concepts/file-handling/imgs/img_9.png
deleted file mode 100644
index c2be9a3e..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_9.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/local-upload-to-firebase-supabase.avif b/docs/ff-concepts/file-handling/imgs/local-upload-to-firebase-supabase.avif
new file mode 100644
index 00000000..4610439d
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/local-upload-to-firebase-supabase.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/save-blurhash.avif b/docs/ff-concepts/file-handling/imgs/save-blurhash.avif
new file mode 100644
index 00000000..54f0e38f
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/save-blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/select-from-assets.avif b/docs/ff-concepts/file-handling/imgs/select-from-assets.avif
new file mode 100644
index 00000000..55bc4839
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/select-from-assets.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/show-controls-disabled.avif b/docs/ff-concepts/file-handling/imgs/show-controls-disabled.avif
deleted file mode 100644
index e53279e7..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/show-controls-disabled.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/show-controls-enabled.avif b/docs/ff-concepts/file-handling/imgs/show-controls-enabled.avif
deleted file mode 100644
index e1a94f20..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/show-controls-enabled.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/start-audio-recording.avif b/docs/ff-concepts/file-handling/imgs/start-audio-recording.avif
new file mode 100644
index 00000000..762877dc
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/start-audio-recording.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/stop-action.png b/docs/ff-concepts/file-handling/imgs/stop-action.png
deleted file mode 100644
index 0d1dea3a..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/stop-action.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/storage-bucket.avif b/docs/ff-concepts/file-handling/imgs/storage-bucket.avif
new file mode 100644
index 00000000..b5e6b36d
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/storage-bucket.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/img.png b/docs/ff-concepts/file-handling/imgs/supabase-storage-bucket.png
similarity index 100%
rename from docs/ff-concepts/file-handling/imgs/img.png
rename to docs/ff-concepts/file-handling/imgs/supabase-storage-bucket.png
diff --git a/docs/ff-concepts/file-handling/imgs/upload-type-firebase.avif b/docs/ff-concepts/file-handling/imgs/upload-type-firebase.avif
new file mode 100644
index 00000000..b02f44be
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/upload-type-firebase.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/upload-type-local-and-api.avif b/docs/ff-concepts/file-handling/imgs/upload-type-local-and-api.avif
new file mode 100644
index 00000000..3edc5b0a
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/upload-type-local-and-api.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/upload-type-supabase.avif b/docs/ff-concepts/file-handling/imgs/upload-type-supabase.avif
new file mode 100644
index 00000000..551c1b28
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/upload-type-supabase.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/use-blurhash.avif b/docs/ff-concepts/file-handling/imgs/use-blurhash.avif
new file mode 100644
index 00000000..22075461
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/use-blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/pdf/_category_.json b/docs/ff-concepts/file-handling/pdf/_category_.json
deleted file mode 100644
index b9a86169..00000000
--- a/docs/ff-concepts/file-handling/pdf/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "PDF",
- "position": 2
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/pdf/pdf-viewer.md b/docs/ff-concepts/file-handling/pdf/pdf-viewer.md
deleted file mode 100644
index 044294f2..00000000
--- a/docs/ff-concepts/file-handling/pdf/pdf-viewer.md
+++ /dev/null
@@ -1,161 +0,0 @@
----
-title: PdfViewer
-slug: /concepts/file-handling/pdf-viewer
-sidebar_position: 1
-tags: [Media, Widget]
-keywords: [Media, PdfViewer, Display PDF File]
----
-# PdfViewer
-The PdfViewer widget allows you to show the PDF file from uploaded assets or the URL link.
-
-## Adding PdfViewer Widget
-
-Here's how you can add the PdfViewer widget to your project:
-
-1. Drag the **PdfViewer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **Network Path** property and enter the **URL** for the pdf file.
-
-:::info
-Every PdfViewer widget added to the project shows a default PDf from an online source.
-:::
-
-
-
-
-
-
-
-## Changing PDF Source
-
-By default, the widget is set to show the PDF file from Network. However, you can change this to use the PDF file uploaded directly to your app.
-
-Here's how you can change the PDF source:
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **PDF Source** dropdown. Change it to **Asset**.
-4. Now, find the **PDF Asset** property, Click on the **Upload Pdf** button, select the pdf file and upload it.
-
-
-
-
-
-
-
-:::tip
-Once you upload the pdf file, you can use it throughout your app. You can manage your uploaded pdfs with the Project Media/Asset Manager.
-:::
-
-To use an uploaded pdf:
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **PDF Source** dropdown. Change it to **Asset**.
-4. Click on **No asset selected** (inside the dropdown) and choose the pdf file.
-
-
-
-
-
-
-
-## Customizing
-
-You can customize the appearance and behavior of this widget using the various properties available under the properties panel.
-
-### Changing Scroll Direction
-
-By default, the PdfViewer allows you to scroll to the next pages in the vertical direction. However, you can change this behavior to allow scrolling in the horizontal direction.
-
-To change the scroll direction:
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Enable the **Horizontal Scroll**.
-
-
-
-
-
-
diff --git a/docs/ff-concepts/file-handling/upload-data.md b/docs/ff-concepts/file-handling/upload-data.md
deleted file mode 100644
index 28e59367..00000000
--- a/docs/ff-concepts/file-handling/upload-data.md
+++ /dev/null
@@ -1,81 +0,0 @@
----
-title: Upload Data
-slug: /concepts/file-handling/upload-data
-sidebar_position: 3
-tags: [Media, Upload Data]
-keywords: [Media, Upload Data, Firebase Storage, Supabase Storage]
----
-
-
-# Upload Data
-
-This section covers actions for uploading media such as photos, videos, PDFs, and Audio files.
-
-You can learn about adding each action by visiting the following pages.
-
-- [Upload/Save Media](upload-save-media.md)
-- [Upload/Save File](upload-save-file.md)
-
-## Types of upload
-
-To upload media, you have two options:
-
-### Firebase
-
-This will upload your media to [Firebase Storage](https://firebase.google.com/docs/storage). Once uploaded, you can directly use the ***Widget State > Uploaded File URL*** to preview media or save the URL.
-
-
-
-### Supabase
-
-Similar to Firebase, this will upload your media to the Supabase bucket (at a specific location that you specify). Once uploaded, you can directly use the ***Widget State > Uploaded File URL*** to preview media or save the URL.
-
-### Local Upload (Widget State)
-
-This will save your media to the device first. You can access it via ***Widget State > Uploaded Local File***. Then, make an API call to transfer the file to your server. **Note** that this API call must return the URL of the uploaded file, which you can later use to preview the media or store it somewhere in your database.
-
-
-## Web Access for PDFs and Other Files
-
-Some types of files require additional configuration to be accessed on the web. In particular, the PDF Viewer requires network files (such as uploaded PDFs) to allow what is called Cross-Origin Resource Sharing (CORS). Without diving too deep into that, the important part is that if you want users to be able to upload and view PDFs using Firebase Storage, follow the instructions below:
-
-**Put On Your Developer Hat**
-
-You'll need to run a few commands to get started. Don't worry though! No programming experience is required for this part, but you'll get to see how it's done 🙂
-
-:::note
-If you *do* have programming experience, you may find it easier to follow this guide instead: https://firebase.google.com/docs/storage/web/download-files#cors_configuration
-:::
-
-Start by finding the Project ID of your Firebase project. You can find that in the Firebase settings tab as seen below.
-
-
-
-Once you have that, follow these steps. Anywhere you see `*FIREBASE_PROJECT_ID*` , replace it with the project ID you found above:
-
-**Step 1**
-
-Go to the following link (remember to use your project ID): `https://console.cloud.google.com/home/dashboard?cloudshell=true&project=FIREBASE_PROJECT_ID`
-
-You'll see a view at the bottom that looks like this (you may have to hit "Continue"):
-
-
-
-Your Project ID should appear in yellow. If not, or if a different project is selected, you may have to tap on the down arrow (circled in red above) and select your project.
-
-**Step 2**
-
-Tap on the terminal (black screen), paste in the following command (again, replacing it with your Project ID ****in the last line), and hit *Enter* (or *Return*)**:**
-
-
-```
-touch cors.json && \
-echo [{\"origin\": [\"*\"], \"method\": [\"GET\"], \"maxAgeSeconds\": 3600}] > cors.json && \
-gsutil cors set cors.json gs://FIREBASE_PROJECT_ID.appspot.com
-```
-
-If you get a message to "Authorize Cloud Shell" make sure to hit "Authorize". Once the command runs it should give you an output similar to below. If so, it worked!
-
-
-
-And with that you are done! PDFs and other uploaded files will now load in the web with no issues!
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/upload-save-file.md b/docs/ff-concepts/file-handling/upload-save-file.md
deleted file mode 100644
index 9e703441..00000000
--- a/docs/ff-concepts/file-handling/upload-save-file.md
+++ /dev/null
@@ -1,139 +0,0 @@
----
-title: Upload or Save File
-slug: /concepts/file-handling/upload-save-file
-sidebar_position: 4
-tags: [Media, Upload Data, File Management]
-keywords: [Media, Upload Data, Firebase Storage, Supabase Storage]
----
-
-
-
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-# Upload or Save File
-
-Using this action, you can upload any type of file to your app (e.g., PDF, MP3, etc.). You can store the file on [Firebase](https://firebase.google.com/docs/storage), [Supabase](https://supabase.com/docs/guides/storage) storage, or your own server using an API. Once uploaded, you can access the file through its generated URL. This URL can be used to display the content immediately or store it in a database for future retrieval.
-
-
-
-:::info[Prerequisites for Firebase]
-1. **Firebase** should be connected to your project. Follow the instructions on [**this page**](../../ff-integrations/database/cloud-firestore/getting-started.md) for integrating Firebase with FlutterFlow.
-2. **Firebase Authentication** must be properly configured. Check out [**this page**](../../ff-integrations/authentication/firebase-auth/auth-initial-setup.md) for setting up authentication.
-3. **Firebase Storage** must be set up and properly configured. It takes just a second! Follow the instructions on [**this page**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
-4. At least one **Firebase Collection** should be configured for the project so that you can store the generated URL.
- :::
-
-
-:::info[Prerequisites for Supabase]
-
-1. Make sure to [**integrate Supabase**](../../ff-integrations/supabase/supabase-setup.md) into your app.
-2. [**Create a storage bucket**](https://supabase.com/docs/guides/storage/quickstart#create-a-bucket) in Supabase.
- **Tip**: To let anyone download the uploaded media, you can enable the 'Public bucket.'
-
-
-
-
-
-3. Apply additional [**security rules**](https://supabase.com/docs/guides/storage/quickstart#add-security-rules) which determine who can access the bucket. **Tip**: If you are uploading to a folder structure like this '*pics/uploads*,' here is how you can add a policy that allows only authenticated users to upload their profile picture.
-
-
-
-
-:::
-
-## Upload File: Tutorial
-
-Let's build a simple example that allows you to upload the PDF file. Here's how it looks:
-
-
-
-Building the upload file feature comprises the following steps:
-
-1. [Firebase only: deploying Firebase Storage rules](#1-firebase-only-deploying-firebase-storage-rules)
-2. [Optional: enabling Web access](#2-optional-enabling-web-access)
-3. [Adding Upload/Save File action](#3-adding-uploadsave-file-action)
-4. [Preview uploaded file](#4-preview-uploaded-file)
-
-### 1. Firebase only: deploying Firebase Storage rules
-
-Firebase storage rules define who can access the uploaded file. It is essential to set up and deploy the rules before getting started. First, you must enable the *Firebase Storage* on the *Firebase Console* and then deploy its security rules. You can do this from right inside *FlutterFlow*.
-
-Check [**how to deploy the Firebase Storage rules**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
-
-### 2. Optional: enabling Web access
-
-If you plan to support the web version of your app or want to test the PDF upload feature in the *Run* Mode, you need to complete an additional configuration that is required for some file types, such as PDF, to work. Learn how to [enable web access](upload-data.md#web-access-for-pdfs-and-other-files).
-
-### 3. Adding Upload/Save File action
-
-Go to your project page on FlutterFlow and follow the steps below to define the action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-3. Click on the **+ Add Action**.
-4. Search and select the **Upload/Save File** (under *Utilities > Upload Data*) action.
-5. If you haven't integrated Firebase or Supabase yet, the default upload type will be **[Store media for upload](upload-data.md#local-upload-widget-state)**. However, once integrated, you can choose the **Upload Type** as [Firebase](upload-data.md#firebase), [Supabase](upload-data.md#supabase) or [Local (Widget State)](upload-data.md#local-upload-widget-state).
-6. Use the **File Type** dropdown to specify whether you want to upload a **PDF**, **Audio (MP3),** **ANY,** or **Uploaded Media**. The *Uploaded Media* option is there for uploading the media stored on the device. If you choose **Uploaded Media**, ensure you add one more same action (before this action) with **Upload Type** set to [**Local Upload (Widget State)**](upload-data.md#local-upload-widget-state).
-7. You can **Allow multiple Files** to be uploaded. After the multiple files are uploaded, you can access them via *Set from Variable menu > Widget State > Uploaded File URLs (`List `).*
-8. To let users know whether the file is still being uploaded, you can enable the 'Show Snackbar' option.
-9. In *Upload Type*,
- 1. If you selected ***Firebase***, you must [deploy the storage rules](../../ff-integrations/storage/firebase-storage/storage-rules.md).
- 2. If you selected **Supabase**, provide the **Bucket Name** and set the **Uploaded Folder Path** (e.g., attachments/pdfs). This is the path where the files will be uploaded.
- 3. If you selected ***Local Upload (Widget State)**,* you probably want to store the file on the device first and then upload it to your backend server via API. To do so, add the next action as an [**API call**](../../resources/control-flow/backend-logic/api/create-test-api-calls.md) and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. See how to [configure an API for the multipart request body](../../resources/control-flow/backend-logic/api/rest-api.md). **Tip**: When this type is selected, you have an option to directly display the PDF before it gets uploaded to your server; see [here](#41-access-file-from-bytes-in-memorynot-yet-uploaded).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### 4. Preview uploaded file
-
-Once the file is uploaded, you get the uploaded file URL. You can use it to display the content inside the supported widget.
-
-Here is an example showing a PDF file in a PdfView widget.
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the **Properties Panel** (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **Network Path** and click on the **Set from Variable**.
-4. For media uploaded on **Firebase** or **Supabase**, select the **Source** as ***Widget State*** > ***Uploaded File URL***.
-5. For media uploaded via **API**, select the **Source** as **Action Outputs > [Action Output Variable Name] (Api Response)**. This should be the response of the API that was used to upload the file, and it must contain the URL of the uploaded file. To retrieve the url from API response, see how to [use JSON path](../../resources/control-flow/backend-logic/api/rest-api.md).
-6. You can display the placeholder until the current file is uploaded. To do so, click the **Set from Variable** and specify a placeholder URL under the **Default Value** property.
-7. Click on **Confirm**.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#### 4.1 Access file from bytes (in memory/not yet uploaded)
-
-If you simply wish to display a PDF within your app without uploading it anywhere, or if you'd like to preview the PDF before sending it to your server through an API, you can achieve this by configuring the **PDF Source** as **Uploaded File** and specifying the **Uploaded File** source as **Widget State -> Uploaded Local File**.
-
-
-
diff --git a/docs/ff-concepts/file-handling/upload-save-media.md b/docs/ff-concepts/file-handling/upload-save-media.md
deleted file mode 100644
index ac45fb2e..00000000
--- a/docs/ff-concepts/file-handling/upload-save-media.md
+++ /dev/null
@@ -1,382 +0,0 @@
----
-title: Upload or Save Media
-slug: /concepts/file-handling/upload-save-media
-sidebar_position: 5
-tags: [Media, Upload Data, File Management]
-keywords: [Media, Upload Data, Firebase Storage, Supabase Storage]
----
-
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-
-# Upload or Save Media
-
-This action allows you to easily upload a photo or video to your app. You have the flexibility to store the file on [Firebase](https://firebase.google.com/docs/storage), [Supabase](https://supabase.com/docs/guides/storage) storage, or your own server using an API. Once uploaded, you can access the file through its generated URL. This URL can be used to display the content immediately or store it in a database for future retrieval.
-
-
-
-
-
-
-
-
-:::info[Prerequisites for Firebase]
-1. **Firebase** should be connected to your project. Follow the instructions on [**this page**](../../ff-integrations/database/cloud-firestore/getting-started.md) for integrating Firebase with FlutterFlow.
-2. **Firebase Authentication** must be properly configured. Check out [**this page**](../../ff-integrations/authentication/firebase-auth/auth-initial-setup.md) for setting up authentication.
-3. **Firebase Storage** must be set up and properly configured. It takes just a second! Follow the instructions on [**this page**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
-4. At least one **Firebase Collection** should be configured for the project so that you can store the generated URL.
- :::
-
-
-:::info[Prerequisites for Supabase]
-
-1. Make sure to [**integrate Supabase**](../../ff-integrations/supabase/supabase-setup.md) into your app.
-2. [**Create a storage bucket**](https://supabase.com/docs/guides/storage/quickstart#create-a-bucket) in Supabase.
- **Tip**: To let anyone download the uploaded media, you can enable the 'Public bucket.'
-
-
-
-
-
-3. Apply additional [**security rules**](https://supabase.com/docs/guides/storage/quickstart#add-security-rules) which determine who can access the bucket. **Tip**: If you are uploading to a folder structure like this '*pics/uploads*,' here is how you can add a policy that allows only authenticated users to upload their profile picture.
-
-
-
-
-:::
-
-
-## Adding Upload/Save Media action
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the **Properties Panel** (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window. If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile and select **Add Action**.
-3. Search and select the **Upload/Save Media** (under *Utilities > Upload Data*) action.
-4. If you haven't integrated Firebase or Supabase yet, the default upload type will be **[Store media for upload](upload-data.md#local-upload-widget-state)**. However, once integrated, you can choose the **Upload Type** as [Firebase](upload-data.md#firebase), [Supabase](upload-data.md#supabase) or [Local (Widget State)](upload-data.md#local-upload-widget-state).
-5. Use the **Media Type/Source** to specify whether you want to upload a photo or a video, or both using this action.
-6. Using **Media Source** dropdown, you can choose between ***Camera***, ***Gallery**,* and ***Either Camera or Gallery*** (this option will bring up a bottom sheet from where the user can choose the media source as Camera or Gallery) and **Uploaded Media**. If you choose **Uploaded Media**, ensure you add one more same action (before this action) with **Upload Type** set to **Local Upload (Widget State)**.
-7. If you are uploading a photo, you can set a maximum width and height for it by using the **Max Width** and **Max Height** properties, respectively. This will modify the image dimension by maintaining the photo's aspect ratio.
-8. You can control the **Image Quality** by using the slider or directly entering the value. The value must be 0 to 100, where 100 is the original quality.
-9. To retrieve the uploaded media's dimensions, i.e., width and height, enable **Include Media Dimension**. This computation is expensive, so be sure before you enable it.
-10. Use the **Source Picker Style** to tailor the appearance of the bottom sheet UI that opens when selecting either *Camera* or *Gallery*.
-11. You can **Allow multiple images**. Note that for this to work, the *Media Source* must be set to only *Gallery*. After the multiple images are uploaded, you can access them via *Set from Variable menu > Widget State > Uploaded File URLs (`List `).*
-12. To let users know whether the image is still uploading, you can enable the **Show Snack bar**.
-13. If you selected *Either Camera or Gallery*, you would be presented with a few more properties to define the **Source Picker Style** (the bottom sheet design). You can specify the ***Font Family***, ***Text Color***, and ***Background Color*** of the bottom sheet.
-14. In *Upload Type*:
- 1. If you selected ***Firebase***, you must [deploy the storage rules](../../ff-integrations/storage/firebase-storage/storage-rules.md).
- 2. If you selected **Supabase**, provide the **Bucket Name** and set the **Uploaded Folder Path** (e.g., pics/uploaded). This is the path where the media will be uploaded.
- 3. if you selected ***Local (Widget State)**,* you probably want to upload the media to your backend server via API. To do so, add the next action as an **API call** and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. See how to [configure an API for the multipart request body](../../resources/control-flow/backend-logic/api/rest-api.md). **Tip**: When this type is selected, you have an option to directly display the image before it gets uploaded to your server; see [here](#display-images-from-bytes-in-memorynot-yet-uploaded).
-15. Once you have uploaded the media, see how to display it on a widget in the [next section](#showing-uploaded-media).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### Showing uploaded media
-
-For displaying the media on the same page from where the **Upload/Save Media Action** is called, follow the steps below:
-
-1. Drag and drop the appropriate widget that can display the uploaded media. For example, to display uploaded photo, you can use the **Image** widget. Similarly, for video, use the **VideoPlayer** widget.
-2. Move to the properties panel, set its **Type** to **Network**, and click **Set from Variable**.
-3. For media uploaded on **Firebase** or **Supabase**, select the **Source** as ***Widget State*** > ***Uploaded File URL***.
-4. For media uploaded via **API**, select the **Source** as **Action Outputs > [Action Output Variable Name] (Api Response)**. This should be the response of the API that was used to upload the media, and it must contain the URL of the uploaded media. To retrieve the URL from API response, see how to [use JSON path](../../resources/control-flow/backend-logic/api/rest-api.md).
-5. To show the placeholder image/video until the current one is uploaded, click the **Set from Variable** and specify a placeholder image/video URL under the **Default Value** property.
-6. Click on **Confirm**.
-
-:::tip
-To ensure smooth functionality, it's important to provide a **Default Value** when displaying media on the same page as the upload action. Without it, you may encounter errors during app runtime due to an initially empty URL. Once this action is triggered and the media is successfully stored on Firebase/Supabase Storage, the URL becomes accessible.
-:::
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#### Display images from bytes (in memory/not yet uploaded)
-
-If you simply wish to display an image within your app without uploading it anywhere, or if you'd like to preview the image before sending it to your server through an API, you can achieve this by configuring the **Image Type** as **Uploaded File** and specifying the **Uploaded File** source as **Widget State -> Uploaded Local File**.
-
-
-
-
-### Storing the uploaded media URL
-
-You should store the uploaded media URL in your database (Firebase collection or database table) so that you can easily access it later inside the app.
-
-#### Save URL in Firebase collection
-
-To save URL in a Firebase collection:
-
-1. Ensure you have a **field** that can store a photo or video path, for example, `photo_url (Data Type: Image Path)` or `video_url (Data Type: Video Path)`.
-2. Now use the Firebase [Create](../../ff-integrations/database/cloud-firestore/firestore-actions.md#create-document-action)/[Update](../../ff-integrations/database/cloud-firestore/firestore-actions.md#update-document-action) document action to store the URL in a field.
-
-:::note
-While choosing *Value Source*, you can set either *Widget State > Uploaded File URL* or directly choose *Uploaded Photo/Video*.
-:::
-
-
-
- 
- Saving uploaded URL in Firestore document
-
-
-
- 
- Saving uploaded URL in Firestore document
-
-
-
- 
- Saving uploaded URL in Firestore document
-
-
-#### Save URL via backend API
-
-You can use your backend AP to store the URL, like you would do for any other data.
-
-
-
-### Adding BlurHash
-
-BlurHash is a new and innovative way of generating image placeholders that are both compact and visually appealing. When you're scrolling through a web or mobile app, you may have noticed that some images take longer to load. This can be frustrating and disrupt the user experience. That's where BlurHash comes in - it provides a way to display a blurred version of the image that looks similar to the original while the real image is loading in the background.
-
-With BlurHash, you can create more visually appealing and contextually relevant placeholders that better reflect the content of the image being loaded. It can be used in a variety of contexts, from photo galleries and social media apps to e-commerce and news apps.
-
-Here's how it looks when images are loaded with BlurHash:
-
-
- 
- Using BlurHash to display cat images
-
-
-Here are the steps to generate and use the BlurHash:
-
-1. [Generate BlurHash](#generate-blurhash)
-2. [Save BlurHash](#save-blurhash)
-3. [Use BlurHash](#use-blurhash)
-
-#### Generate BlurHash
-
-There is no separate action to generate the Blurhash. Instead, you can generate it using the **Upload/Save Media** action. From the page where you upload the image, use this action and simply enable the **Include Blur Hash** option. This will automatically create a Blurhash for the image being uploaded.
-
-
-
-
-
-
-#### Save BlurHash
-
-The generated BlurHash is accessible via the **Widget State > Uploaded Local File > Media Blur Hash**. Before you use the BlurHash, It is recommended to store it in the same collection or table where you save the image URL for convenient access.
-
-
- 
- Collection schema to store BlurHash
-
-
-Here's how you access and save the BlurHash in a Firebase collection using [**create document**](../../ff-integrations/database/cloud-firestore/firestore-actions.md#create-document-action) action:
-
-
-
-
-
-
-
-
-:::tip
-You can also create a [**custom data type**](../../resources/data-representation/custom-data-types.md) called 'image' and then add two fields such as 'image_url' and 'image_blurhash' like this:
-
-
- 
- Custom data type to store image URL and BlurHash
-
-:::
-
-#### Use BlurHash
-
-To use BlurHash, select the **Image** widget, move to the **properties panel**, enable the **Use Blur Hash** option, and then set the **Blur Hash String** value from a variable.
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/uploading-files.md b/docs/ff-concepts/file-handling/uploading-files.md
new file mode 100644
index 00000000..ccc3e743
--- /dev/null
+++ b/docs/ff-concepts/file-handling/uploading-files.md
@@ -0,0 +1,223 @@
+---
+slug: /concepts/file-handling/uploading-files
+title: Uploading Files
+description: Learn how to upload media in FlutterFlow.
+tags: [Media Files, Upload Data]
+sidebar_position: 1
+keywords: [Media Files, Upload Data, Media Management, Firebase, Supabase, Upload Actions]
+---
+
+# Uploading Files
+
+Uploading files is an essential feature for many apps, enabling users to share images, videos, documents, and more. FlutterFlow offers flexible actions to handle file uploads, whether you’re using Firebase, Supabase, or your own backend server. You can customize the upload process to suit your app’s needs, such as resizing media, setting quality, or temporarily storing files locally before uploading.
+
+This guide covers the available upload methods, configuration options, and workflows, including how to save media locally and upload it via an API.
+
+## Types of Media Uploads
+
+FlutterFlow provides three methods for uploading media files, each catering to different needs:
+
+### Firebase
+
+Media files can be uploaded directly to **Firebase Storage**, a reliable cloud-based solution. Once the upload is complete, you can use the **Widget State > Uploaded File URL** to preview the media or store the file URL for later use.
+
+
+
+### Supabase
+
+You can upload media to a **Supabase bucket** at a specified location. After the upload, the file's URL is accessible via **Widget State > Uploaded File URL**, enabling you to preview the media or save the URL for later use in your app.
+
+
+
+### Local Upload (Widget State)
+
+This method initially stores your media on the device, making it accessible via **Widget State > Uploaded Local File**. You can preview, edit, or process the file before uploading it to a cloud storage.
+
+
+
+## Upload or Save Media [Action]
+
+This action allows you to upload a photo or video to your app. You can choose to store the file on [Firebase](#firebase), [Supabase](#supabase) storage, or your own server using an API. Once uploaded, you can access the file through its generated URL. This URL can be used to display the content immediately or store it in a database for future retrieval.
+
+:::info[Prerequisites for Firebase]
+1. **Firebase** should be connected to your project. Follow the instructions on [**this page**](../../ff-integrations/database/cloud-firestore/getting-started.md) for integrating Firebase with FlutterFlow.
+2. **Firebase Authentication** must be properly configured. Check out [**this page**](../../ff-integrations/authentication/firebase-auth/auth-initial-setup.md) for setting up authentication.
+3. **Firebase Storage** must be set up and properly configured. It takes just a second! Follow the instructions on [**this page**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
+4. At least one **Firebase Collection** should be configured for the project so that you can store the generated URL.
+:::
+
+
+:::info[Prerequisites for Supabase]
+1. Make sure to [**integrate Supabase**](../../ff-integrations/supabase/supabase-setup.md) into your app.
+2. [**Create a storage bucket**](https://supabase.com/docs/guides/storage/quickstart#create-a-bucket) in Supabase. By default, the **Public bucket** option is disabled, meaning uploaded media is not accessible by anyone without authentication. If needed, you can enable the Public bucket option, but this is not recommended for sensitive content.
+
+
+
+
+
+3. Apply additional [**security rules**](https://supabase.com/docs/guides/storage/quickstart#add-security-rules) which determine who can access the bucket. **Tip**: If you are uploading to a folder structure like this '*pics/uploads*,' here is how you can add a policy that allows only authenticated users to upload their profile picture.
+
+
+
+:::
+
+To create an upload media workflow, add the **Upload/Save Media** action to the widget (e.g., a button or any interactive element) where you want users to initiate the file upload. Next, set the [**Upload Type**](#types-of-media-uploads). In the **Media Type/Source** section, specify the type of media to upload: photo, video, or both. Then, use the **Media Source** dropdown to choose the source of the media:
+
+- **Camera**: Directly capture media using the device's camera.
+- **Gallery**: Select existing media from the device's gallery.
+- **Either Camera or Gallery**: Allows users to choose the source via a bottom sheet, letting them select either the camera or the gallery as the media source.
+
+Once the media is uploaded, see how to display it on a widget in the [next section](displaying-media.md).
+
+:::info
+
+When you set **Upload Type** to:
+
+- **Firebase**: You must [**deploy the storage rules**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
+- **Supabase**: Provide the **Bucket Name** and set the **Uploaded Folder Path** (e.g., pics/uploaded). This is the path where the media will be uploaded.
+
+:::
+
+
+
+
+
+
+
+
+The Upload Media action offers various settings to control how media files are uploaded, resized, and processed in your app. Below is a breakdown of all the available properties.
+
+
+
+- **Max Width** and **Max Height**: If you are uploading a photo, you can set a maximum width and height using these properties. This resizes the image while maintaining its original aspect ratio.
+- **Image Quality**: Control the image quality by adjusting the slider or entering a value between 0 and 100, where 100 retains the original quality.
+- **Include Media Dimensions**: Enable this option to retrieve the dimensions (width and height) of the uploaded media. Keep in mind that this operation is resource-intensive, so enable it only if necessary.
+- **Include Blur Hash**: Automatically generates a BlurHash for the uploaded image, allowing you to display a blurred placeholder while the full image loads. For more information, refer to the [BlurHash](displaying-media.md#blurhash) section.
+- **Source Picker Style**: Customize the appearance of the bottom sheet UI that appears when selecting a media source (e.g., Camera or Gallery).
+- **Allow Multiple Images**: Enable this option to allow users to select multiple images. Note that this requires the **Media Source** to be set to **Gallery**. Once multiple images are uploaded, you can access their URLs via **Set from Variable menu > Widget State > Uploaded File URLs (`List`)**.
+- **Show Snackbar**: Enable this option to notify users about the upload progress with a snackbar message.
+
+Check out our YouTube video for a detailed explanation of the **Upload or Save Media [Action]** in FlutterFlow.
+
+
+
+
+
+
+
+
+### Store Media for Upload
+
+You can also save the media file temporarily on the device before uploading it to cloud storage by setting the **Upload Type** to [**Local Upload**](#local-upload-widget-state). This saves the file in Bytes, allowing you to preview, edit, or process it before finalizing the upload.
+
+Once the file is uploaded to the device, you can do the following:
+
+- **Preview or Validate the Media**: Show the user an in-app preview before they decide whether to finalize or discard the upload.
+
+- **Editing Before Submission**: In social media apps, users upload photos for posts or stories. The app temporarily saves the image on the device while users edit or apply filters, and then uploads the final image to cloud storage.
+- **Perform Data Operations**: In document scanning apps, users capture images of documents, which are temporarily stored on the device. The app accesses the file bytes to apply OCR (Optical Character Recognition), enhance contrast, or convert the image to PDF before uploading the final processed file to cloud storage.
+- **Offline Functionality**: Store the media locally and defer uploading until the user regains internet access.
+- **Upload to Server**: When you want to store the file externally, you can then make an API call (e.g., multipart form data) to transfer the local file. Be sure to retrieve and save the resulting file URL in your database if you plan to display it later.
+
+Here are some examples of uploading a file to a device and using it in different scenarios:
+
+**Example 1: Upload to Your Backend Server via API**
+
+First, set the **Upload/Save Media** action with the **Local Upload (Widget State)** upload type. Then, add the next action as an **API call** and select the API that will upload the file to your server. After the API call is complete, ensure your server returns the uploaded file's URL. Use this URL to save in the database or [display the uploaded image](displaying-media.md).
+
+:::info
+The request body for the API must be in *Multipart* format. See how to [**configure an API for the multipart request body**](../../resources/control-flow/backend-logic/api/rest-api.md#multipart-format).
+:::
+
+
+
+
+
+
+
+
+**Example 2: Compress Image Using Custom Action**
+
+First, configure the **Upload/Save Media** action with the **Local Upload (Widget State)** upload type. This temporarily saves the media file on the device.
+
+Next, create and add a [**Custom Action**](../../ff-concepts/adding-customization/custom-actions.md) (e.g., `compressImageAction`) that takes the locally stored file as input and compresses it using its **bytes** data. Ensure the custom action processes the image and returns a compressed file. Once compressed, the file can then be uploaded to cloud storage using another **Upload/Save Media** action.
+
+
+
+**Example 3: Upload to Firebase or Supabase**
+
+First, configure the **Upload/Save Media** action with the **Local Upload (Widget State)** upload type. Once the file is modified or processed, add another **Upload/Save Media** action to the widget that confirms the final upload. Set the **Upload Type** to **Firebase** or **Supabase**, choose **File Type** as the **Uploaded File**, and select **File to Upload** from **Widget State > Uploaded Local File**.
+
+
+
+
+## Upload or Save File [Action]
+
+You can upload any type of file to your app, such as PDFs, MP3s, and more. The process for uploading files is almost similar to the [Upload or Save Media Action](#upload-or-save-media-action).
+
+:::info[Web access for PDF files]
+
+If you plan to support the web version of your app or test the PDF upload feature in **Run Mode**, you’ll need to complete additional configuration steps required for certain file types (e.g., PDFs). Learn how to [**enable web access**](displaying-media.md#web-access-for-pdfs-and-other-files).
+
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/video/_category_.json b/docs/ff-concepts/file-handling/video/_category_.json
deleted file mode 100644
index 9cb05936..00000000
--- a/docs/ff-concepts/file-handling/video/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "Video",
- "position": 1
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/video/video-player.md b/docs/ff-concepts/file-handling/video/video-player.md
deleted file mode 100644
index 33682d18..00000000
--- a/docs/ff-concepts/file-handling/video/video-player.md
+++ /dev/null
@@ -1,271 +0,0 @@
----
-title: VideoPlayer
-slug: /concepts/file-handling/video-player
-sidebar_position: 0
-tags: [Media, Widget]
-keywords: [Media, VideoPlayer, Play Video]
----
-
-# VideoPlayer
-
-The VideoPlayer widget is used to show video from uploaded assets or the URL link. The VideoPlayer widget can play various video formats that include but are limited to MP4, MOV, WAV, MPEG, JPEG motion photo, and so on.
-
-## Adding VideoPlayer Widget
-
-Here's how you can add the VideoPlayer widget to your project:
-
-1. Drag the **VideoPlayer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Path** property and enter the **URL** for the new video.
-
-:::info
-By default, every VideoPlayer widget added to the project will show a sample video from a network URL.
-:::
-
-
-
-
-
-
-
-## Changing the Video Type
-
-By default, the widget is set to play a video from the internet. However, you can change this to use the video uploaded directly to your app.
-
-Here's how you can change the Video Type:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Video Type** dropdown. Click on **Network** (inside the dropdown) and select **Asset**.
-4. Now, find the **Asset Video** property, Click on the **Upload Video** button, select the video and upload it.
-
-
-
-
-
-
-
-If you want to use the same video multiple times in your app, you don't need to upload the same video multiple times. You can use the uploaded video for other VideoPlayer widgets as well.
-
-:::tip
-Once you upload the video, you can use it throughout your app. You can manage your uploaded videos with the Project Media Asset Manager.
-:::
-
-To use the uploaded video:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Video Type** dropdown. Click on **Network** (inside the dropdown) and select **Asset**.
-4. Click on **No asset select** (inside the dropdown) and choose the video.
-
-## Customization
-
-You can customize the appearance of this widget using the various properties available under the properties panel.
-
-### Setting Aspect Ratio
-
-Setting the *Aspect Ratio* to the VideoPlayer allows you to show video in a specific aspect ratio. The height of the widget is determined by applying the given aspect ratio to the width, expressed as a ratio of width to height. For example, setting the value of 1.7 will show the video in a 16:9 aspect ratio.
-
-To set the aspect ratio:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Aspect Ratio** property, if you want to set the aspect ratio of 16:9, enter the value as 1.7 (Simply divide the 16 by 9).
-
-:::tip
-Try changing the width of VideoPlayer and the height will be adjusted as per the aspect ratio.
-:::
-
-
-
-
-
-
-
-### Controlling the AutoPlay
-
-The *AutoPlay* property allows you to configure whether the video should start playing as soon as it loads. By default, this property is disabled and you have to click on the play button to start watching the video.
-
-To enable/disable auto-playing a video:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Enable the **Auto Play** property.
-
-### Enable or Disable Looping of Video
-
-The Loop Video property allows you to configure whether the video should start playing again after it ends. By default, this property is enabled and the video keeps on playing after it ends.
-
-To enable/disable the looping of video:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Loop Video** property, enable or disable to change the looping video behavior.
-
-### Show or Hide Video Controls
-
-The *Show Controls* property allows you to configure whether the player should show the controls over the video such as play-pause button, seek bar, and so on. By default, this property is enabled and all the video controls are visible over the video.
-
-To show/hide video controls:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Show Controls** property, Use it to show or hide controls over the video.
-
-
-
-
-
-
-
-### Controlling Full Screen
-
-The *Allow Full Screen* property allows you to configure whether the player should show the full-screen icon in video controls. By default, this property is enabled and users can open video in full-screen mode by tapping the full-screen icon at the bottom right corner of the player.
-
-To enable/disable full-screen icon:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Allow Full Screen** property, checkmark/uncheck to show/hide the full-screen mode icon.
-
-
-
-
-
-
-
-### Showing Playback Speed Menu
-
-The *Include Speed Playback Menu* property allows you to configure whether the player should show the playback speed menu. The playback speed menu helps users to increase or decrease the speed of the video. By default, this property is disabled.
-
-To show the playback speed menu:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Include Playback Speed Menu** property, checkmark it (click on it).
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/video/youtube-player.md b/docs/ff-concepts/file-handling/video/youtube-player.md
deleted file mode 100644
index 7fb6a17e..00000000
--- a/docs/ff-concepts/file-handling/video/youtube-player.md
+++ /dev/null
@@ -1,127 +0,0 @@
----
-title: YoutubePlayer
-slug: /concepts/file-handling/youtube-player
-sidebar_position: 1
-tags: [Media, Widget]
-keywords: [Media, YoutubePlayer, Play YouTube Video]
----
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-# YoutubePlayer
-
-The **YouTubePlayer** widget in FlutterFlow allows you to seamlessly integrate and play YouTube videos within your app. It offers customizable playback options and an intuitive interface for enhancing the user experience.
-
-## Adding YoutubePlayer Widget
-
-To add the YoutubePlayer widget in your project:
-
-Simply drag the **YoutubePlayer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-
-
-
-
-
-
-
-## Setting The Video URL
-
-The YoutubePlayer widget uses Youtube's video URL to play the video. When you add the YoutubePlayer to your app, by default the URL is set to play a random video. You can change the Video URL by using the URL property.
-
-To set the Youtube Video URL:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **URL** property and enter the **URL** for the new video.
-
-
-
-
-
-
-
-
-## Control Looping Video
-
-By default, The Youtube video starts playing again after it is finished playing. You can change this behavior using the Loop Video property.
-
-To control looping:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **Loop Video** property, keep it checked for looping the video or uncheck to stop looping. Click on it.
-
-## Muting The Video
-
-To mute the video:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **Mute Video** property and click to checkmark it.
-
-## Enable or Disable Video Controls
-
-By default, when the video is being played, different controls are shown such as volume, play-pause, subtitles, fullscreen. You can enable or disable these controls using the *show controls* property.
-
-To enable or disable video controls:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **Show Controls** property, keep it checked to show controls, or uncheck to hide the controls.
-4. (Optional) To disable the fullscreen control, uncheck the **Show Full Screen Control**.
-
-Here's how it looks on enabling and disabling the Controls:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/ff-concepts/layout/responsive-layout.md b/docs/ff-concepts/layout/responsive-layout.md
index d9f99ee0..4189caf8 100644
--- a/docs/ff-concepts/layout/responsive-layout.md
+++ b/docs/ff-concepts/layout/responsive-layout.md
@@ -196,4 +196,58 @@ To implement this, we can go to its widget properties and toggle the device icon
And now you have a more responsive screen for this shopping app use case that looks good in both mobile and desktop formats.
-With these adjustments, your shopping app now boasts a highly responsive screen that seamlessly adapts to both mobile and desktop formats. This ensures an optimal user experience across all devices, maintaining both functionality and aesthetic appeal.
\ No newline at end of file
+With these adjustments, your shopping app now boasts a highly responsive screen that seamlessly adapts to both mobile and desktop formats. This ensures an optimal user experience across all devices, maintaining both functionality and aesthetic appeal.
+
+## Responsive Value
+
+**Responsive Values** allow you to define different property values, such as widths, heights, font sizes, or padding, for different device sizes (mobile, tablet, desktop, and wide). At runtime, your app evaluates the screen width and automatically applies the appropriate value based on your configurations.
+
+:::info[possible use cases]
+
+- **Adaptive Layouts**: Automatically adjust element sizes to deliver a consistent UI across devices.
+- **Better Readability**: Increase font size on larger screens to improve legibility.
+- **Improved Spacing**: Use different padding or margins on tablets and desktops to optimize content flow.
+
+:::
+
+To set a responsive value, select a widget and choose a property that supports responsiveness. Click **Set from Variable > Responsive Value**, then enter different values for each screen size:
+
+- Mobile (below `Breakpoint Small`)
+- Tablet (below `Breakpoint Medium`)
+- Desktop (below `Breakpoint Large`)
+- Wide (above `Breakpoint Large`)
+
+As you preview on different devices, the property will automatically adjust based on the selected screen size.
+
+:::tip[Customizing Breakpoints]
+
+You can adjust the default screen size breakpoints (mobile, tablet, desktop, wide) in FlutterFlow’s Theme Settings. See how to [**Customize Breakpoints**](#customize-responsive-breakpoints).
+
+:::
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/ff-concepts/localization-accessibility/accessibility.md b/docs/ff-concepts/localization-accessibility/accessibility.md
index 6f60424a..83f148a9 100644
--- a/docs/ff-concepts/localization-accessibility/accessibility.md
+++ b/docs/ff-concepts/localization-accessibility/accessibility.md
@@ -24,7 +24,7 @@ Here are some key accessibility features you can use:
## Semantic Label
-You can use **Semantic Labels** to provide custom descriptions, hints, or to emphasize the importance of specific parts of the widget tree. This ensures that screen reader users receive clear and meaningful information about each widget more effectively.
+**Semantic Labels** enhance your app’s accessibility and SEO by providing meaningful context about widgets for screen readers and search engines. These descriptions are especially helpful for users relying on assistive technologies.
For example, in an e-commerce app, you can add a semantic label to an '*Add to Bag*' button with a message like '*Add the selected item to cart*', which helps users better understand the button's action.
@@ -37,7 +37,7 @@ To add a semantic label for any widget, select the widget, move to the propertie
height: 0,
width: '100%'}}>
-Moreover, to add a semantic label for every widget in your app that has an action trigger `OnTap` or `onLongPress`, you can enable the **Add Warning for Semactic Widgets**. By doing so, you'll get a warning if any widget has action but doesn't have a semantic label added yet.
-
:::tip
+You can also dynamically set semantic labels using variables or expressions. This allows the label to change based on the app context, so screen readers announce exactly what’s on the screen instead of generic terms like "image" or "button." For example, a product image can read out the product name (e.g., "Red Running Shoes" pulled from Firestore) instead of just saying "image."
+:::
+
+### Advanced Semantic Settings (Enterprise Only)
-You can click on the warning item to directly navigate to that widget.
+These settings help make your app more accessible by giving you better control over how screen readers interpret and describe your UI.
+
+:::info
+
+These settings are only available to **Enterprise** users.
:::
+Here’s what each option does:
+
+- **Is Container**: Indicates the widget acts as a grouping for other semantic widgets.
+- **Is Image**: Tells screen readers the widget represents an image.
+- **Is Button**: Declares that the widget behaves like a button.
+- **Is Header**: Identifies a widget as a heading for better navigation.
+- **Explicit Child Nodes**: Forces semantics to include all child nodes, even if normally ignored.
+- **Exclude Semantics**: Prevents screen readers from announcing this widget.
+- **Is Live Region**: Tells assistive tech that the widget’s content may change dynamically and should be re-announced.
+- **Hint Text**: Provides an additional hint for users (e.g., "Double tap to open").
+- **Tooltip Text**: Displays helpful text on long press or hover.
+- **Ordinal Sort Key**: Controls the order in which widgets are accessed by screen readers.
+
+:::tip
+You can add a semantic label for every widget in your app that has an action trigger `OnTap` or `onLongPress`, by enabling the **Add Warning for Semantic Widgets**.
+By doing so, you'll get a warning if any widget has an action but doesn't have a semantic label added yet. You can click on the warning item to directly navigate to that widget.
+:::
+

After you add semantic labels, enable **TalkBack** on Android or **VoiceOver** on iOS to test how screen readers interact with your app. These screen readers will help you verify that all UI elements are read clearly, descriptions are meaningful, and users can navigate logically without getting lost.
Learn more about [enabling screen reader on your device](https://docs.flutter.dev/ui/accessibility-and-internationalization/accessibility#screen-readers).
+## Semantic Announce [Action]
+
+The **Semantic Announce** action lets you notify screen reader users about important UI changes or provide contextual updates. It sends a request to the device’s accessibility service (TalkBack/VoiceOver) to speak the text out loud.
+
+It significantly improves accessibility by allowing screen reader users to receive timely and meaningful feedback. This is especially helpful when visual feedback might be missed or unavailable.
+
+:::tip[possible use cases]
+
+- **Form Submission**: After a user submits a form, you can trigger a screen reader announcement like "Your form has been submitted successfully," giving immediate feedback without requiring visual cues.
+- **Dynamic Content Updates**: When new content is added or changed on the screen—like loading new chat messages or refreshing a feed—you can announce messages like "3 new messages loaded" to ensure screen reader users are aware of the update.
+- **Error or Validation Messages**: If a user enters invalid input, you can announce helpful validation feedback like "Please enter a valid email address".
+
+:::
+
+The Semantic Announce action allows you to trigger screen reader announcements with the following settings:
+
+- **Announcement Text**: The message you want the screen reader to speak aloud (e.g., "Item added to favorites").
+- **Is Text Right to Left**: Set this to True for right-to-left languages like Arabic or Hebrew. It defaults to False, which is appropriate for left-to-right languages like English.
+
+
+
+:::info[Best Practices]
+
+- Long announcements can overwhelm the user. Aim for a concise phrase like "Search complete — 3 results."
+- Too many announcements can confuse or irritate the user. Only announce critical or timely changes that aren’t otherwise discoverable.
+- Use the correct language direction of the message. If your app supports multiple locales, dynamic direction binding can help.
+- Screen reader behavior can vary across Android (TalkBack) and iOS (VoiceOver). Test thoroughly on real hardware to confirm the experience.
+
+:::
+
+## Focus Configuration
+
+**Focus Configuration** helps improve keyboard and remote-control navigation in your app—especially important for web, desktop, TV, and kiosk apps. It controls how users move through widgets using the Tab key or other navigation inputs (like arrow keys or D-pad on TV or remote).
+
+You can control the Focus Configuration using the following properties:
+
+- **Wrap in Focus Traversal Group**: It places a widget (and all its children) in a dedicated group so focus cycles within that region before moving on. For example, if you have a login form with two fields: Email and Password, enabling this option ensures that pressing Tab will cycle only between them (and not jump to unrelated parts of the screen).
+- **Focus Traversal Order**: This sets the exact sequence in which widgets receive focus using numeric values (e.g., 1, 2, etc.). For example, In a sign‑up form, set `Name = 1`, `Email = 2`, and `Password = 3` so pressing Tab moves logically down the form rather than following the raw widget tree.
+- **Show Border on Focus**: Enabling this toggle highlights the widget with a visible border when it receives focus, making navigation clearer. Once enabled, you can customize the border’s appearance using **Border Width**, **Border Color**, and **Border Radius** to match your design.
+
+:::warning
+
+While you can assign a value for the **Focus Traversal Order** of any widget, it won’t take effect unless you enable **Wrap in Focus Traversal Group** on the current widget or one of its parent widgets.
+
+The **Focus Traversal Group** defines a context or scope for focus traversal, and **Focus Traversal Order** only applies within that group. Without it, there's no defined order for the traversal logic to follow.
+
+:::
+
+## Update Text Scaling Factor [Action]
+The **Update Text Scaling Factor** action in FlutterFlow allows you to dynamically adjust the text size across your app during runtime. This is particularly useful for improving accessibility by letting users control the size of the text without having to manually change system settings.
+
+Imagine you have a "+" and "-" button on a page to help users adjust text size. When the user taps the "+" button, the text scaling factor increases by 1, making the text larger. Tapping the "-" button decreases the text scaling factor by 1, making the text smaller. Additionally, a Reset button can be provided to return the text scaling back to its default value.
+
+:::info
+
+This action works in conjunction with the [**Display Settings**](../../resources/projects/settings/general-settings.md#display-settings) configured at the project level, such as **Min Text Scaling Factor** and **Max Text Scaling Factor**.
+
+:::
+
+When configuring the Update Text Scaling Factor action, you can choose from three update types:
+
+- **Set Value**: Directly assigns the text scaling factor to a specific value.
+- **Increment/Decrement**: Adjusts the current scaling factor by a specified amount. A positive value increases scaling, and a negative value decreases it.
+- **Reset**: Restores the text scaling factor to the project's default setting.
+
+
+
## Keyboard Navigation
You can use the [On Shortcut Press](../../resources/ui/pages/page-lifecycle.md#on-shortcut-press-action-trigger) action trigger to bind keyboard shortcuts to specific actions. This makes it easier for users with disabilities to navigate your app, especially in web and desktop environments.
@@ -79,7 +170,7 @@ It enhances accessibility by allowing users to interact without relying solely o
## Haptic Feedback
-Using [Haptic Feedback](../alerts-notification/haptic-feedback.md), you can vibrate the user's device, which is particularly helpful for users with visual or cognitive impairments. It provides a tactile response to indicate that an action has been completed.
+Using [Haptic Feedback](../alerts/haptic-feedback.md), you can vibrate the user's device, which is particularly helpful for users with visual or cognitive impairments. It provides a tactile response to indicate that an action has been completed.
For example, vibrating the user's device when successfully submitting a form.
@@ -108,4 +199,4 @@ You can use tools like [**WCAG Contrast Checker**](https://webaim.org/resources/
- Don't use color as the only means to convey important information. Include text, icons, or patterns to supplement color, making the content accessible to colorblind users.
- Verify your app's UI under high contrast or larger text sizes to ensure it remains readable and usable.
- Use simple gestures like taps and double-taps instead of multi-finger swipes or long presses. Provide alternate ways to perform actions, such as using a button in addition to a swipe gesture.
-- Perform usability tests with individuals with disabilities. Real user feedback is invaluable for identifying issues that might not be caught during standard testing.
\ No newline at end of file
+- Perform usability tests with individuals with disabilities. Real user feedback is invaluable for identifying issues that might not be caught during standard testing.
diff --git a/docs/ff-concepts/localization-accessibility/imgs/semantic-announcement.avif b/docs/ff-concepts/localization-accessibility/imgs/semantic-announcement.avif
new file mode 100644
index 00000000..3c780d02
Binary files /dev/null and b/docs/ff-concepts/localization-accessibility/imgs/semantic-announcement.avif differ
diff --git a/docs/ff-concepts/localization-accessibility/imgs/text-scaling-action.avif b/docs/ff-concepts/localization-accessibility/imgs/text-scaling-action.avif
new file mode 100644
index 00000000..dd3f05c4
Binary files /dev/null and b/docs/ff-concepts/localization-accessibility/imgs/text-scaling-action.avif differ
diff --git a/docs/ff-concepts/navigation-routing/deep-dynamic-linking.md b/docs/ff-concepts/navigation-routing/deep-dynamic-linking.md
index 8bbc6ba5..02bec4e3 100644
--- a/docs/ff-concepts/navigation-routing/deep-dynamic-linking.md
+++ b/docs/ff-concepts/navigation-routing/deep-dynamic-linking.md
@@ -10,7 +10,7 @@ keywords: [FlutterFlow, Deep Linking, Dynamic Linking, Concepts]
# Deep & Dynamic Linking
:::danger[Support for Dynamic Links]
-On August 25th, 2025, Firebase Dynamic Links will be shut down. It's recommended to start exploring alternative solutions for link management and deep linking. Read more about the [**announcement here**](https://firebase.google.com/support/dynamic-links-faq).
+On August 25th, 2025, Firebase Dynamic Links will be shut down. Read more about the [**announcement here**](https://firebase.google.com/support/dynamic-links-faq). It's recommended to start exploring alternative solutions like [**Branch.io**](#branch-deeplinking-library) for link management and deep linking.
:::
Adding deep and dynamic linking allows you to share a special type of link that takes the user right
@@ -34,8 +34,8 @@ requires authentication, you'll see a login page. After successful login, you ca
shared with you.
The best thing to note here is that even if the app has a different flow for accessing the page
-content (e.g. Home Page -> All Posts -> Single Post), you can bypass the flow and directly open a
-specific page (e.g. Single Post).
+content (e.g., Home Page -> All Posts -> Single Post), you can bypass the flow and directly open a
+specific page (e.g., Single Post).
## Deep Link
@@ -84,11 +84,14 @@ In this step, You will set the URL scheme. To do that:
enter the **scheme** **name** (before "://") and **hostname** (after "://").
4. If you want users to navigate back to the home page instead of closing the app when they press
- the back button from a deep link page, enable the **Pages Are Subroutes of Root Page** option. *
- *Tip**: we recommend enabling this option to increase user engagement with your app.
+ the back button from a deep link page, enable the **Pages Are Subroutes of Root Page** option.

+:::tip
+We recommend enabling this option to increase user engagement with your app.
+:::
+
#### 2. Setting page URL
The page URL points to the specific page in your app, which is used on the Web and for deep linking
@@ -176,7 +179,7 @@ Here is how you do it:
-## Dynamic Link
+## Dynamic Links with Firebase Dynamic Links [Deprecated]
The dynamic link opens a specific page in your app. Unlike the deep link, the dynamic link survives
the app install. That means if the user has not installed the app, they can be taken to the
@@ -193,10 +196,7 @@ product
from Firebase) to create dynamic links.
:::
-### Adding Dynamic Link
-
-Let's build an example of sharing and opening a profile page using the dynamic link. The example
-looks like the below:
+Let’s walk through an example of sharing and opening a profile page using a dynamic link. The example will look like this:
@@ -212,7 +212,7 @@ The steps to add the dynamic link are as follows:
5. [Sharing dynamic link](#5-sharing-dynamic-link)
6. [Testing dynamic link](#6-testing-dynamic-link)
-#### 1. Setting up a domain
+### 1. Setting up a domain
The dynamic link requires a domain name that will be used as the URL prefix in the link.
@@ -234,7 +234,7 @@ To set up the domain name, follow the steps below:
Setting up a domain for the dynamic link
-#### 2. iOS setup
+### 2. iOS setup
You must complete additional configuration for the dynamic link to work on the iOS devices.
@@ -278,7 +278,7 @@ To add the Associated Domain capability on App Store:
Adding Associated Domain capability to App Store
-#### 3. Set URL scheme
+### 3. Set URL scheme
In this step, You will set the URL scheme. To do that:
@@ -298,7 +298,7 @@ In this step, You will set the URL scheme. To do that:

-#### 4. Setting page URL
+### 4. Setting page URL
The page URL points to the specific page in your app, which is used on the Web and for deep linking
on mobile.
@@ -320,7 +320,7 @@ To set the page URL:
Setting page URL
-#### 5. Sharing dynamic link
+### 5. Sharing dynamic link
You can share the dynamic link of the current page by adding the [**Generate Current Page Link
**](generate-current-page-link.md)
@@ -330,7 +330,7 @@ To share the dynamic link of the page:
1. Select the page that you would like to open via a deep link.
-2. Select any widget (e.g. share button) from the widget tree or the canvas area.
+2. Select any widget (e.g., share button) from the widget tree or the canvas area.
3. First, add the action
to [Generate Current Page Link](generate-current-page-link.md#defining-generate-current-page-link-action).
@@ -352,7 +352,7 @@ To share the dynamic link of the page:
Sharing dynamic link
-#### 6. Testing dynamic link
+### 6. Testing dynamic link
Dynamic links can not be tested in Run Mode. Instead, you will need to test the links on a real
device/emulator.
@@ -400,4 +400,733 @@ To pass custom data with the link, you need to have the following:
-That's all you need to pass custom data with a **Deep Link** or **Dynamic Link**.
\ No newline at end of file
+That's all you need to pass custom data with a **Deep Link** or **Dynamic Link**.
+
+## Deep Links with Branch.io
+
+Since **Firebase Dynamic Links** have been deprecated and can no longer be used for new Firebase projects, we can integrate a powerful alternative: **[Branch.io](https://branch.io/)** — a cross-platform solution for deep linking and deferred linking.
+
+With Branch, we can support robust deep linking inside FlutterFlow apps without writing a backend from scratch.
+
+
+### Branch.io Configuration
+
+Start by setting up your project in the [Branch Dashboard](https://dashboard.branch.io). Once you’ve created a project:
+
+**1. Note down your Branch Key**
+
+Once you create a project, the first thing you’ll need to do is note down your **Branch Key**.
+
+
+
+
+
+
+
+
+
+This key uniquely identifies your app and will be required later when setting up your FlutterFlow configuration.
+
+**2. Set up Redirect Links**
+
+In the Branch dashboard, you’ll find settings to define fallback URLs — these determine where users are sent if your app isn’t installed. Typically, you would redirect users to the App Store, Play Store, or a custom landing page.
+
+
+
+
+
+
+
+
+Setting up redirects is important because it ensures that your links don't break and that users always have a seamless experience, even if they need to install the app first.
+
+**3. Create a Smart Link**
+
+After setting up your project and redirects, you can create a new Smart Link from the **Quick Links** tab in the Branch dashboard. Here you’ll be able to set a link title, alias, add analytics tags, and customize the social media preview (such as the image, title, and description).
+
+Once saved, Branch will generate a Smart Link that’s ready to use across your campaigns and app flows.
+
+Here's a short demo:
+
+
+
+
+
+
+### FlutterFlow Configuration Setup
+
+To make **Branch Smart Links** work in your FlutterFlow app, you’ll need to update the native configuration files via the **Custom Code** tab in your project.
+
+1. First, create environment variables for:
+ - `branchHostUrl` (e.g., `brnch4.app.link`)
+ - `branchKey` (your Branch key, use it for production and optionally `branchKeyTest` for dev environments. You can toggle modes through Branch dashboard and also through FlutterFlow environment toggling).
+
+2. Then navigate to, FlutterFlow > Custom Code > Configuration Files.
+
+
+**🔧 Android Setup**
+
+1. Create two variables in `AndroidManifest.xml` file named `branchKey` and `branchHostUrl` and bind them to the environment variables we earlier created.
+
+2. Add an `intent-filter` block to your **Main Activity** through the **Activity Tags** hook:
+
+```xml
+
+
+
+
+
+
+```
+
+3. Add an **App Component** block for meta-data:
+
+```xml
+
+
+```
+
+
+
+**🍎 iOS Setup**
+
+1. In `Info.plist`, add a new variable called `branchKey` and bind it to the environment variable.
+
+2. In `Info.plist`, add the following code snippet.
+
+```xml
+branch_key
+{{branchKey}}
+```
+3. In `Runner.entitlements`, add a new variable called `branchHostUrl` and bind it to the environment variable.
+
+4. In `Runner.entitlements`, add the following code snippet.
+
+```xml
+com.apple.developer.associated-domains
+
+ applinks:{{branchHostUrl}}
+
+```
+Branch automatically hosts and serves the `apple-app-site-association` file needed for Universal Links. You don’t need to manually upload it to your domain.
+
+
+**FlutterFlow Routing Setup**
+
+FlutterFlow also defines a Custom URI Scheme (like `myapp://`) by default. Even if you're using Branch for web-based Smart Links, it’s a good idea to keep this in sync.
+
+1. Go to:
+Settings & Integrations > App Settings > App Details
+
+2. Scroll to **Routing & Deep Linking** section.
+
+3. Under Custom URI Scheme, match the URI host/domain to what’s defined in your Branch dashboard (e.g., `brnch4://` or `dreambrush://`).
+
+
+
+Even if your links mainly use `https://`, FlutterFlow's routing engine may still use the custom URI internally. Keeping this field consistent prevents confusion or route mismatches.
+
+You're now ready to use Branch Smart Links in a FlutterFlow app with seamless deferred deep linking, App/Universal Link verification, and environment-based configuration.
+
+### Integrate Flutter Branch SDK
+To integrate Branch with your FlutterFlow app, you'll use the [`flutter_branch_sdk`](https://pub.dev/packages/flutter_branch_sdk) Dart package. This will allow your app to listen to Branch links and respond accordingly.
+
+
+1. Go to your **FlutterFlow project > Settings and Integrations > Pubspec Dependencies** tab, and add the following dependency.
+
+```js
+flutter_branch_sdk: ^5.0.1
+```
+Make sure to use the latest version available from [pub.dev](https://pub.dev/packages/flutter_branch_sdk)
+
+
+2. Create a Custom Action to initialize the Branch SDK. This ensures the Branch session is set up when your app starts.
+
+```js
+import 'package:flutter_branch_sdk/flutter_branch_sdk.dart';
+
+Future initBranch() async {
+ // Add your function code here!
+ await FlutterBranchSdk.init();
+}
+
+```
+
+Call this action inside the **Final Actions** of your `main.dart`.
+
+3. Create another custom action to listen for Branch link clicks and optionally route the user:
+
+```js
+
+// Automatic FlutterFlow imports
+import '/flutter_flow/flutter_flow_theme.dart';
+import '/flutter_flow/flutter_flow_util.dart';
+import '/custom_code/actions/index.dart'; // Imports other custom actions
+import '/flutter_flow/custom_functions.dart'; // Imports custom functions
+import 'package:flutter/material.dart';
+// Begin custom action code
+// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
+
+import 'dart:async';
+import 'package:flutter_branch_sdk/flutter_branch_sdk.dart';
+import 'package:flutter/services.dart';
+
+StreamSubscription
-Integrating the RevenueCat in your app comprises the following steps:
-1. [Setup RevenueCat](#1-setup-revenuecat)
-2. [Enable RevenueCat in FlutterFlow](#2-enable-revenuecat-in-flutterflow)
-3. [Retrieving in-app purchases and subscription details](#3-retrieving-in-app-purchases-and-subscription-details)
-4. [Add RevenueCat actions](#4-add-revenuecat-actions)
-5. [Testing](#5-testing)
-6. [Launch](#6-launch)
-
-## 1. Setup RevenueCat
+## Setup RevenueCat
To set up the RevenueCat, follow these steps carefully:
1. Sign up for a new RevenueCat account [here](https://app.revenuecat.com/).
2. [Create a project](https://www.revenuecat.com/docs/getting-started/quickstart#%EF%B8%8F-create-a-project), [add your app](https://www.revenuecat.com/docs/getting-started/quickstart#%EF%B8%8F-add-an-app--platform), and ensure that you [add service credentials](https://www.revenuecat.com/docs/getting-started/quickstart#%EF%B8%8F-service-credentials) to help RevenueCat communicate with the app stores on your behalf.
3. [Create subscriptions](https://www.revenuecat.com/docs/getting-started/quickstart#%EF%B8%8F-store-setup) in the respective stores.
- 1. While creating subscriptions in Google Play Console, if you see a message saying '***Your app doesn't have any in-app products yet**'* like in this picture, follow the steps below:
+ 1. While creating subscriptions in Google Play Console, if you see a message saying '***Your app doesn't have any in-app products yet**'* like in this picture, follow the steps below:

-
- 1. Return to FlutterFlow and navigate to **Settings & Integrations >** **In App Purchases & Subscriptions >** **RevenueCat**.
-
- 2. Switch on the **Enable RevenueCat**. For now, just enter any random string as your API Key (eg. `testkey`). We’ll update this later.
-
- 3. Now, from the toolbar menu, click **Download APK**
-
- 4. In the Play Console, create a [Closed testing](https://play.google.com/console/about/closed-testing/) track and create a new release.
-
- 5. Upload your **App Bundle** or **APK**, enter the release name, and create the release.
-
- 6. Open the **Subscriptions** tab again. It should let you manage subscriptions now.
+
+ 1. Return to FlutterFlow and navigate to **Settings & Integrations >** **In App Purchases & Subscriptions >** **RevenueCat**.
+
+ 2. Switch on the **Enable RevenueCat**. For now, just enter any random string as your API Key (eg. `testkey`). We’ll update this later.
+
+ 3. Now, from the toolbar menu, click **Download APK**
+
+ 4. In the Play Console, create a [Closed testing](https://play.google.com/console/about/closed-testing/) track and create a new release.
+
+ 5. Upload your **App Bundle** or **APK**, enter the release name, and create the release.
+
+ 6. Open the **Subscriptions** tab again. It should let you manage subscriptions now.
4. [Create Products and Entitlements in RevenueCat](https://www.revenuecat.com/docs/getting-started/quickstart#%EF%B8%8F-configure-products-and-entitlements-in-revenuecat).
-## 2. Enable RevenueCat in FlutterFlow
+### Enable RevenueCat in FlutterFlow
To enable RevenueCat in FlutterFlow, follow the steps below:
@@ -103,9 +95,9 @@ To enable RevenueCat in FlutterFlow, follow the steps below:
-## 3. Retrieving in-app purchases and subscription details
+## Displaying Subscription Details in Your App
-To display the in-app purchases and subscription details, such as price, description, etc., inside the UI elements, you need to retrieve this information from RevenueCat.
+To show in-app purchase and subscription information — such as pricing, product name, and description — within your app’s UI, you'll need to fetch these details from RevenueCat using the appropriate API or method.
Here is an example of retrieving monthly subscription details:
@@ -135,7 +127,7 @@ Here is an example of retrieving monthly subscription details:
-## 4. Add RevenueCat actions
+## RevenueCat Actions
To manage in-app purchases and subscriptions inside your FlutterFlow app, you have to use the RevenueCat Actions. Below are the types of RevenueCat actions:
@@ -222,15 +214,12 @@ Using this action, you can allow users to re-activate the subscription they have
-## 5. Testing
-
-You can test your subscriptions using sandbox environments, which simulate real store behavior without incurring costs. [This document](https://www.revenuecat.com/docs/test-and-launch/sandbox) provides detailed guidelines for testing purchases on [Android](https://www.revenuecat.com/docs/test-and-launch/sandbox/google-play-store) and [iOS devices](https://www.revenuecat.com/docs/test-and-launch/sandbox/apple-app-store).
+## Testing Subscriptions
-## 6. Launch
+You can test your subscriptions using sandbox environments, which simulate real store behavior without incurring costs. Check out the full **[Sandbox Testing Guide](https://www.revenuecat.com/docs/test-and-launch/sandbox)** for more details.
-Before launching your app to production make sure you go through the **Launch Checklist** of RevenueCat:
+Before going live, make sure to review **[RevenueCat’s Launch Checklist](https://docs.revenuecat.com/docs/launch-checklist)** to ensure everything is properly set up for production.
-[In-App Purchase Launch Checklist – RevenueCatRevenueCat](https://docs.revenuecat.com/docs/launch-checklist)
## FAQs
@@ -251,3 +240,8 @@ See more details [here](https://community.revenuecat.com/sdks-51/why-are-offerin
+## Looking for other options?
+
+If you're looking for other tools to manage in-app subscriptions, [**Adapty**](https://adapty.io/) is a solid alternative to RevenueCat — it offers advanced analytics, paywall A/B testing, and seamless integration with iOS and Android apps.
+You can explore the [**Adapty Library on our Marketplace**](https://marketplace.flutterflow.io/item/Mf1oFJcqngHzERZSPNA8) — it's actively maintained by the Adapty team and always kept up to date.
+
diff --git a/docs/ff-integrations/payments/stripe.md b/docs/ff-integrations/payments/stripe.md
index dc6cb824..0d5c6e1d 100644
--- a/docs/ff-integrations/payments/stripe.md
+++ b/docs/ff-integrations/payments/stripe.md
@@ -40,11 +40,11 @@ While using Stripe as the payment provider, users can buy products using credit
:::info[Prerequisites]
-Before starting to set up payments, make sure you have,
+Before starting to set up payments, make sure you:
1. Complete [**Firebase Setup**](../../ff-integrations/firebase/connect-to-firebase-setup.md) for your project.
-2. Enabled [**Firebase Authentication**](../authentication/firebase-auth/auth-initial-setup.md) for your project.
-3. Upgraded your Firebase project to [**Blaze Plan**](https://firebase.google.com/pricing). We use [**Firebase Cloud Functions**](https://firebase.google.com/docs/functions) to process a transaction.
+2. Enable [**Firebase Authentication**](../authentication/firebase-auth/auth-initial-setup.md) for your project.
+3. Upgrade your Firebase project to [**Blaze Plan**](https://firebase.google.com/pricing). We use [**Firebase Cloud Functions**](https://firebase.google.com/docs/functions) to process a transaction.
:::
@@ -58,7 +58,7 @@ Integrating the Stripe Payments in your app comprises the following steps:
4. [Testing](#4-testing)
5. [Releasing to production](#5-releasing-to-production)
-### 1. Setup Stripe payment
+### 1. Setup Stripe Payment
Setting up the Stripe payment includes acquiring the keys from your Stripe account and adding them to FlutterFlow.
@@ -76,7 +76,7 @@ Follow the steps below to set up payment using Stripe:
6. Copy the **Publishable Key** and **Secret Key** from the Stripe API keys page and paste them into the respective fields inside FlutterFlow. If you are using Stripe in test mode, make sure you paste them inside the **Test Credentials** section.
7. Under the **Additional Settings**, you need to specify the following:
1. **Merchant Display Name** (*Required*): Enter a name for the merchant (you) that the user will see while performing the payment.
- 2. **Merchant Country Code** (*Required*): Enter your country code. This must be the 3-digit ISO country code, such as USA, IND, and NGA.
+ 2. **Merchant Country Code** (*Required*): Enter your country code. This must be the 2 digit ISO country code, such as US, IN, and AU.
3. **Apple Merchant ID** (*Optional*): You need to enter this if you want to accept payments through Apple Pay as well. The instructions for using Apple Pay are in [this section](#2-apple-pay-setup-optional).
8. Click **Deploy**.
@@ -86,7 +86,7 @@ Follow the steps below to set up payment using Stripe:
height: 0,
width: '100%'}}>
diff --git a/docs/ff-integrations/search/algolia-search.md b/docs/ff-integrations/search/algolia-search.md
index c4cf73a5..99b341da 100644
--- a/docs/ff-integrations/search/algolia-search.md
+++ b/docs/ff-integrations/search/algolia-search.md
@@ -9,82 +9,30 @@ keywords: [FlutterFlow, Algolia Search, Firestore Search]
# Algolia
-Using Algolia you can add search functionality to your FlutterFlow app. It allows you to search for documents present inside a Firestore Collection. Learn how to integrate Algolia Search with your app by following this tutorial.
+[Algolia](https://www.algolia.com/) is a powerful search-as-a-service platform that provides lightning-fast and highly relevant search capabilities. Integrating Algolia into your FlutterFlow app allows you to implement real-time search functionality, making it easier for users to find relevant information within your app.
:::info[Prerequisites]
-Make sure you:
-- Complete [**Firebase Setup**](../../ff-integrations/firebase/connect-to-firebase-setup.md) for your project.
-- Upgraded your Firebase project to [**Blaze Plan**](https://firebase.google.com/pricing).
-- Have at least one **Firestore Collection** on which you want to perform the search queries.
-:::
-
-## Algolia integration
-Alogolia integration comprises the following steps:
+- Algolia integration in FlutterFlow is tied exclusively to Firestore collections. This means you must [**setup Firebase**](../../ff-integrations/firebase/connect-to-firebase-setup.md) to sync data from Firestore into Algolia for searching.
+- **Upgraded** your Firebase project to the [**Blaze Plan**](https://firebase.google.com/pricing) for the Algolia Firebase Extension to work.
+- Have at least one **Firestore Collection** on which you want to perform the search queries.
-1. [Setup Algolia](#1-setup-algolia)
-2. [Integrate with Firebase](#2-integrate-with-firebase)
-3. [Import existing documents](#3-import-existing-documents)
-4. [Algolia configuration on FlutterFlow](#4-algolia-configuration-on-flutterflow)
-5. [Choose searchable fields](#5-choose-searchable-fields)
-6. [Using Algolia Search](#6-using-algolia-search)
+:::
-### 1. Setup Algolia
+## Algolia integration
-You need to create an Algolia account for using their search service. Follow the steps below to setup Algolia:
+Follow the steps below to integrate Algolia in your FlutterFlow apps:
-1. Login to [Algolia](https://www.algolia.com/). If you don't have an account, create your free Algolia account by going [here](https://www.algolia.com/users/sign_up).
-2. For a new account, fill up the required details and select a region of the data center.
-3. Once you reach the dashboard of Algolia, go to **Settings**.
-4. Select **Applications**. By default, you should already have an application called "(unnamed application)".
-5. Click on the button with three dots present beside it, and select **Rename**.
-6. Enter a name for the Application and click **Save**.
+### Setup Algolia
-
-
-
-
-
+Setting up Algolia involves creating an application, defining an index, and generating an API key with the necessary permissions. Here are the steps in detail:
-### 2. Integrate with Firebase
+#### Step 1: Create an Algolia Application
-You have to configure Firebase for integrating the Algolia search, follow the steps below:
+Login to [Algolia](https://www.algolia.com/). If you don’t have an account, sign up for a free account [here](https://www.algolia.com/users/sign_up). During registration, fill in the required details and select a **data center region**. After signing up, you’ll be presented with an **import data screen**, but you can skip this for now (see button at the top right).
-1. Go to your **Firebase project dashboard**.
-2. Click on **Extensions**.
-3. Click **Install** under ***Search with Algolia***.
-4. In ***Step 1*** (Review billing and usage), it will show some information related to billing, click **Next**.
-5. In ***Step 2*** (Review APIs enabled and resources created), this extension automatically creates a Cloud Function to interact with Algolia, click **Next**.
-6. In ***Step 3*** (Configure extension), you have to fill in some information related to Algolia:
- 1. Enter the **Collection Path** which is actually the name of the Collection that you want to make searchable using Algolia.
- 2. You can skip the **Indexable Fields**.
- 3. For **Algolia Index Name**, go to the Algolia dashboard and create a new index. Enter the same name in this field.
- 4. For **Algolia Application Id**, you can go to the Algolia dashboard page, and check its URL, `https://www.algolia.com/apps/`. Copy the `application_id` and enter in the field.
- 5. For **Algolia API Key**, from the Algolia dashboard go to `Settings > API Keys > All API Keys` and click **New API Key**. Under **Indices**, select the Index that you created earlier. In the **ACL** field, include these options: `addObject`, `deleteObject`, `listIndexes`, `deleteIndex`, `editSettings` & `settings`. Click **Create**. Copy the generated API Key and enter it in the respective field.
- 6. Select a **Cloud Functions location**.
- 7. Click **Install Extension**.
+Next, name your application by navigating to **Settings > Applications** in the Algolia dashboard. By default, you should see an application called **"(unnamed application)"**. Click the three-dot button beside it, select **Rename**, enter a name for your application, and click **Save**.
-Wait for the extension to get installed before proceeding to the next phase.
-### 3. Import existing documents
-
-Once you have the Algolia extension installed on Firebase, it starts monitoring the Collection and automatically adds the documents that are created or updated in the Firestore Collection to Algolia Index.
-
-But for the documents that were present in the Firestore Collection before the extension was installed, won't get added to Algolia Index automatically.
-
-:::info
-You will find the specific instructions for importing your documents to Algolia by going to **Extensions > Manage (under Search with Algolia) > How this extension works** page. To keep it simple, the steps are listed below.
-:::
-
-To use the import script you'll need a **Firebase service account**, follow the steps below:
+#### Step 2: Create an Index
-1. Go to your Firebase project dashboard.
-2. Click **Settings** (the gear icon on the left menu), and select **Project settings**.
-3. Go to the **Service accounts** tab.
-4. Under ***Firebase Admin SDK***, click **Generate new private key**.
-5. In the dialog that opens up, click **Generate key**.
+An **index** in Algolia is like a **database table** where your searchable data is stored. To create an index, go to the **Search** section in the left menu, then select **Index**. Click on **Create Index**, and **provide an exact name that corresponds to the Firestore collection** on which you intend to perform the search queries.
-This will download the service account private key to your system, store it in a secure location, and don't share this key anywhere.
+#### Step 3: Generate an API Key
-Follow the steps below to import your existing documents to Algolia:
-
-1. To run the script, you need to have `npx` installed on your system. If you don't have it installed, install [Node.js](https://www.nodejs.org/) (`npx` comes along with it).
-2. From the Firebase dashboard, go to **Extensions > Manage (under Search with Algolia) > How this extension works** page. Copy the import script and run it on your system, the command will look like this:
-
-```
- LOCATION=us-central1\
- PROJECT_ID=\
- ALGOLIA_APP_ID=\
- ALGOLIA_API_KEY=\
- ALGOLIA_INDEX_NAME=\
- COLLECTION_PATH=\
- GOOGLE_APPLICATION_CREDENTIALS=\
- npx firestore-algolia-search
-```
-
-:::warning
-Don't use the above script directly, you need to replace all the angle brackets with the appropriate values of those fields.
-
-It's **recommended** to just copy the script from the page specified above (it will contain all the values specific to your Collection), remove the `FIELDS` and `TRANSFORM_FUNCTION` params if it contains `{ unspecified parameter }`, enter the correct credentials path, and run it.
-:::
-
-After running this command if you navigate to the Algolia Search Index page, you will find all your existing Firebase documents imported there.
-
-
-
-
-
-
-
-
-### 4. Algolia configuration on FlutterFlow
-
-In order to use Algolia Search in your apps, you have to configure Algolia on FlutterFlow. Follow the steps below:
+To integrate Algolia, you need an **API key** with the correct permissions. In the Algolia dashboard, go to **Settings > API Keys > All API Keys**, then click **New API Key**. Under **Indices**, select the index you created in the previous step. In the **ACL (Access Control List)** field, include these permissions: `addObject`, `deleteObject`, `listIndexes`, `deleteIndex`, `editSettings`, and `settings`. Click **Create**, then copy the generated API Key and keep it handy—you’ll need it next to [configure Algolia Firebase Extension](#sync-firebase-data).
-1. Go to the [FlutterFlow dashboard](https://app.flutterflow.io/).
-2. Click **Settings and Integrations** (the gear icon) from the Navigation Menu (left side menu).
-3. Select **Integrations > Algolia**.
-4. On the **Algolia Configuration** page, first, you have to enter the **Application ID**. You will find it on the Algolia dashboard page, copy the application ID from the URL: `https://www.algolia.com/apps/`.
-5. You will get the **Search API Key** by going to `Algolia Settings > API Keys`. Copy the **Search-Only API Key** and paste it into the respective field of FlutterFlow.
-6. Under **Indexed Collections**, select the Collections to be indexed by Algolia Search.
+### Sync Firebase Data
-### 5. Choose searchable fields
+To sync your data from Firebase to Algolia, you must install [Algolia Firebase Extension](https://extensions.dev/extensions/algolia/firestore-algolia-search). It allows you to seamlessly connect **Cloud Firestore** with **Algolia**, ensuring that any updates, additions, or deletions in Firestore are instantly reflected in your search index.
-If you don't want all the fields of any Collection to be used for searching a document, you can choose the fields that you want to be indexable by Algolia.
+Follow these steps to set up the official Firebase extension for Algolia search:
-Follow the steps below:
+1. **Open Firebase Extensions:** Go to the [**Search Firestore with Algolia**](https://extensions.dev/extensions/algolia/firestore-algolia-search) extension page, then click **Install in Firebase Console**. Choose your project to proceed with the installation.
-1. From the Algolia dashboard, select **Search** (present on the left menu).
-2. Select **Index** under **Configure**, and go to the **Configuration** tab.
-3. Click **+ Add a Searchable Attribute** button.
-4. Enter the **name** of the field that you want Algolia to use while searching.
-5. Repeat **Steps 3 & 4** if you want to add more fields.
-6. Click **Review and Save Settings**, and then **Save Settings** inside the dialog that opens up.
-
-Now, Algolia will only use the fields that you specified here while searching for any term in your app.
+2. **Update Extension Instance ID (Optional)**: An extension instance ID uniquely identifies each installed instance of an extension within your Firebase project. This ID is used to manage the extension instance, including updating or uninstalling it.
+3. **Review Billing and Usage:** A summary of billing details will appear. After reviewing, click **Next**.
+4. **Review APIs Enabled and Resources Created:** This extension automatically creates some resources like Cloud Functions and APIs to interact with Algolia. Check the listed resources, then click **Next**.
+5. **Review Access Granted to this Extension:** You'll be presented with a list of specific services and resources that the extension needs access to. Review the permissions, then click **Next**.
+6. **Configure Extension:** During installation, you'll be prompted to provide the following details.
+ - **Collection Path**: Specify the name of the Firestore collection you want to index for search.
+
+ - **Indexable Fields (Optional)**: You can leave this blank to index all fields or manually list fields you want indexed.
+ - **Force Data Sync (Optional)**: You can enable this to ensure that the extension performs an additional read operation from Firestore before processing and sending data to Algolia. It guarantees that the most recent and accurate data is indexed.
+ - **Algolia Index Name**: The name of the index you created (in [step 2](#step-2-create-an-index)) in Algolia Setup.
+ - **Algolia Application ID**: You can go to the Algolia dashboard page and check its URL, `https://www.algolia.com/apps/`. Copy the `application_id` and enter it in the field.
+ - **Algolia API Key**: Paste the API key you created (in [step 3](#step-3-generate-an-api-key)) during the Algolia Setup and hit **Create Secret** button.
+ - **Full Index Existing Documents**: Set this to **Yes** to import the existing data from the Firestore collection into the Algolia index.
+ - **Cloud Functions Location**: Choose the region for deploying the Cloud Function.
+7. **Install**: Click **Install extension** to finalize. Allow a few moments for the extension to install completely before proceeding to the next steps.
+### Choose Searchable Fields
-### 6. Using Algolia search
-
-There are two methods of using Algolia Search in your app:
-
-- Add an **Action** to trigger the [Algolia Search](#algolia-search) by passing the search term, based upon a user gesture.
-- Add the API Call as a [Backend Query](../../resources/control-flow/backend-logic/backend-query/algolia-search-query.md) that gets triggered automatically as the user navigates to the page.
-
-## Algolia Search
-
-You can trigger an Algolia Search using this Action. This will help users to search for documents present inside a Firestore Collection by providing a search term.
-
-From this page, you will learn to define an Algolia Search Action on FlutterFlow.
-
-### Building Search UI
-
-You need a text that would be provided as the search term while triggering the search query. Usually, you should take the term as user input. A basic search UI contains a TextField and a search IconButton widget.
-
-Follow the steps below to define a search user interface:
+To limit the fields used for searching in Algolia, you can specify which attributes should be indexed. From the **Algolia dashboard**, go to **Search > Index > Configuration** and click **+ Add a Searchable Attribute**. Enter the field name you want Algolia to use and repeat this step for additional fields.
-1. Drag a TextField widget from the [Widget Panel](../../intro/ff-ui/widget-palette.md) and drop it onto the canvas.
-2. You can customize the TextField properties to match your app's design style.
-3. Now, drag a IconButton widget and drop it onto the canvas. You can use a Row widget to keep both the TextField and the IconButton in the same row. In some cases, it's possible to add them inside the AppBar as well (watch the demo below).
-4. Change the icon of the IconButton widget to a search icon, and customize it if required.
-
-
-
-
-
-
-
-
-This completes the building of a simple search user interface. Move on to the next step to define the Search Action.
-
-### Define Algolia Search Action
-
-Follow the steps below to define an Algolia Search Action:
-
-1. Select the **widget** (eg., IconButton) on which you want to define the action.
-2. Select **Actions** from the Properties panel (the right menu).
-3. Click **+ Add Action** button.
-4. Choose a gesture from the dropdown among **On Tap, On Double Tap, or On Long Press**.
-5. Select the **Action Type** as ***Algolia Search**.*
-6. Choose the **Firebase Collection** on which to perform the search.
-7. Now, you have to define from where to get the **Search Term**. You can either choose ***Specific Value*** or ***From Variable***. If you want to use a TextField value as the search term, you should choose *From Variable*.
-8. If you have chosen **Specific Value**, define the term inside the field present.
-9. If you have chosen ***From Variable***, select a **Source** from the dropdown menu and then select an option from the **Available Options**. For example, if you want to use the value of a TextField, select the Source as ***Widget State*** and choose the field name under Available Options.
-10. Finally, you can set the number of maximum search results to fetch under **Max Results**.
+Once done, click **Review and Save Settings**, then confirm by clicking **Save Settings** in the dialog. Algolia will now search only within the specified fields in your app.
+### Configure in FlutterFlow
-### Display Search Results
-
-Once you have the Search Action defined, you need to show the results on the UI.
+To integrate **Algolia Search** into your FlutterFlow app, go to **Settings and Integrations > Algolia** and enable it. Enter the **Application ID**, which you can find in your Algolia dashboard URL (`https://www.algolia.com/apps/`). Next, copy the **Search API Key** from **Algolia Settings > API Keys** and paste it into FlutterFlow. Finally, under **Indexed Collections**, select the Firestore collections you want to make searchable.
-Follow the step below to display the search results in your app:
-
-1. Drag and drop a ListView widget onto the canvas. Create a widget inside the ListView for displaying each of the search results.
-2. Select the ListView widget, click on **Generate Dynamic Children** from the Properties Panel.
-3. Enter a **Variable Name** so that the Algolia search results can be referenced while displaying them inside widgets or while passing it to a different page of the app.
-4. Select the **Source** as the name of the results variable where Algolia search data is stored.
-5. Click **Save**. Then, click **Ok** in the dialog box that pops up.
-6. **Set** the Algolia Search data correctly to each of the widgets where want to display the data.
-For example, if you want to show data inside a Text widget, select the widget, click **Set from Variable**, choose **Source** as the variable name where you stored each of the Algolia search data (in step 3), choose the field name from the **Available Options** dropdown whose data who want to display, click **Save**.
+Here’s exactly how you do it:
+## Using Algolia Search
-### Passing Search Result to another page
+You can use Algolia Search in your app using two methods:
-You can use the Algolia search result data from any of the widgets present inside the ListView. To pass this data to a different page of the app, that page should have a **Parameter** defined having the same data type.
+- [**Algolia Search Action**](#algolia-search-action): This method is useful when the user enters a search term in a TextField and then interacts with a widget, such as tapping a button, to initiate the search.
+- [**Backend Query**](../../resources/control-flow/backend-logic/backend-query/algolia-search-query.md): This approach automatically searches or refreshes search results as the user types in the TextField. It leverages the **Update Page On Text Change** property to dynamically update results.
-Follow the steps below to define a parameter:
+### Algolia Search [Action]
-1. Go to the page where you want to pass the data.
-2. Click **Define parameters** button present on top of the Properties Panel.
-3. Click **+ Add Parameter**.
-4. Enter a **Parameter Name**.
-5. Select the **Type** as ***Record Reference***.
-6. Choose the **Record Type** from the dropdown menu.
-7. Click **Save**.
-
-
-
-
-
-
+To configure the **Algolia Search** action in FlutterFlow, begin by selecting the widget that will trigger the search, such as an **IconButton**. In the **Properties Panel**, navigate to the **Actions** tab and click on **+ Add Action**, choose the appropriate gesture, like **On Tap**. Search and select the **Algolia Search** action.
+Next, configure the search parameters: for **Firebase Collection**, select the Firestore collection you intend to search; for **Search Term**, choose **From Variable** and select the TextField's value (e.g., **Widget State > [Your TextField]**); and specify the optional **Max Results** to determine the number of search results.
-Follow the steps below to pass each to the search result to a different page:
-
-1. Select the widget present inside the ListView on which you want to apply the [Navigate](../../ff-concepts/navigation-routing/page-navigation.md#navigate-to-action) Action.
-2. Select **Actions** from the Properties panel (the right menu).
-3. Click **+ Add Action** button.
-4. Choose a gesture from the dropdown among **On Tap, On Double Tap, or On Long Press**.
-5. Select the **Action Type as Navigate**.
-6. Choose Navigation Type as Navigate to Page, select the page under **Navigate To**.
-7. Click **+ Pass in Parameter**.
-8. Select the **Parameter** name from the dropdown.
-9. Choose the **Source** as the Algolia search result variable and select **reference** under **Available Options**.
+Here’s an example of how you can add Algolia Search Action:
-
+## FAQs
+
+
+Does Algolia work with other data sources like Supabase?
+
+
+By default, FlutterFlow’s built-in Algolia integration only supports Firestore as the data source. If you need to use Algolia with another database—such as Supabase—you would have to manage that integration via [**custom code**](../../ff-concepts/adding-customization/custom-code.md). However, out of the box, FlutterFlow currently does not offer an Algolia search on databases beyond Firestore.
+
+
\ No newline at end of file
diff --git a/docs/ff-integrations/storage/firebase-storage/storage-library.md b/docs/ff-integrations/storage/firebase-storage/storage-library.md
new file mode 100644
index 00000000..10bcd94d
--- /dev/null
+++ b/docs/ff-integrations/storage/firebase-storage/storage-library.md
@@ -0,0 +1,104 @@
+---
+slug: /integrations/firebase-storage/storage-library
+title: Firebase Storage Library
+description: The Firebase Storage Library provides access to the files in Cloud Storage through the Firebase SDK beyond what FlutterFlow's built-in support provides.
+tags: [Firebase Storage, Cloud Storage, Integration, Library]
+sidebar_position: 2
+keywords: [FlutterFlow, Firebase Storage, Cloud Storage, Integration, Security]
+---
+
+The [Firebase Storage Library][storage-library-item] provides access to the files in Cloud Storage through the Firebase SDK beyond what [FlutterFlow's built-in support](/concepts/file-handling) provides.
+
+
+[storage-library-item]: https://marketplace.flutterflow.io/item/Ec3NWw8sxqJ1tbriOIEE
+
+## Instructions
+
+To start using this library:
+
+1. [Import the library](/resources/projects/libraries/#importing-a-library) into your existing FlutterFlow project.
+2. [Connect your FlutterFlow project to Firebase](/integrations/firebase/connect-to-firebase/) (if you haven't done so already).
+ The library will default to using the default bucket of your associated Firebase project. You can override this behavior by passing an explicit bucket URL to any of the actions.
+3. [Use the Custom Actions](/concepts/custom-code/custom-actions/#using-a-custom-action) and Custom Functions in your Action Flows.
+
+
+### Custom actions
+
+* `uploadFileToBucket` \- Upload a file to any path in any bucket that you have write access to.
+ * **Parameters:**
+ * The `bucketName` (`String?`) to upload the file to. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `fullPath` (`String?`) where the file will be written to inside the bucket. If this is specified, the `prefix` parameter is ignored.
+ * The `uploadedFile` (`FFUploadedFile`) that is to be uploaded to Cloud Storage. This is the action output of a previous `Store media for upload` action.
+ * The `prefix` (folder/directory) (`String?`) where the file will be uploaded to. If `fullPath` is not specified, the action uses this parameter and the `name` of the `uploadedFile` to determine the full path where it writes the file.
+ * **Action result:**
+ * If successful, the action result is a `fileObject` containing the full path of the uploaded file.
+
+* `listAllFilesInBucket` \- List all files in any bucket that you have read access to.
+ * **Parameters:**
+ * The `bucketName` (`String?`) to list the files from. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `listType` (`StorageListType?`) of the items to list (files, directories, both). If left empty, the action will list both files and prefixes (folders/directories).
+ * The `prefix` (`String?`) is the `/` separated path from which to list files. If left empty, the action will list the items in the root of the storage bucket.
+ * **Action result:**
+ * If successful, the action results in a `List` of `fileObject` elements.
+
+* `downloadFile` \- Download the data for a file that you have read access to. This downloads the actual data into your application code. If you instead want a public URL to the data, use `getDownloadUrl` instead.
+ * **Parameters:**
+ * The `bucketName` (`String?`) to download the file from. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `fullPath` (`String`) of the file whose data will be read from the bucket.
+ * **Action result:**
+ * If successful, the action result is an `FFUploadedFile` with the data of the file that was read from the bucket.
+
+* `getDownloadUrl` \- Get the download URL for a file in a bucket that you have read access to. This URL then provides public, read-only access to the file
+ * **Parameters:**
+ * The `bucketName` (`String?`) that contains the file. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `fullPath` (`String`) of the file for which to get the download URL.
+ * **Action result:**
+ * If successful, the action result is a HTTP URL that allows public access to the file.
+
+* `getMetadataForFile` \- Get the metadata for a file in any bucket that you have read access to
+ * **Parameters:**
+ * The `bucketName` (`String?`) that contains the file. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `fullPath` (`String`) of the file for which to get the download URL.
+ * A**ction result:**
+ * If successful, the action result is a `FullMetadata` with all the metadata and custom metadata of the file.
+
+
+* `updateMetadataForFile` \- Update the metadata for a file in any bucket that you have write access to
+ * **Parameters:**
+ * The `bucketName` (`String?`) that contains the file. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `fullPath` (`String`) of the file for which to get the download URL.
+ * The `metadata` (`SettableMetadata`) to write to the Cloud Storage bucket for the file. If any value is left out or empty in the metadata, it is left unmodified in Cloud Storage.
+ * **Action result:**
+ * If successful, the action result is a `FullMetadata` with all the metadata and custom metadata of the file after the update.
+
+
+* `getPathFromUrl` \- Get the path for a file based on its (https:// or gs://) URL. This is a synchronous call, as it doesn't require any call to the server.
+ * **Parameters**
+ * The `Url` to parse.
+ * **Action result:**
+ * The action result is a `fileObject` derived from the URL.
+
+* `deleteFileFromBucket` \- Deletes a file from any bucket you have write access to.
+ * **Parameters:**
+ * The `bucketName` (`String?`) that contains the file. If you leave this empty, it uses the default bucket of the associated Firebase project.
+ * The `fullPath` (`String`) of the file to delete from the bucket.
+ * **Action result:**
+ * If the action succeeds the file has been deleted. There is no additional information.
+
+### Enums
+
+* `StorageListType` is an enumeration of the types of items that the `listAllFilesInBucket` action can return. Values:
+ * `files`: List only the files in the specified path.
+ * `prefixes`: List only the prefixes in the specified path. You might more commonly refer to these as folders or directories, but since Cloud Storage doesn't actually have support for folders/directories, it uses `/` characters in the file names to emulate those and calls them prefixes.
+ * `filesAndPrefixes`: List both files and prefixes in the specified path.
+
+### Data Types
+
+* `fileObject` \- the metadata for a file or prefix (folder/directory) in Cloud Storage. It has the following fields:
+ * `fullPath` (`String`) \- The full path of the file/prefix inside the storage bucket. The value does not start with a leading `/`.
+ * `isPrefix` (`Boolean`) \- Indicates whether the object is a file (`false`) or prefix (folder/directory) (`true`).
+
+
+* `FullMetadata` \- the full metadata of an item in a storage bucket as returned by `getMetadataForFile`, modelled after the [`FullMetadata` class in the Firebase SDK for Cloud Storage](https://pub.dev/documentation/firebase_storage/latest/firebase_storage/FullMetadata-class.html).
+* `SettableMetadata` \- the settable metadata of an item in a storage bucket, as passed to a call to `updateMetadataForFile`, modelled after the [`SettableMetadata` class in the Firebase SDK for Cloud Storage](https://pub.dev/documentation/firebase_storage/latest/firebase_storage/SettableMetadata-class.html).
+* `KeyValuePair` \- A `String`/`String` key/value pair as used for the `customMetadata` in the `FullMetadata` and `SettableMetadata` data types.
diff --git a/docs/generated-code/component-gen-code.md b/docs/generated-code/component-gen-code.md
new file mode 100644
index 00000000..2645bac2
--- /dev/null
+++ b/docs/generated-code/component-gen-code.md
@@ -0,0 +1,39 @@
+---
+title: Component Model
+slug: /generated-code/component-model
+sidebar_position: 5
+---
+
+# Generated Code: Components
+
+Similar to a [**Page**](pages-generated-code.md), when creating a **[component](../resources/ui/components/intro-components.md)** in FlutterFlow, it automatically generates two files: a `Widget` class and a `Model` class.
+
+:::info[Prerequisites]
+This guide uses examples from the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v2)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
+:::
+
+## ComponentModel class
+
+`ComponentModel` classes are responsible for managing the state and behavior of individual components used within a page. These classes extend the `FlutterFlowModel` class, providing a consistent structure and shared functionality across all component models. This ensures that each component's state is isolated and reusable, making the app easier to maintain and scale.
+
+The lifecycle of a `ComponentModel` and its associated widget class follows the same structure as a page. For more details, refer to the documentation on **[Generated Pages](pages-generated-code.md)**.
+
+### onComponentLoad Action: Generated Code
+
+When you define actions for the `onComponentLoad` action trigger of a component, these actions are added inside an `addPostFrameCallback` method within the page's `initState` method. This ensures that the actions are executed only after the initial widget tree is built.
+
+```js
+ @override
+ void initState() {
+ super.initState();
+ _model = createModel(context, () => ProductListPageModel());
+
+ // On component load action.
+ SchedulerBinding.instance.addPostFrameCallback((_) async {
+ await _model.updateTotalCost(context);
+ safeSetState(() {});
+ });
+
+ }
+```
+
diff --git a/docs/generated-code/custom-data-type-gen.md b/docs/generated-code/custom-data-type-gen.md
index 445f5482..c822632e 100644
--- a/docs/generated-code/custom-data-type-gen.md
+++ b/docs/generated-code/custom-data-type-gen.md
@@ -7,7 +7,7 @@ sidebar_position: 2
# DataTypeStruct class
:::info[Prerequisites]
-This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v1)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
+This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v2)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
:::
diff --git a/docs/generated-code/directory-structure.md b/docs/generated-code/directory-structure.md
index 06490eaf..b94a5903 100644
--- a/docs/generated-code/directory-structure.md
+++ b/docs/generated-code/directory-structure.md
@@ -7,7 +7,7 @@ sidebar_position: 1
# Directory Structure
:::info[Prerequisites]
-This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v1)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
+This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v2)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
:::
When you download the code generated by FlutterFlow, you'll notice many additional files and folders beyond what you see in FlutterFlow's Code Viewer. These files make up the complete project structure, organized according to a specific architecture. Understanding this structure is like having a detailed map, guiding you through the code and making it easier to navigate and customize your FlutterFlow project later. So, let's dive in and explore this directory structure.
diff --git a/docs/generated-code/ff-app-state.md b/docs/generated-code/ff-app-state.md
index a54c8137..ab792043 100644
--- a/docs/generated-code/ff-app-state.md
+++ b/docs/generated-code/ff-app-state.md
@@ -1,19 +1,19 @@
---
title: FFAppState
-sidebar_position: 2
+sidebar_position: 4
---
# FFAppState
:::info[Prerequisites]
-This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v1)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
+This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v2)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
:::
The `FFAppState` class in FlutterFlow acts as a central hub for managing the application's global state. It's designed as a singleton, meaning there's only one instance of this class throughout the app's lifecycle. This class extends [**ChangeNotifier**](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html), allowing widgets to listen and react to state changes.
It includes methods for initializing and updating the app's persisted state and also defines various state variables with corresponding **getters and setters** for manipulating these values.
-Here is a basic template of the class, taken from the [**eCommerceFlow demo app**](https://bit.ly/ff-docs-demo-v1)'s generated code:
+Here is a basic template of the class, taken from the [**eCommerceFlow demo app**](https://bit.ly/ff-docs-demo-v2)'s generated code:
```js
class FFAppState extends ChangeNotifier {
@@ -34,15 +34,14 @@ class FFAppState extends ChangeNotifier {
notifyListeners();
}
- // App State variable of primitive type with a getter and setter
- bool _enableDarkMode = false;
+ // App State variable of primitive type with a getter and setter
+ bool _enableDarkMode = false;
- bool get enableDarkMode => _enableDarkMode;
+ bool get enableDarkMode => _enableDarkMode;
- set enableDarkMode(bool value) {
+ set enableDarkMode(bool value) {
_enableDarkMode = value;
- }
-
+ }
}
```
@@ -52,7 +51,7 @@ The `_enableDarkMode` is an App State variable created by developer that creates
When updating an `AppState` variable from the Action Flow Editor, you will be presented with several **[update type](../resources/data-representation/app-state.md#update-type)** options such as **Rebuild All Pages**, **Rebuild Current Page**, and **No Rebuild** in the Action Settings. Let's see how the generated code changes when these options are selected.
### Rebuild Current Page
-When a developer chooses to update App State with the update type set to **Rebuild Current Page**, the corresponding `setter` is called. Immediately after, `setState((){});` is invoked, which updates only the current page.
+When a developer chooses to update App State with the update type set to **Rebuild Current Page**, the corresponding `setter` is called. Immediately after, `setState(() {});` is invoked, which updates only the current page.
Here's an example of the generated code when we update the App State `enableDarkMode` in the `onInitialization` action trigger of the `ProductListPage`.
@@ -90,7 +89,7 @@ Only the setter is called with no setState or update method invoked afterward. T
When you add an [**Update App State**](../resources/data-representation/app-state.md#update-app-state-action) action via the Action Flow Editor, the corresponding pages will include this line within the build method:
```js
- @override
+@override
Widget build(BuildContext context) {
context.watch();
...
@@ -155,4 +154,4 @@ These functions are automatically generated to provide a convenient and consiste
:::info[How to create App State variables]
To learn more about creating and using App State variables in FlutterFlow's UI, check out the[ **App State**](../resources/data-representation/app-state.md) guide.
-:::
\ No newline at end of file
+:::
diff --git a/docs/generated-code/flutterflow-model.md b/docs/generated-code/flutterflow-model.md
new file mode 100644
index 00000000..de0b875d
--- /dev/null
+++ b/docs/generated-code/flutterflow-model.md
@@ -0,0 +1,109 @@
+---
+title: FlutterFlow Model
+slug: /generated-code/flutterflow-model
+sidebar_position: 4
+---
+
+# FlutterFlow Model
+
+The `FlutterFlowModel` class is an abstract class used in FlutterFlow to provide a unified and extensible structure for managing state and behavior of widgets (both pages and components). It encapsulates **initialization, state management,** and **disposal** logic, making it easier to handle the lifecycle of widgets and their models.
+
+FlutterFlow automatically generates the `flutter_flow_model.dart` file, which contains the `FlutterFlowModel` class and utility methods like `wrapWithModel()` and `createModel()`.
+
+The diagram below illustrates how these utility classes and methods are utilized in a widget or model class:
+
+
+
+
+When a component is added to your page (and every component you create [generates both a widget and a model class)](component-gen-code.md), the flow below explains how the utility classes are used when there is a child component:
+
+
+
+
+
+Here’s a breakdown of the lifecycle of `FlutterFlowModel` class:
+
+## Initialization
+Ensures the model is initialized **only once** and is tied to the `BuildContext` and the widget it is associated with.
+
+```js
+abstract class FlutterFlowModel {
+ // Initialization methods
+ bool _isInitialized = false;
+ void initState(BuildContext context);
+ void _init(BuildContext context) {
+ if (!_isInitialized) {
+ initState(context);
+ _isInitialized = true;
+ }
+ if (context.widget is W) _widget = context.widget as W;
+ _context = context;
+ }
+```
+
+
+## Widget & Context references
+
+Provides references to the associated widget and its `BuildContext`.
+
+```js
+ // The widget associated with this model. This is useful for accessing the
+ // parameters of the widget, for example.
+ W? _widget;
+ W? get widget => _widget;
+
+ // The context associated with this model.
+ BuildContext? _context;
+ BuildContext? get context => _context;
+```
+
+`_widget` and `_context` (private fields) store the widget and context references. `widget` and `context` (getters) are the public accessors for `_widget` and `_context`.
+
+## Disposal
+
+Manages the cleanup of resources when the model or widget is disposed.
+
+```js
+ bool disposeOnWidgetDisposal = true;
+ void dispose();
+ void maybeDispose() {
+ if (disposeOnWidgetDisposal) {
+ dispose();
+ }
+ // Remove reference to widget for garbage collection purposes.
+ _widget = null;
+ }
+```
+The `disposeOnWidgetDisposal` determines whether the model should be disposed when the widget is removed. This defaults to `true` for **pages** and `false` for **components** (as parent models typically manage their child components).
+
+The `maybeDispose()` checks `disposeOnWidgetDisposal` before disposing. It removes the widget reference to aid garbage collection.
+
+## Updates and Change Notification
+
+Allows the model to notify the associated widget or parent component/page when updates occur.
+
+```js
+ // Whether to update the containing page / component on updates.
+ bool updateOnChange = false;
+ // Function to call when the model receives an update.
+ VoidCallback _updateCallback = () {};
+ void onUpdate() => updateOnChange ? _updateCallback() : () {};
+
+ FlutterFlowModel setOnUpdate({
+ bool updateOnChange = false,
+ required VoidCallback onUpdate,
+ }) =>
+ this
+ .._updateCallback = onUpdate
+ ..updateOnChange = updateOnChange;
+
+ // Update the containing page when this model received an update.
+ void updatePage(VoidCallback callback) {
+ callback();
+ _updateCallback();
+ }
+```
+
+## wrapWithModel()
+
+The `wrapWithModel()` method in FlutterFlow links a model to a widget and its child widgets, allowing them to access and manage state. It wraps the widget with a Provider, making the model available throughout the widget tree.
\ No newline at end of file
diff --git a/docs/generated-code/imgs/page-component-generated.png b/docs/generated-code/imgs/page-component-generated.png
new file mode 100644
index 00000000..89f38d1d
Binary files /dev/null and b/docs/generated-code/imgs/page-component-generated.png differ
diff --git a/docs/generated-code/imgs/page-generated.png b/docs/generated-code/imgs/page-generated.png
new file mode 100644
index 00000000..c0ef3f8f
Binary files /dev/null and b/docs/generated-code/imgs/page-generated.png differ
diff --git a/docs/generated-code/imgs/page-generation-initial.png b/docs/generated-code/imgs/page-generation-initial.png
new file mode 100644
index 00000000..668ed040
Binary files /dev/null and b/docs/generated-code/imgs/page-generation-initial.png differ
diff --git a/docs/generated-code/page-model.md b/docs/generated-code/page-model.md
deleted file mode 100644
index 9983cb48..00000000
--- a/docs/generated-code/page-model.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: PageModel class
-sidebar_position: 4
----
-# PageModel class
-
-:::info[Prerequisites]
-This guide uses example of the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v1)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
-:::
-
-
-When you create a new page in FlutterFlow, it automatically generates two files: a `Widget` class and a `Model` class. The `PageModel` classes are responsible for managing the state of individual pages and initializing the components used in these Pages. These classes extend the `FlutterFlowModel` class, which provides a consistent structure and shared functionality across all page models.
-
-A `PageModel` class typically holds local state fields specific to the page, which correspond to the **[Page State variables](../resources/ui/pages/page-lifecycle.md#page-state)**. For example, in the `product_list_page_model.dart` [file](https://github.com/FlutterFlow/sample-apps/blob/main/ecommerce_flow/lib/product/product_list_page/product_list_page_model.dart) (which is the `Model` file for the `ProductListPage`), one of the state fields might be `_searchString`. This private field stores the current search string and includes a getter and setter to manage its value while logging any changes.
-
-```js
-String? _searchString;
-set searchString(String? value) {
- _searchString = value;
- debugLogWidgetClass(rootModel);
-}
-String? get searchString => _searchString;
-```
-
-In addition to managing local state, the `PageModel` class also contains fields for handling the state of widgets on the page. For instance, `_dropDownValue` is a private field that stores the current value of a dropdown widget. Similar to `_searchString`, it has a getter and setter that logs changes to this field.
-
-```js
-String? _dropDownValue;
-set dropDownValue(String? value) {
- _dropDownValue = value;
- debugLogWidgetClass(rootModel);
-}
-String? get dropDownValue => _dropDownValue;
-```
-
-The `PageModel` class is also responsible for initializing the models of components used on the page. For example, if the page includes a `CartCounter` component, the model for this component is initialized within the page's model class.
-
-```js
-// Model for CartCounter component.
- late CartCounterModel cartCounterModel;
-
-@override
-void initState(BuildContext context) {
- cartCounterModel = createModel(context, () => CartCounterModel()..parentModel = this);
-
-}
-```
-
-When dealing with dynamic lists of components, such as those in a `ListView`, Row, or Column widget, the `PageModel` initializes a `Map` to manage the state of each component instance. For example, if the page includes a list of `CategoryAvatar` components, the initialization might look like this:
-
-```js
-// Models for CategoryAvatar dynamic component.
- Map categoryAvatarModels = {};
-
-```
-
-Finally, the `dispose` function in the `ProductListPageModel` class is used to clean up resources when they are no longer needed. This is a common practice in Flutter to prevent memory leaks. In this class, the `dispose` function is overridden to dispose of the `cartCounterModel`, `searchQueryFocusNode`, and `searchQueryTextController`.
-
-```js
-
- @override
- void dispose() {
- cartCounterModel.dispose();
- searchQueryFocusNode?.dispose();
- searchQueryTextController?.dispose();
- }
-```
\ No newline at end of file
diff --git a/docs/generated-code/pages-generated-code.md b/docs/generated-code/pages-generated-code.md
new file mode 100644
index 00000000..d1fd5c93
--- /dev/null
+++ b/docs/generated-code/pages-generated-code.md
@@ -0,0 +1,184 @@
+---
+title: Page Model
+slug: /generated-code/page-model
+sidebar_position: 5
+---
+
+# Generated Code: Pages
+
+When you create a new Page in FlutterFlow, it automatically generates two files: a `Widget` class and a `Model` class. So if the name of the page you created is called **ProductListPage**, FlutterFlow generation backend will automatically create **ProductListPageWidget** class and **ProductListPageModel** class.
+
+:::info[Prerequisites]
+This guide uses examples from the generated code of the **[EcommerceFlow demo app](https://bit.ly/ff-docs-demo-v2)**. To view the generated code directly, check out the **[Github repository](https://github.com/FlutterFlow/sample-apps/tree/main/ecommerce_flow)**.
+:::
+
+## PageModel class
+
+ The `PageModel` classes are responsible for managing the state of individual pages and initializing the components used in these Pages. These classes extend the `FlutterFlowModel` class, which provides a consistent structure and shared functionality across all page models.
+
+The following diagram shows how FlutterFlow generates the model and widget class when you create a new Page in FlutterFlow:
+
+
+:::tip[FlutterFlow Model]
+To learn more about the utility classes and methods that FlutterFlow generates for all pages & components, see [**the FlutterFlowModel document**](flutterflow-model.md).
+:::
+
+
+
+#### Managing Local State
+
+A `PageModel` class typically holds local state fields specific to the page, which correspond to the **[Page State variables](../resources/ui/pages/page-lifecycle.md#page-state)**.
+
+For example, in the ProductListPage, user may create a Page State variable called `searchString`. Correspondingly, in the `product_list_page_model.dart` [file](https://github.com/FlutterFlow/sample-apps/blob/main/ecommerce_flow/lib/product/product_list_page/product_list_page_model.dart) (which is the `Model` file for the `ProductListPage`), the corresponding state field would be `_searchString`. This private field stores the current search string and includes a getter and setter to manage its value while logging any changes.
+
+```js
+String? _searchString;
+set searchString(String? value) {
+ _searchString = value;
+ debugLogWidgetClass(rootModel);
+}
+String? get searchString => _searchString;
+```
+
+:::tip[Private variables in Dart]
+In Dart, variables that start with an underscore (`_`), such as `_searchString`, are private to the class. This means they cannot be accessed outside the class or its scope.
+:::
+
+In addition to managing local state, the given `PageModel` class also contains fields for handling the state of widgets on the page. For instance, `_dropDownValue` is a private field that stores the current value of a dropdown widget (if it is added to the current Page). Similar to `_searchString`, it has a getter and setter that logs changes to this field.
+
+```js
+String? _dropDownValue;
+set dropDownValue(String? value) {
+ _dropDownValue = value;
+ debugLogWidgetClass(rootModel);
+}
+String? get dropDownValue => _dropDownValue;
+```
+
+#### Initializing child component models
+The `PageModel` class is also responsible for initializing the models of components used on the page. For example, if the page includes a `CartCounter` component, the model for this component is initialized within the page's model class.
+
+```js
+// Model for CartCounter component.
+ late CartCounterModel cartCounterModel;
+
+@override
+void initState(BuildContext context) {
+ cartCounterModel = createModel(context, () => CartCounterModel()..parentModel = this);
+
+}
+```
+:::info
+Only the model class of a child component is initialized inside the page or parent model class. In the case of page model classes, they are initialized within the widget’s state class itself. See the **[Widget class section](#pagewidget-class)** for more details.
+:::
+
+When dealing with dynamic lists of components, such as those in a `ListView`, Row, or Column widget, the `PageModel` initializes a `Map` to manage the state of each component instance. For example, if the page includes a list of `CategoryAvatar` components, the initialization might look like this:
+
+```js
+// Models for CategoryAvatar dynamic component.
+ Map categoryAvatarModels = {};
+```
+
+#### dispose()
+
+Finally, the `dispose` function in the `ProductListPageModel` class is used to clean up resources when they are no longer needed. This is a common practice in Flutter to prevent memory leaks. In this class, the `dispose` function is overridden to dispose of the `cartCounterModel`, `searchQueryFocusNode`, and `searchQueryTextController`.
+
+```js
+
+ @override
+ void dispose() {
+ cartCounterModel.dispose();
+ searchQueryFocusNode?.dispose();
+ searchQueryTextController?.dispose();
+ }
+```
+
+
+## PageWidget class
+
+The `PageWidget` classes are responsible for creating the UI of individual pages and holding the widget tree as designed in the FlutterFlow canvas. These classes always extend Flutter's `StatefulWidget` class utilizing Flutter's built-in state management through `setState` to handle dynamic updates and interact with the app's lifecycle.
+
+```js
+class ProductListPageWidget extends StatefulWidget {
+ const ProductListPageWidget({super.key});
+
+ @override
+ State createState() => _ProductListPageWidgetState();
+}
+```
+
+#### PageModel Initialization
+Within the State class, the `PageModel` object is initialized. [This class](#pagemodel-class) serves as a centralized place to manage the page’s state, handle business logic, and interact with the data layer.
+
+```js
+class _ProductListPageWidgetState extends State {
+ late ProductListPageModel _model;
+
+ @override
+ void initState() {
+ super.initState();
+ _model = createModel(context, () => ProductDetailPageModel());
+
+ }
+
+```
+
+#### PageModel Dispose
+Similarly, the [`dispose` method](#dispose) of the `PageModel` class is invoked from the **overridden** `dispose` method of the widget's **State** class. This ensures that any resources managed by the `PageModel`, such as listeners or controllers, are properly released when the widget is removed from the widget tree.
+
+```js
+ @override
+ void dispose() {
+ _model.dispose();
+ super.dispose();
+ }
+```
+
+#### Global Scaffold Key
+Each page includes a `GlobalKey` for the `Scaffold`, which can be used to manage the scaffold's state, such as opening or closing drawers or snackbars programmatically.
+
+```js
+final scaffoldKey = GlobalKey();
+
+return Scaffold(
+ key: scaffoldKey,
+ ...)
+```
+
+#### Keyboard Dismissal
+Moreover, the root widget of every page is a `GestureDetector` with an `onTap` callback that unfocuses the current input field. This approach ensures that tapping anywhere outside an input field dismisses the keyboard or removes focus, creating a better user experience.
+
+```js
+return GestureDetector(
+ onTap: () {
+ FocusScope.of(context).unfocus();
+ FocusManager.instance.primaryFocus?.unfocus();
+ },
+...)
+```
+
+These functionalities are automatically added by FlutterFlow to ensure seamless navigation and proper keyboard handling across pages.
+
+### onPageLoad Action: Generated Code
+
+When you define actions for the `onPageLoad` action trigger of a Page, these actions are added inside an `addPostFrameCallback` method within the page's `initState` method. This ensures that the **on Page Load** actions are executed after the widget is fully built and rendered. This avoids issues caused by trying to update the UI before it is ready.
+
+```js
+ @override
+ void initState() {
+ super.initState();
+ _model = createModel(context, () => ProductListPageModel());
+
+ // On page load action.
+ SchedulerBinding.instance.addPostFrameCallback((_) async {
+ _model.searchString = null;
+ safeSetState(() {});
+ ... // more actions
+ });
+
+ }
+```
+
+:::tip[safe Set State]
+The `safeSetState` method is a custom implementation built on top of Flutter's `setState` method. It ensures that `setState` is only called when the widget is currently mounted, preventing potential runtime errors.
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/state-management/generated-code.md b/docs/generated-code/state-mgmt-gen-code.md
similarity index 58%
rename from docs/ff-concepts/state-management/generated-code.md
rename to docs/generated-code/state-mgmt-gen-code.md
index c755e912..c8f20237 100644
--- a/docs/ff-concepts/state-management/generated-code.md
+++ b/docs/generated-code/state-mgmt-gen-code.md
@@ -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.
-
+
## Page & Component Models
@@ -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.
@@ -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`.
@@ -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
diff --git a/docs/index.md b/docs/index.md
index 08a5bd30..e7c4b109 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -4,7 +4,7 @@ custom_edit_url: null
showLastUpdateTime: false
hide_title: true
slug: /
-hide_table_of_contents: true
+hide_table_of_contents: false
---
import InfoCard from '@site/src/components/InfoCard';
@@ -20,23 +20,140 @@ import BranchIcon from '@site/static/icons/branch_New.png';
-
-# Visual Development Platform
-FlutterFlow is a visual development platform that lets you build mobile, web, and desktop apps incredibly fast, without sacrificing quality or features.
+# Getting Started with FlutterFlow
+FlutterFlow is a visual development environment that lets you build mobile, web, and desktop apps incredibly fast, without sacrificing on app quality or features.
+
+
-
-
-
-
-
-
+
+
+
+
+
### FlutterFlow Tour
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+### Best Practices
+
+Essential guidelines and recommendations for building robust FlutterFlow applications. Discover security best practices and performance optimization techniques to ensure your apps are production-ready, scalable, and maintainable.
+
+
+
+
+
+
+
+### Scaling FlutterFlow Apps
+
+Learn advanced techniques and strategies to scale your FlutterFlow applications from simple prototypes to enterprise-grade solutions with native integrations and modular architecture.
+
+
+
+
+
+
+
+### Additional Tools
+
+Discover additional tools and references to enhance your FlutterFlow development experience:
+
+
+
+
+
+
+## Still Have Problems?
+
+If you're still experiencing issues or need additional help, here are some resources to get you back on track:
+
+- **[Submit Bug Report](/misc/submit-bug-report)** - Report bugs or issues you've encountered
+- **[Community Forum](https://community.flutterflow.io)** - Ask questions and get help from the community
+- **[Reddit Community](https://www.reddit.com/r/FlutterFlow/)** - Join discussions on Reddit
+- **[Documentation Bug](https://github.com/FlutterFlow/flutterflow-documentation/issues)** - Report documentation issues
+- **[Contribute to Documentation](https://github.com/FlutterFlow/flutterflow-documentation?tab=readme-ov-file#how-to-contribute)** - Contribution guidelines for contributing to the FlutterFlow documentation site.
+- **[FlutterFlow Support](mailto:support@flutterflow.io)** - Get direct support from the FlutterFlow support team.
\ No newline at end of file
diff --git a/docs/intro/before-you-begin/app-architecture.md b/docs/intro/before-you-begin/app-architecture.md
index 0a0e0c56..a43af2a7 100644
--- a/docs/intro/before-you-begin/app-architecture.md
+++ b/docs/intro/before-you-begin/app-architecture.md
@@ -22,7 +22,7 @@ This includes:
Backend usually refers to more complex logic and data storage. This includes:
-- Setting up a database that is capabale of storing, sending and retrieving data
+- Setting up a database that is capable of storing, sending and retrieving data
- Leveraging off-the-shelf services, like authentication providers or payment platforms
- Defining business logic, either by writing code or using a low-code tool
diff --git a/docs/intro/before-you-begin/setting-up-flutterflow.md b/docs/intro/before-you-begin/setting-up-flutterflow.md
index 2015caac..e3455aaf 100644
--- a/docs/intro/before-you-begin/setting-up-flutterflow.md
+++ b/docs/intro/before-you-begin/setting-up-flutterflow.md
@@ -29,6 +29,10 @@ The FlutterFlow application can be accessed from your browser or installed as a
- **macOS**: While FlutterFlow should work on 10.13 or higher, we recommend using 13 or higher
- **Windows**: While FlutterFlow should work on 7 or higher, we recommend using 10 or higher
+:::info
+Some Windows users may experience a crash. To fix this, install the [**Microsoft Visual C++ 2015–2022 Redistributable (both x64 and x86)**](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170) from the official Microsoft site.
+:::
+
For details on target platform system requirements, please see the [Flutter documentation](https://docs.flutter.dev/reference/supported-platforms).
### Desktop vs Web:
diff --git a/docs/intro/ff-ui/builder.md b/docs/intro/ff-ui/builder.md
index d7d89397..ef411a38 100644
--- a/docs/intro/ff-ui/builder.md
+++ b/docs/intro/ff-ui/builder.md
@@ -13,7 +13,7 @@ keywords: [App Builder, FlutterFlow, UI, Design]
On opening the project, you'll see the App Builder, which consists of four main sections:
[Navigation Menu](#navigation-menu), [Toolbar](#toolbar), [Canvas](#canvas-area), and [Properties Panel](#properties-panel).
-
+
## Navigation Menu
@@ -34,8 +34,9 @@ Here is a list of all the features accessible from the navigation menu:
11. **Custom Functions**: Add custom functionalities, widgets, and actions.
12. **Cloud Functions**: Write and deploy cloud functions for Firebase.
13. **Tests**: Add automated tests.
-14. **Theme settings**: Customize visual appearance.
-15. **Settings and Integrations**: Access app-related settings and integrations.
+14. **Agents**: Create, configure, and manage [AI Agents](../../ff-integrations/ai/ai-agents.md) to integrate conversational AI interactions into your app.
+15. **Theme settings**: Customize visual appearance.
+16. **Settings and Integrations**: Access app-related settings and integrations.
## ToolBar
diff --git a/docs/intro/ff-ui/dashboard.md b/docs/intro/ff-ui/dashboard.md
index 0e1874ed..77936387 100644
--- a/docs/intro/ff-ui/dashboard.md
+++ b/docs/intro/ff-ui/dashboard.md
@@ -74,6 +74,10 @@ You can also find links to various resources to assist in building apps with Flu
- Additionally, ensure that you have added a name to your FlutterFlow profile. The same name will be used for the community forum profile.
:::
+- **URL Access (Only Available for Enterprise Users)**: You can view and copy URLs that need to be whitelisted for FlutterFlow to function correctly in enterprise environments with restricted internet access. Check out docs on **[Whitelisting URLs](../../misc/enterprise-page.md#whitelist-urls)**.
+
+ 
+
- **Account**: This is helpful if you want to look at your account information, upload a profile picture, reset your password, see your referrals, or delete account.
- **Plan info**: See information about the current plan and eventually upgrade to access additional features.
diff --git a/docs/intro/ff-ui/imgs/navigation-menu.avif b/docs/intro/ff-ui/imgs/navigation-menu.avif
new file mode 100644
index 00000000..89200d55
Binary files /dev/null and b/docs/intro/ff-ui/imgs/navigation-menu.avif differ
diff --git a/docs/intro/ff-ui/imgs/resource-description.avif b/docs/intro/ff-ui/imgs/resource-description.avif
new file mode 100644
index 00000000..0ece4810
Binary files /dev/null and b/docs/intro/ff-ui/imgs/resource-description.avif differ
diff --git a/docs/intro/ff-ui/imgs/toolbar.avif b/docs/intro/ff-ui/imgs/toolbar.avif
index 0e6f05f6..25a8f344 100644
Binary files a/docs/intro/ff-ui/imgs/toolbar.avif and b/docs/intro/ff-ui/imgs/toolbar.avif differ
diff --git a/docs/intro/ff-ui/imgs/url-access-dashboard.avif b/docs/intro/ff-ui/imgs/url-access-dashboard.avif
new file mode 100644
index 00000000..5558856e
Binary files /dev/null and b/docs/intro/ff-ui/imgs/url-access-dashboard.avif differ
diff --git a/docs/intro/ff-ui/my-organization.md b/docs/intro/ff-ui/my-organization.md
index 6320fff0..b2c6280d 100644
--- a/docs/intro/ff-ui/my-organization.md
+++ b/docs/intro/ff-ui/my-organization.md
@@ -13,10 +13,6 @@ From here, you can manage billing for your team, edit projects simultaneously, a
With the ability to easily collaborate and share resources, you can create amazing apps faster than ever before.
-:::info
-Learn [**how to create a team**](../../accounts-billing/subscriptions/flutterflow-for-teams.md) to get started.
-:::
-
diff --git a/docs/intro/ff-ui/resource-hierarchy.md b/docs/intro/ff-ui/resource-hierarchy.md
index 5811bc45..a1a146fd 100644
--- a/docs/intro/ff-ui/resource-hierarchy.md
+++ b/docs/intro/ff-ui/resource-hierarchy.md
@@ -4,11 +4,11 @@ title: Resource Hierarchy Overview
description: Explore the Resource Hierarchy Overview to understand the correlation between traditional Flutter app components and their equivalents in FlutterFlow.
tags: [Resource Hierarchy, FlutterFlow, Project Management]
sidebar_position: 5
-keywords: [Resource Hierarchy, FlutterFlow, Project Management]
+keywords: [Resource Hierarchy, FlutterFlow, Project Management, Resource Description]
---
-# Resource hierarchy overview
+# Resource Hierarchy Overview
This guide aims to help you understand the structure and elements of a typical FlutterFlow project. It will walk you through some important parts of the app, from the overall project down to individual design elements, explaining their purpose and how they relate to traditional Flutter app components.
@@ -34,4 +34,54 @@ If you are coming from Flutter, it is beneficial for you to understand the Flutt
2. **MyPage to Page**: `MyPage` in Flutter represents a specific screen in the app. Similarly, In FlutterFlow, each "Page" corresponds to a screen, where you build the layout and functionality specific to that page of the project. Learn more about pages in FlutterFlow [here](../../resources/ui/pages/intro-pages.md#creating-a-page).
3. **Column, Button, Text to Built-in widgets**: In FlutterFlow, widgets are categorized under "Built-in widgets," which users can drag and drop onto their canvas to build the UI. Learn more about widgets [here](../../resources/ui/overview.md#widgets).
4. **Custom widget to Component**: `CustomWidget` in Flutter indicates user-defined widgets that serve specific functions not covered by built-in widgets. FlutterFlow translates this into "Component" allowing you to create and use custom components within your projects. Learn more about creating a component [here](../../resources/ui/components/intro-components.md).
-5. **Theme/style constants to Design System**: In Flutter, theme and style constants are used to ensure consistent styling across an app. FlutterFlow uses a "Design System" to manage and apply uniform styles and themes throughout the application. Learn more about design system [here](../../ff-concepts/design-system/design-system.md).
\ No newline at end of file
+5. **Theme/style constants to Design System**: In Flutter, theme and style constants are used to ensure consistent styling across an app. FlutterFlow uses a "Design System" to manage and apply uniform styles and themes throughout the application. Learn more about design system [here](../../ff-concepts/design-system/design-system.md).
+
+## Resource Description
+
+A Resource Description is a brief text note that explains the purpose, usage, or key details of a particular resource. By supplying clear, concise descriptions, you create better project documentation and a smoother development experience—both for yourself and any collaborators.
+
+:::info
+Here are some reasons why resource descriptions can be helpful:
+- **Team Collaboration**: When multiple developers or designers work on the same project, concise descriptions help everyone understand each element’s role without guesswork.
+- **Better Search**: Descriptions are indexed in the FlutterFlow search. This helps locate pages, components, and other resources quickly, especially in large projects.
+- **Project Documentation**: Acts as built-in documentation of your app, which makes future updates easier.
+:::
+
+You can add a description for each of the following resources in FlutterFlow:
+
+- **Project**: Use the project-level description to summarize the overall goals or scope of your app. For instance, "A delivery management app for small businesses" helps keep the team aligned on the primary objective.
+- **Page**: Explains a page’s main function. Example: "Displays the user’s shopping cart and checkout options."
+- **Component**: Clarifies the functionality or design intention of a reusable component. Example: "Reusable card component to be used as ListTile."
+- **Action Blocks**: Provide a concise description of what the set of actions does (e.g., "Sends a notification to the user’s email address upon form submission").
+- **Custom Functions**: Describe the logic or purpose behind the function. Example: "Calculates shipping costs based on weight and distance."
+- **Custom Actions**: Specify the custom behavior you’ve created, such as "Opens a QR scanner and returns the scanned value."
+- **Custom Widgets**: Explain the widget’s purpose or structure. Example: "Carousel widget for displaying multiple images with pagination."
+- **Data Type**: Summarizes the purpose of a custom data model. Example: "Represents a user’s order including items, total cost, and status."
+- **Parameters**: Provide context for how a parameter is used, including expected data types or value ranges. Example: "String to store the user’s phone number—must include country code."
+- **Page/Component State Variables**: Clarify what state data is being stored and why. For instance, "Tracks the currently selected tab in this component."
+- **App State Variables**: Describe the global data shared across pages. Example: "Stores the user’s authentication token for all network requests".
+- **Constant**: Add the intended purpose of any fixed value used throughout the app. Example: "Base API URL for all network calls".
+- **Enum**: Provide a rationale for the enumerated values. Example: "Defines possible user roles—admin, editor, viewer".
+- **Firestore Collection**: Explain what data the collection holds and how it relates to your app’s functionality. Example: "Stores all user profiles with fields for name, email, and profile photo URL".
+
+In FlutterFlow, you can read descriptions as tooltips when hovering over the green note icon.
+
+:::tip
+
+In the generated code, FlutterFlow inserts descriptions as docstring-like comments near the relevant classes, methods, or properties. For instance, a data type named `OrderInfo` with a description of “Represents a user’s order, including items, total cost, and status” will have that text added above the class declaration:
+
+ ```jsx
+ /// Represents a user’s order, including items, total cost, and status.
+ class OrderInfo {
+ /// The total price in USD for this order.
+ double totalAmount;
+ List items;
+ // ...
+ }
+ ```
+
+In a standard IDE (e.g., VS Code or Android Studio), if you place your mouse over a custom data type class name, the description set in FlutterFlow appears as a tooltip, helping you quickly grasp the purpose of a resource.
+
+
+
+:::
\ No newline at end of file
diff --git a/docs/intro/ff-ui/storyboard.md b/docs/intro/ff-ui/storyboard.md
index 87ecff3e..1a0b2294 100644
--- a/docs/intro/ff-ui/storyboard.md
+++ b/docs/intro/ff-ui/storyboard.md
@@ -56,6 +56,6 @@ Watch this video if you prefer watching a video tutorial.
## FAQs
-I am getting "Error: Unable to initialize Storyboard
+I am getting "Error: Unable to initialize Storyboard"
This error typically occurs because the initial page has not been set. To resolve this, please set the initial page in the [App Details](../../resources/projects/settings/general-settings.md#app-details) settings of your project.
diff --git a/docs/intro/ff-ui/toolbar.md b/docs/intro/ff-ui/toolbar.md
index a3983710..4119ffd6 100644
--- a/docs/intro/ff-ui/toolbar.md
+++ b/docs/intro/ff-ui/toolbar.md
@@ -13,11 +13,11 @@ The Toolbar, located at the top of the app builder, provides easy access to nume

-## Project info
+## Project Info
Hovering over this section reveals the essential information about your project. Here, you can easily check the project name, branch name, environment name and the current version of FlutterFlow that you're using, along with its release date. Additionally, it shows the Flutter version that your project is currently running on.
-## Help
+## Help Menu
From here, you will get access to essential resource links that will come in handy while building your apps.
@@ -31,7 +31,7 @@ From here, you will get access to essential resource links that will come in han
8. **Current Status/Known Issues**: We want to keep you informed about the current status of FlutterFlow and provide updates regarding any known issues. We aim to ensure transparency and keep you in the loop about the platform's performance and potential issues.
9. **Show/Hide Chat**: You can use this option to show or hide the chat button at the bottom right of the app builder.
-## Keyboard shortcuts
+## Keyboard Shortcuts
With keyboard shortcuts, you can perform common actions related to widgets and run your project in Test or Run mode with just a few keystrokes, saving you time and effort. Select this option to see all the shortcuts.
@@ -43,168 +43,12 @@ The Command Palette makes it easy to find and use things in the App Builder. Ope

-## AI Tools
-FlutterFlow AI Tools is a powerful set of features designed to speed up app development by leveraging artificial intelligence. These tools allow you to quickly generate app elements such as pages, components, and even entire page layouts with relevant widgets automatically populated.
-
-### New Page Creation
-Instantly create pages in your app from a prompt. To create a page, open the **AI Tools** menu from the Toolbar. Next, select **New Page Creation** and enter a description for your page.
-
-
-
-
-
-
-
-### New Component Creation
-Aside from pages, you can also create [Components](/resources/ui/components) directly from a prompt. To create a component, open the **AI Tools** menu from the Toolbar. Next, select **New Component Creation** and enter a description for your UI component.
-
-
-
-
-
-
-
-### Sketch To Component
-Sketch to Component allows you to add a sketch of your [Component](/resources/ui/components). This sketch can include outlines of widgets or layouts to incorporate, and it can also include annotations that tell the AI tool more about the design you have in mind.
-
-To create a Component from a sketch, open the **AI Tools** menu from the Toolbar. Next, select **Sketch to Component** and draw directly in the input or upload an image file of your sketch.
-
-
-
-
-
-
-
-### Page Autocomplete
-Page Autocomplete intelligently adds relevant widgets to a page based on the pages’s context, making it easy to complete partially built pages.
-The project context includes the existing widgets and design of those widgets, as well as the page's description.
-
-If the page does not have a description, you will be asked to describe what you want the page to contain.
-
-To use Page Autocomplete, open the **AI Tools** menu from the Toolbar. Next, and select **Page Autocomplete** on the page that
-you want FlutterFlow AI to complete.
-
-
-
-
-
-
-
-## Canvas size
-
-We allow you to visualize and design your app for various mobile, tablet, and desktop devices. The [canvas](../ff-ui/canvas.md) size is defined as width (in pixels) x height (in pixels). This size is determined according to the device selected. To set a custom canvas size, click on the Canvas Size and enter the width and height (in pixels) you want.
-
-
-
-
-
-
-## Project history
-
-Understand the crucial concepts of project history, such as saving and versioning [here](../../testing-deployment-publishing/branching-collaboration/saving-versioning.md).
-
-## Project comments
+## AI Generation History
+
+The **AI Generation History** panel lets you track the status of your AI-generated items. It provides a list of all previously generated pages and components, and you can easily preview them from here.
+
+
+## Project Comments
This helps you leave your thoughts, opinions, questions, or feedback on a specific widget with your project team or a client. While adding a comment, you can tag users, and they will be able to respond, creating a thread of conversation.
@@ -214,7 +58,7 @@ To tag users, select the @ symbol and choose the project team member(s).
:::
-## Optimizations & Enhancements
+## Project Suggestions
We scan and suggest enhancements to elevate your app's design and speed. Imagine having a personal consultant for design and performance dedicated to improving the user experience of your app.
@@ -230,7 +74,7 @@ You can control what kind of suggestions you would like to receive by clicking o

-## Project issues
+## Project Issues
If there are any issues or warnings present in your current project that might result in a build failure or app crash, they will be displayed in this section. You can click this option to view a short description of each issue and navigate to the place where you can fix the issue by clicking on the respective issue.
@@ -242,11 +86,12 @@ If there are any issues or warnings present in your current project that might r

-## Branching
-[Branching](../../testing-deployment-publishing/branching-collaboration/branching.md) enables you to create a separate copy of your existing project, allowing you to develop new features without affecting the current functionality.
+## Version Control
+**Version Control** is a system that tracks changes to your project's files over time, allowing you to revert to previous states if needed. In FlutterFlow, you can utilize [Branching](../../testing-deployment-publishing/branching-collaboration/branching.md) to create a separate copy of your project to build or test features without affecting the main version.
-## Developer menu
+
+## Developer Menu
The Developer Menu provides developers with access to tools such as code viewing, GitHub integration, and source code download capabilities.
1. **View Code**: This option lets you display the *Dart* code for all the pages of your FlutterFlow project. You can also take a look at the dependencies being used by the app here.
@@ -263,7 +108,11 @@ The Developer Menu provides developers with access to tools such as code viewing
_Connect GitHub Repo_, _Download Code_, and _Download APK_ features requires a [**paid plan**](https://flutterflow.io/pricing).
:::
-## Share project
+6. **Open in VSCode**: This option lets you open your entire FlutterFlow project in a VS Code environment, offering a richer development experience. You’ll have real-time autocomplete and error detection, easier access to existing Flutter & Dart tooling, and the ability to leverage the AI ecosystem.
+
+7. **Refactor Project**: This option opens your FlutterFlow project in a YAML-based file editor, allowing you to perform bulk edits more efficiently. You can search, edit, and replace values across multiple files—useful for renaming keys, updating data types, or migrating resources to a Library. Check out the [**Refactor Project**](../../resources/projects/refactor-project.md) documentation for more details.
+
+## Share Project
You can make a project public so that others can view and clone your project. Before you share your project, make sure to remove any sensitive information.
@@ -274,10 +123,10 @@ You can make a project public so that others can view and clone your project. Be
:::
-## Preview
+## Preview App
You can use this option to run your app in [Preview mode](../../testing-deployment-publishing/running-your-app/run-your-app.md#preview-mode).
-## Testing
+## Test Mode
This menu allows you to run your app in [Test](../../testing-deployment-publishing/running-your-app/run-your-app.md#test-mode) or [Run](../../testing-deployment-publishing/running-your-app/run-your-app.md#run-mode) mode.
diff --git a/docs/intro/roadmap.md b/docs/intro/roadmap.md
index 80218a29..7cea4598 100644
--- a/docs/intro/roadmap.md
+++ b/docs/intro/roadmap.md
@@ -26,7 +26,7 @@ The UI Layer is all about the visual elements and interactions in your app. It i
- [Responsiveness](../ff-concepts/layout/responsive-layout.md)
- Interaction Feedback
- [Animations](../ff-concepts/animations/animations.md)
- - [Haptic Feedback](../ff-concepts/alerts-notification/haptic-feedback.md)
+ - [Haptic Feedback](../ff-concepts/alerts/haptic-feedback.md)
## Logic Layer
The Logic Layer handles your app's business logic and decision-making. This includes state management, conditional actions, and navigation logic.
@@ -51,8 +51,8 @@ The Logic Layer handles your app's business logic and decision-making. This incl
- [Deep & Dynamic Linking](../ff-concepts/navigation-routing/deep-dynamic-linking.md)
- **Notification Systems**:
- - [Triggering Push Notifications](../ff-concepts/alerts-notification/push-notifications.md)
- - [Alert Dialogs](../ff-concepts/alerts-notification/alert-dialog.md)
+ - [Triggering Push Notifications](../ff-concepts/notifications/push-notifications.md)
+ - [Alert Dialogs](../ff-concepts/alerts/alert-dialog.md)
## Data Layer
The Data Layer manages data storage, retrieval, and integration with external sources like APIs and databases.
diff --git a/docs/marketplace/adding-purchasing-item.md b/docs/marketplace/adding-purchasing-item.md
index a6c48be7..26b89239 100644
--- a/docs/marketplace/adding-purchasing-item.md
+++ b/docs/marketplace/adding-purchasing-item.md
@@ -11,49 +11,28 @@ import TabItem from '@theme/TabItem';
# Adding & Purchasing Items
-## Adding a Marketplace Item
+The **FlutterFlow Marketplace** lets you add new features to your app in just a few clicks. It includes ready-made components, templates, and libraries built by other users. These items can help you add things that are not yet available in FlutterFlow or would take more time to build from scratch.
-Add new functionality to your app in seconds! The FlutterFlow Marketplace features user-built components and templates that you can add directly to your FlutterFlow project. These items allow you to add functionality that is not currently available or easy to build in FlutterFlow.
+To add a Marketplace item, go to your FlutterFlow dashboard and click **Marketplace**, or visit [marketplace.flutterflow.io](https://marketplace.flutterflow.io/) directly. Click on any item to view its details.
-### 1. Open FlutterFlow Marketplace
+- For **free items**, click **+ Clone for Free**, then choose the project you want to add it to.
+- For **paid items**, click **Buy Now** and complete the purchase.
-To add a Marketplace Item to your project, head to your FlutterFlow dashboard and select **Marketplace** or head over to [marketplace.flutterflow.io](https://marketplace.flutterflow.io/). In Marketplace, click on any item to learn more about it.
-
-
-
-:::tip
-You can directly search for an item or filter by item type at the top (e.g., Template Apps).
-:::
-
-:::warning[Important]
-You must view item details to see supported platforms (iOS, Android, Web).
-:::
-
-
-### 2. Add an item to your FlutterFlow project
-To add a Marketplace item to your project, go to the item details page.
+Once added, the item will be available in your selected project for immediate use.
-
+
+
+
+
+
+
+
-
-1. Click **+ Add Now**
-2. Navigate to the **Owned Items** tab in your [dashboard](https://marketplace.flutterflow.io/dashboard)
-3. Click **+ Add to Project** next to the item
-4. Select the project you'd like to add the item to, and FlutterFlow will automatically import the item
+## Add Library Item
-:::tip
-You will need to add the item to each individual project that you want to use the item in.
-:::
-
-
-
+To install a library item from the Marketplace, search for the library, open its details page, and click **+ Add for Free**. This adds the library to your FlutterFlow account, meaning you can reuse it in any of your projects.
-1. Click **+ Buy Now**
-2. You will be redirected to Stripe for check out. Fill in payment details and click **Pay**.
-3. Upon successful payment, navigate to the **Owned Items** tab in your [dashboard](https://marketplace.flutterflow.io/dashboard)
-4. You can now start a new project using the template
+To add it to a specific project, go to **Settings > Project Dependencies**, click **Add Library**, and search for your library.
-**Note:** Template App purchases are single-use only and non-refundable. See [Marketplace Terms of Service](https://flutterflow.io/tos-marketplace) and our [Refund Policy](refund-policy.md) for details.
-
-
+
diff --git a/docs/marketplace/creators-hub/creators-hub.md b/docs/marketplace/creators-hub/creators-hub.md
index ae9094da..0a7f08f9 100644
--- a/docs/marketplace/creators-hub/creators-hub.md
+++ b/docs/marketplace/creators-hub/creators-hub.md
@@ -10,11 +10,11 @@ keywords: [FlutterFlow, MarketPlace, Creators Hub]
# Creators Hub
Welcome to the FlutterFlow Marketplace Creators' Hub! This section is designed to provide you with all the necessary information to contribute effectively and responsibly to Marketplace. Whether you are submitting your first item or looking to understand the legal nuances, you'll find detailed guidelines and helpful tips here.
-### **Submitting an Item for Review**
+### Submitting an Item for Review
- Understand the [criteria](submission-criteria.md) we apply to items submitted to Marketplace.
-- Learn how to prepare and [submit](submit-item-for-reivew.md) your items to the Marketplace with our step-by-step guide.
+- Learn how to prepare and [submit](submit-item-for-review.md) your items to the Marketplace with our step-by-step guide.
-### **Legal Guidelines for Creators**
+### Legal Guidelines for Creators
A user-friendly [guide](legal-guidelines-for-creators.md) outlining what content can and cannot be published on our Marketplace.
diff --git a/docs/marketplace/creators-hub/review-dispute-guidelines.md b/docs/marketplace/creators-hub/review-dispute-guidelines.md
new file mode 100644
index 00000000..a24bbdb2
--- /dev/null
+++ b/docs/marketplace/creators-hub/review-dispute-guidelines.md
@@ -0,0 +1,49 @@
+---
+slug: review-dispute-guidelines
+title: Review Dispute Guidelines
+description: Learn about FlutterFlow Marketplace review dispute process and when reviews may be removed or modified.
+tags: [MarketPlace, Review Dispute, Guidelines]
+sidebar_position: 3
+keywords: [FlutterFlow, MarketPlace, Review Dispute, Guidelines, Feedback, Reviews]
+---
+
+# FlutterFlow Marketplace Review Dispute Guidelines
+
+At FlutterFlow Marketplace, we believe in transparent and honest feedback. Reviews are an essential part of helping buyers make informed decisions and helping creators improve their work.
+
+However, not all reviews are created equal. Sometimes feedback is based on misunderstandings, irrelevant factors, or issues unrelated to the quality of the item itself. This guideline outlines when and how we handle review disputes.
+
+### Criteria for Removing a Review
+
+We may remove a review if it meets **one or more** of the following criteria:
+
+- **Spam or Abuse:** The review contains offensive language, harassment, or unrelated spam content.
+- **Misuse of the Review System:** The review is about unrelated topics (e.g., FlutterFlow features, pricing, unrelated bugs).
+- **Critical Misunderstanding:** The review is based on a clear misunderstanding of the item's purpose or scope, despite the listing being accurate and transparent.
+- **Irrelevant to the Current Version:** The review references issues that have since been resolved, and the creator has updated the item significantly.
+
+:::note
+We may remove outdated reviews in cases where leaving them would misrepresent the current product.
+:::
+
+### Reviews That Meet Our Standards
+
+We **will not remove** a review just because it is negative if it:
+
+- Represents a real user experience
+- Critiques the item's quality, usability, documentation, or performance in good faith
+- Highlights friction that future buyers may encounter, even if subjective
+
+### How to Dispute a Review
+
+If you believe a review on your item qualifies for removal:
+
+1. **Contact Us:** Email [marketplace@flutterflow.io](mailto:marketplace@flutterflow.io).
+2. **Include:**
+ - A link to the item and review
+ - A short explanation of why you believe it qualifies for removal
+
+:::info Decision
+Our team will review each case individually and respond within **10 business days**.
+Please note we are actively working on better creator tools to allow creators to reply directly to reviews.
+:::
\ No newline at end of file
diff --git a/docs/marketplace/creators-hub/submission-criteria.md b/docs/marketplace/creators-hub/submission-criteria.md
index 01b23f63..29f22c6b 100644
--- a/docs/marketplace/creators-hub/submission-criteria.md
+++ b/docs/marketplace/creators-hub/submission-criteria.md
@@ -203,10 +203,30 @@ A seamless and positive test experience is crucial for users to evaluate your Fl
#### 4.1 Functional Run Mode Link
-- **Criteria:** The provided Run Mode link must be active and correctly load a working demo of your project.
-- **Why it Matters:** The Run Mode link is the primary way users can interact with your project before purchasing. A broken or inaccessible link creates a significant barrier.
-- **What To Do:**
- - **Double-check your link:** Before submitting, test the link multiple times to confirm it showcases the experience you want potential buyers to have.
+- **Criteria:** The provided Run Mode link must be active and correctly load a working demo of your project. For mobile-only features or utility libraries that cannot be demonstrated in Run Mode's web environment, you must provide alternative demonstration methods.
+- **Why it Matters:** The Run Mode link is the primary way users can interact with your project before purchasing. A broken, inaccessible, or non-demonstrative link creates a significant barrier to understanding the item's value.
+- **What To Do:**
+ - **For Standard Web-Compatible Items:**
+ - Double-check your link before submitting to confirm it showcases the experience you want potential buyers to have.
+ - Test the link multiple times to ensure consistent functionality.
+ - **For Mobile-Only Features:**
+ - Create a dedicated demonstration page in your project that explains the mobile-only functionality.
+ - Include screenshots, videos, or mockups showing how the feature works on mobile devices.
+ - Clearly indicate which features are mobile-only and why they cannot be demonstrated in Run Mode.
+ - Optionally, provide a published FlutterFlow web deploy link that can be used instead of the Run Mode URL.
+ - **For Utility Libraries (e.g., Analytics, Background Services):**
+ - Create a demonstration page that explains the library's functionality.
+ - Show configuration options and expected outcomes.
+ - Include visual aids like flowcharts or diagrams to explain the library's operation.
+ - Provide example code or configuration snippets.
+ - Consider adding debug/test outputs that demonstrate the library is working.
+ - **Documentation:**
+ - Regardless of the type of item, ensure your documentation clearly explains how to implement and test the functionality in a real mobile environment.
+ - Include troubleshooting guides and common implementation scenarios.
+
+:::tip
+For items that cannot be fully demonstrated in Run Mode, focus on creating a clear, informative demonstration page that helps users understand the value and implementation of your item. Visual aids, clear explanations, and comprehensive documentation are key to helping users make informed decisions.
+:::
#### 4.2 User Sign-In (Anonymous Auth)
@@ -251,7 +271,7 @@ Building a solid app template goes beyond surface-level design. It's about creat
#### 5.2 No Pixel Overflow
- **Criteria:** Ensure your UI elements are positioned and sized correctly to avoid content overflowing its container, leading to visual glitches / cut off content.
-- **Why It Matters:** Pixel overflows are a sign of UI inconsistencies that can negatively impact the user experience, especially on different screen sizes. Pixel overflow issues can occur in Test Mode when there’s a hardcoded pixel value and not enough space on the screen to render that exact value.
+- **Why It Matters:** Pixel overflows are a sign of UI inconsistencies that can negatively impact the user experience, especially on different screen sizes. Pixel overflow issues can occur in Test Mode when there's a hardcoded pixel value and not enough space on the screen to render that exact value.
- **What To Do:**
- **Preview pixel overflows:** Toggle the pixel overflow icon in the top-right of the canvas to see if there are any overflow issues.
- **Leverage FlutterFlow's layout tools:** Use Expanded and Flex values to help prevent layout issues. Make `Columns` or `Rows` scrollable to prevent overflows. Use auto-sizing text or text clipping where it makes sense. Remove hard-coded width and height where it makes sense.
@@ -314,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
@@ -376,7 +396,7 @@ Stay tuned for an upcoming "style guide" we're publishing that goes into deeper
- **Criteria:** Projects should include automated tests that verify core functionality and key user workflows. While not required for approval, this is strongly recommended for libraries and will positively impact visibility.
- **Why It Matters:** Automated tests help ensure reliability, catch regressions, and demonstrate your commitment to quality. They also improve your item's visibility.
- **What To Do:**
- - **Add Integration Tests:** Use FlutterFlow's [automated testing](../../testing-deployment-publishing/testing/automated-tests.md) features to verify your item's core functionality.
+ - **Add Integration Tests:** Use FlutterFlow's [automated testing](../../testing-deployment-publishing/running-your-app/automated-tests.md) features to verify your item's core functionality.
- **Test Key Workflows:** Focus on testing critical user paths and features that users will rely on.
- **For Libraries:** Since libraries are often used as building blocks in larger applications, thorough testing is particularly important to:
- Verify that Library Values are properly implemented
diff --git a/docs/marketplace/creators-hub/submit-item-for-reivew.md b/docs/marketplace/creators-hub/submit-item-for-review.md
similarity index 87%
rename from docs/marketplace/creators-hub/submit-item-for-reivew.md
rename to docs/marketplace/creators-hub/submit-item-for-review.md
index bfc9cb49..ba30b402 100644
--- a/docs/marketplace/creators-hub/submit-item-for-reivew.md
+++ b/docs/marketplace/creators-hub/submit-item-for-review.md
@@ -1,5 +1,5 @@
---
-slug: submit-item-for-reivew
+slug: submit-item-for-review
title: Submitting Item for Review
description: Learn how to submit an item to the FlutterFlow Marketplace.
tags: [MarketPlace, Creators Hub]
@@ -20,7 +20,7 @@ Please review our [**Submission Guidelines**](submission-criteria.md) and our [*
## How to Submit an Item
-An item can be an enitre project (in the case of Temlate Apps or Libraries), a page or a component (in the case of Template Page & Components) or a Custom Function, Action or Widget (in the case of Custom Code).
+An item can be an entire project (in the case of Temlate Apps or Libraries), a page or a component (in the case of Template Page & Components) or a Custom Function, Action or Widget (in the case of Custom Code).
### 1. Set your project as a Marketplace project
@@ -74,11 +74,13 @@ If you aren't ready to submit your item, select **Save As Draft** to continue ed
#### Cover Photo
-The cover photo should be 1200x800 pixels and help the users understand the purpose of the item. Please do not include the FlutterFlow logo in your cover image.
+The cover photo should be **1200x800 pixels** and help the users understand the purpose of the item. GIFs are allowed but should not be distracting, focus solely on the use and/or usability of the template, and be highly optimized to ensure a smooth load on the platform. Please do not include the FlutterFlow logo in your cover image.
#### Gallery Photos (optional)
-Include up to 4 additional photos that showcase your item's features. Each should be should be 1200x800 pixels.
+Include up to 4 additional photos that showcase your item's features. GIFs are allowed but should not be distracting, focus solely on the use and/or usability of the template, and be highly optimized to ensure a smooth load on the platform.
+
+Each should be should be **1200x800 pixels**.
#### Name
@@ -86,11 +88,13 @@ The item name should be professional, unique, and help the users understand the
#### Description
-The description should provide an overview of the key features, helping users determine if the item aligns with their requirements. If the item includes any third-party paid services, those should also be mentioned in the description. Please use correct grammar and capitalization.
+The description should provide an overview of the key features, helping users determine if the item aligns with their requirements.
+
+If the item includes any third-party paid services or pub.dev packages/dependencies, those should also be mentioned in the description. Please use correct grammar and capitalization.
#### Usage Instructions
-Provide clear and concise instructions on how to implement and utilize your item within FlutterFlow. Include any necessary steps, code snippets, or configurations required to get started. If your item depends on any third party services, please show users where to find relevant API keys or more information. Please use correct grammar and capitalization.
+Provide clear and concise instructions on how to implement and utilize your item within FlutterFlow. Include any necessary steps, code snippets, or configurations required to get started. If your item depends on any third party services or pub.dev packages/dependencies, please provide full details of these including showing users where to find relevant API keys or more information. Please use correct grammar and capitalization.
#### Marketplace Item Type
diff --git a/docs/marketplace/imgs/branch-library-install.png b/docs/marketplace/imgs/branch-library-install.png
new file mode 100644
index 00000000..7575e84d
Binary files /dev/null and b/docs/marketplace/imgs/branch-library-install.png differ
diff --git a/docs/marketplace/imgs/free-item.avif b/docs/marketplace/imgs/free-item.avif
new file mode 100644
index 00000000..1dd3d36f
Binary files /dev/null and b/docs/marketplace/imgs/free-item.avif differ
diff --git a/docs/marketplace/imgs/paid-item.avif b/docs/marketplace/imgs/paid-item.avif
new file mode 100644
index 00000000..dcc09f5d
Binary files /dev/null and b/docs/marketplace/imgs/paid-item.avif differ
diff --git a/docs/marketplace/index.md b/docs/marketplace/index.md
index 3a27679d..6168e2db 100644
--- a/docs/marketplace/index.md
+++ b/docs/marketplace/index.md
@@ -4,7 +4,7 @@ title: FlutterFlow Marketplace
description: Discover how to explore, purchase, and contribute to the FlutterFlow Marketplace, including guidelines for submissions and handling copyrights.
tags: [Marketplace , Creator Hub]
sidebar_position: 0
-keywords: [FlutterFlow, Marketplace, Add and Purchase Items, Refund Policy, Submit Feedback, Creator Hub, Submission Criteria, Legal Guidelines, Copyright, DMCA Process, External Licensing, Creators FAQs]
+keywords: [FlutterFlow, Marketplace, Add and Purchase Items, Refund Policy, Submit Feedback, Review Dispute Guidelines, Creator Hub, Submission Criteria, Legal Guidelines, Copyright, DMCA Process, External Licensing, Creators FAQs]
---
# FlutterFlow Marketplace
@@ -14,12 +14,20 @@ FlutterFlow's Marketplace is a dynamic platform designed to enhance your app dev
In the FlutterFlow Marketplace, you can [add and purchase](adding-purchasing-item.md) items to quickly integrate into your projects, significantly reducing development time. The Marketplace is curated to ensure high-quality resources, with contributions from a diverse community of developers and designers.
## Becoming a Contributor
-If you're interested in contributing to the Marketplace, the [creator hub](creators-hub/creators-hub.md) is your starting point. Here, you can learn about [submitting items for review](creators-hub/submit-item-for-reivew.md), [submission criteria](creators-hub/submission-criteria.md), and [legal guidelines](creators-hub/legal-guidelines-for-creators.md) for creators. Ensuring your submissions adhere to these guidelines helps maintain the quality and integrity of the Marketplace.
+If you're interested in contributing to the Marketplace, the [creator hub](creators-hub/creators-hub.md) is your starting point. Here, you can learn about [submitting items for review](creators-hub/submit-item-for-review.md), [submission criteria](creators-hub/submission-criteria.md), and [legal guidelines](creators-hub/legal-guidelines-for-creators.md) for creators. Ensuring your submissions adhere to these guidelines helps maintain the quality and integrity of the Marketplace.
## Protecting Your Work
Understanding and navigating [copyright (DMCA process)](creators-hub/copyright-dmca-process.md) is crucial for both creators and users. The Marketplace provides clear instructions on how to handle copyright issues, ensuring that intellectual property rights are respected.
For those dealing with third-party resources, [navigating external licensing](creators-hub/navigating-external-licenses.md) is essential. The Marketplace offers guidelines to help you understand and comply with various licensing agreements.
+## Marketplace Policies and Guidelines
+
+Understanding our marketplace policies helps ensure a positive experience for all users:
+
+- [Refund Policy](refund-policy.md) - Learn about our refund policy and exceptional circumstances
+- [Review Dispute Guidelines](creators-hub/review-dispute-guidelines.md) - Understanding when and how reviews may be disputed
+- [Submit Feedback](submit-feedback.md) - Learn how to rate items and provide feedback
+
## FAQs
Our [Creators FAQs](creators-hub/creators-hub.md) section provides answers to common questions, supporting you throughout your journey in the Marketplace.
\ No newline at end of file
diff --git a/docs/marketplace/submit-feedback.md b/docs/marketplace/submit-feedback.md
index 46549dbd..b8ab4b8d 100644
--- a/docs/marketplace/submit-feedback.md
+++ b/docs/marketplace/submit-feedback.md
@@ -4,7 +4,7 @@ title: Submit Feedback
description: Learn more about the submitting feedback on FlutterFlow marketplace items.
tags: [MarketPlace, Submit Feedback]
sidebar_position: 2
-keywords: [FlutterFlow, MarketPlace, Submit Feedback]
+keywords: [FlutterFlow, MarketPlace, Submit Feedback, Review Dispute Guidelines]
---
# Submitting Feedback for Items
@@ -57,3 +57,7 @@ If you encounter any issues with an item that may require our attention, such as
:::tip
If you are the original author or copyright holder of content that has been uploaded to the FlutterFlow Marketplace without your permission, you can file DMCA takedown request following the instructions in [**FlutterFlow's Terms of Service**](https://flutterflow.io/tos).
:::
+
+## Review Disputes
+
+If you're a creator and believe a review on your item was submitted inappropriately, you can learn about our review dispute process in our [Review Dispute Guidelines](creators-hub/review-dispute-guidelines.md). This covers when reviews may be removed and how to submit a dispute.
diff --git a/docs/misc/customer-support-policy.md b/docs/misc/customer-support-policy.md
index 6036ea60..13007cf4 100644
--- a/docs/misc/customer-support-policy.md
+++ b/docs/misc/customer-support-policy.md
@@ -12,8 +12,17 @@ Our support team is available from 5 AM to 5 PM Eastern Time, Monday through Fri
### How To Reach Us
-* **Pro** and **Teams** users can reach us using the in-app chat inside FlutterFlow
-* We can also be reached at support@flutterflow.io
+Depending on your plan, there are multiple ways you can get support when using FlutterFlow:
+
+- **Account and Billing Support**: Available for all plans. You can always reach out for help with managing your account or billing-related questions.
+
+- **Community Support**: All users have access to the FlutterFlow Community Forums, where you can ask questions, share knowledge, and connect with other builders.
+
+- **Email Support**: Available starting from the **Basic** plan and above. Get direct help from our support team via email.
+
+- **In-App Support**: Available starting from the **Growth** plan and above. Chat directly with support specialists from within FlutterFlow for faster assistance.
+
+- **Dedicated Live Support**: Exclusive to the **Enterprise** plan. Gain direct access to dedicated support specialists for priority, hands-on help.
### What We Can Help With
@@ -46,7 +55,7 @@ Lastly, you can connect with a [FlutterFlow Expert](https://experts.flutterflow.
We regularly release feature updates and bug releases. To make sure you are on the most recent version of FlutterFlow select Ctrl/Cmd + R.
-If you think you've found a bug, please submit an [in-app bug report](../intro/ff-ui/toolbar.md#help) or let us know via chat (Standard and Pro users only). Please make sure to include:
+If you think you've found a bug, please submit an [in-app bug report](../intro/ff-ui/toolbar.md#help-menu) or let us know via chat (Growth, Business and Enterprise users only). Please make sure to include:
* A link to your project
* The page(s) effected
diff --git a/docs/misc/enterprise-support-policy.md b/docs/misc/enterprise-page.md
similarity index 64%
rename from docs/misc/enterprise-support-policy.md
rename to docs/misc/enterprise-page.md
index 211337ba..600ebe9d 100644
--- a/docs/misc/enterprise-support-policy.md
+++ b/docs/misc/enterprise-page.md
@@ -1,5 +1,23 @@
+---
+slug: /misc/enterprise
+title: Enterprise
+description: Learn how to use FlutterFlow for Enterprise.
+tags: [Enterprise]
+sidebar_position: 1
+keywords: [Enterprise Support Policy, Whitelist URLs]
+---
-# Enterprise Support Policy
+# Enterprise
+
+## Whitelist URLs
+
+Enterprise environments often restrict internet access to enhance security and compliance. For example, they may allow access only to approved URLs that are essential for work-related tasks. FlutterFlow won't properly work in such restrictions because it accesses multiple services—Firestore, Cloud Functions, and various APIs—these URLs must be allowed in your corporate firewall for everything to function correctly.
+
+To find out which URLs need to be whitelisted, navigate to the URL Access page from the FlutterFlow [dashboard](../intro/ff-ui/dashboard.md). Any URLs marked as **Inaccessible** are currently blocked by your network, which may prevent certain features from functioning properly. You can copy these URLs individually or use the Copy All Inaccessible URLs button in the top-right corner to collect them all at once. Then, share the list with your IT team for whitelisting.
+
+
+
+## Enterprise Support Policy
We understand our Enterprise customers often rely on FlutterFlow for mission critical applications. To that end, we have created a dedicated Enterprise support team to provide the highest level of service and support. This document outlines our support channels and scope for Enterprise customers.
diff --git a/docs/misc/flutterflow-experts.md b/docs/misc/flutterflow-experts.md
deleted file mode 100644
index 66a724d7..00000000
--- a/docs/misc/flutterflow-experts.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# FlutterFlow Experts
-
-The FlutterFlow Experts is a platform that [connects](#connect-with-an-expert) users with independent professionals and agencies who have expertise in FlutterFlow. It also allows users to apply to [become experts](#become-an-expert) themselves.
-
-To get started, go to `` and create an account.
-
-:::warning[Please Note]
-Please note that
-- Experts are independent professionals and not employees, agents, or affiliates of FlutterFlow, and
-- any services provided to you are solely the responsibility of the Expert and not FlutterFlow.
-:::
-
-### Connect with an expert
-
-Before reaching out to an expert, it's important to create a detailed and clear proposal about your project. Make sure to clearly convey your needs, objectives, and any specific requirements. This information is crucial for the expert to provide you with an accurate timeline and quote.
-
-To connect with an expert:
-
-1. From the [Dashboard](https://experts.flutterflow.io/dashboard) or [My Proposal](https://experts.flutterflow.io/proposals) page, click on the **+ Create Proposal** button.
-
-
-
-2. Click **Continue,** and you will be asked to enter details about your project, including key features, preferred tools or platforms, project size, and budget.
-
-3. Once completed, you can review the proposal details and **Go to Expert Selection**.
-
-
-
-
-
-
-
-4. To invite experts to view your proposal, click on the **Send Invite** button, write a personalized message, and send the invite. You can send up to three invites at a time.
-
-
-
-
-
-5. Alternatively, you can browse through expert profiles on the [experts page](https://experts.flutterflow.io/experts), see their details, and click the **Hire** button to send them a personalized project proposal.
-
-
-
-
-:::warning[]
-Please do not send the proposal to many experts at the same time.
-:::
-
-### Become an expert
-
-As a FlutterFlow expert, you'll have the opportunity to assist users in implementing complex features, troubleshooting issues, and even designing and building entire apps. To apply, navigate to our [Dashboard](https://experts.flutterflow.io/dashboard) and click the **Apply Now** button.
-
-
-
-### FAQs
-
-#### **Do experts work for FlutterFlow?**
-
-No, experts are independent professionals, such as designers, developers, and consultants, with extensive knowledge and expertise in FlutterFlow.
-
-#### **Am I obligated to work with an expert after contacting them?**
-
-No, there is no obligation to engage with an expert simply by filling out the contact form.
-
-#### **How are contracts and payments managed?**
-
-Contracts and payments are directly negotiated between you and the expert. The scope of work, costs, and timelines will be mutually agreed upon, and payments will be processed through the expert's preferred billing system.
-
diff --git a/docs/misc/hire-flutterflow-developer.md b/docs/misc/hire-flutterflow-developer.md
new file mode 100644
index 00000000..bbec3ae1
--- /dev/null
+++ b/docs/misc/hire-flutterflow-developer.md
@@ -0,0 +1,101 @@
+---
+slug: /misc/hire-flutterflow-developer
+title: Hire FlutterFlow Developer
+description: Learn how to hire a FlutterFlow Developer.
+sidebar_position: 1
+keywords: [Hire FlutterFlow Developer, FlutterFlow Expert]
+---
+
+# Hire FlutterFlow Developer
+
+You can hire a skilled FlutterFlow Developer to build your app at: https://www.flutterflow.io/hire-developer.
+
+**FlutterFlow Developers** include agencies and freelancers skilled in building apps using FlutterFlow. Many of them have the **FlutterFlow Expert** badge, awarded to those who demonstrate advanced technical proficiency. To earn this recognition, they must pass the FlutterFlow Expert training and submit a portfolio of their work for our evaluation.
+
+:::warning[Please Note]
+
+- FlutterFlow Developers are independent professionals, not employees, agents, or affiliates of FlutterFlow.
+- Any services provided are solely the responsibility of the Developer, not FlutterFlow.
+- We recommend signing a contract with the Developer before making any payments to ensure clarity on deliverables and timelines.
+
+:::
+
+Visit https://www.flutterflow.io/hire-developer to get started.
+
+
+
+There are two ways to find a Developer:
+
+- **Get matched**: Receive recommendations based on your project requirements and preferences (*recommended*).
+- **Browse Developers**: Explore available Developers, view their details, and reach out to specific ones.
+
+In both cases, you’d need to make an account with FlutterFlow, and fill out a project proposal about your project. Make sure to clearly convey your needs, objectives, and any specific requirements. This information is crucial for the Developer to provide you with an accurate timeline and quote.
+
+## Get Matched With Developers
+
+To get matched with developers based on your project requirements, follow the steps below:
+
+1. Create or log into your FlutterFlow account.
+
+ 
+
+2. Fill out your project details, including features, budget, geo, and language preferences.
+
+ 
+
+3. Review your project proposal for accuracy and completeness.
+
+ 
+
+4. Confirm your project details to get matched with Developers based on your requirements.
+
+ 
+
+
+:::info[Please Note]
+
+You can send your request upto 5 Developers at a time.
+
+:::
+
+Alternatively, you can browse Developers, view their profiles, and use the **Hire** button to send a personalized project proposal.
+
+
+
+## FAQs
+
+
+
+Do FlutterFlow Developers work for FlutterFlow?
+
+
+No, FlutterFlow Developers are independent professionals, including designers, developers, and consultants with expertise in FlutterFlow.
+
+
+
+
+
+How are Developers selected for my project?
+
+
+Developers are matched based on your requirements, such as geo, language, budget, and project scope. Priority is given to Developers with the FlutterFlow Expert badge.
+
+
+
+
+
+Am I obligated to work with a Developer after contacting them?
+
+
+No, contacting a Developer does not obligate you to engage their services.
+
+
+
+
+
+How are contracts and payments managed?
+
+
+Contracts and payments are directly negotiated between you and the Developer. FlutterFlow does not handle contracts or payments. All terms, including scope, costs, and timelines, are agreed upon by both parties. Payments are processed through the Developer’s preferred billing system.
+
+
\ No newline at end of file
diff --git a/docs/misc/imgs/browse-devs.png b/docs/misc/imgs/browse-devs.png
new file mode 100644
index 00000000..abd568bd
Binary files /dev/null and b/docs/misc/imgs/browse-devs.png differ
diff --git a/docs/misc/imgs/confirm-developers.png b/docs/misc/imgs/confirm-developers.png
new file mode 100644
index 00000000..c4a9d793
Binary files /dev/null and b/docs/misc/imgs/confirm-developers.png differ
diff --git a/docs/misc/imgs/hire-dev-page.png b/docs/misc/imgs/hire-dev-page.png
new file mode 100644
index 00000000..fb9f72bf
Binary files /dev/null and b/docs/misc/imgs/hire-dev-page.png differ
diff --git a/docs/misc/imgs/login-ff-2.png b/docs/misc/imgs/login-ff-2.png
new file mode 100644
index 00000000..7069081a
Binary files /dev/null and b/docs/misc/imgs/login-ff-2.png differ
diff --git a/docs/misc/imgs/login-ff-expert.png b/docs/misc/imgs/login-ff-expert.png
new file mode 100644
index 00000000..6d003bee
Binary files /dev/null and b/docs/misc/imgs/login-ff-expert.png differ
diff --git a/docs/misc/imgs/project-details.png b/docs/misc/imgs/project-details.png
new file mode 100644
index 00000000..eb256c48
Binary files /dev/null and b/docs/misc/imgs/project-details.png differ
diff --git a/docs/misc/imgs/review-project-proposal.png b/docs/misc/imgs/review-project-proposal.png
new file mode 100644
index 00000000..815e96c1
Binary files /dev/null and b/docs/misc/imgs/review-project-proposal.png differ
diff --git a/docs/misc/imgs/url-access.avif b/docs/misc/imgs/url-access.avif
new file mode 100644
index 00000000..00fceaf1
Binary files /dev/null and b/docs/misc/imgs/url-access.avif differ
diff --git a/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md b/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md
index 485f5e4e..b88148f4 100644
--- a/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md
+++ b/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md
@@ -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:
diff --git a/docs/resources/control-flow/backend-logic/api/imgs/private-cloud-func.png b/docs/resources/control-flow/backend-logic/api/imgs/private-cloud-func.png
new file mode 100644
index 00000000..cc8984f9
Binary files /dev/null and b/docs/resources/control-flow/backend-logic/api/imgs/private-cloud-func.png differ
diff --git a/docs/resources/control-flow/backend-logic/api/rest-api.md b/docs/resources/control-flow/backend-logic/api/rest-api.md
index 8a8fc3e8..337b00a2 100644
--- a/docs/resources/control-flow/backend-logic/api/rest-api.md
+++ b/docs/resources/control-flow/backend-logic/api/rest-api.md
@@ -38,7 +38,7 @@ Some of the common request headers that you might need while sending a request a
To pass the request header:
1. Select the **Headers** tab and click on the **+ Add Header** button.
-2. Inside the input box, enter the header name followed by the colon(:) and its value (e.g., **Content-Length: application/json**).
+2. Inside the input box, enter the header name followed by the colon(:) and its value (e.g., **Content-Type: application/json**).
**Response & Test tab > Response Type >** enablethe **Parse as
+2. Open your API call definition > **Response & Test tab > Response Type >** enable the **Parse as
Data Type**. Select the **Data Type** that you want to convert into. For this example, it's 'AllProducts'.

@@ -568,56 +568,88 @@ with a numeric character. However, in cases where you have keys with numeric pre
Learn more about **[JSONPath](https://www.rfc-editor.org/rfc/rfc9535.html)** and how to define a proper expression.
:::
-### Adding JSON Path
+### Add JSON Predefined Path
+You can effortlessly define and manage **JSON Paths** for your API calls in FlutterFlow to parse and extract the data you need. Once added you can [use](#using-json-path) them as **Predefined Path** while accessing the **JSON Body**.
-To add JSON path:
+First, [create and test](../api/create-test-api-calls.md) your API call. Inside the **JSON Paths** section, click **+ Add JSON Path**, enter your **JSON Path**, and assign it a name. If the expression is valid, a preview of the response appears under **Response Preview**. Click the **Preview** icon to see the full response. If the response contains a list of items, the **Is List** option will be enabled automatically.
-1. First, [create and test](../api/create-test-api-calls.md) your API call.
-
-2. Inside the **JSON Paths** section, click on the **+ Add JSON Path**.
-3. Enter your **JSON Path** and give it a **Name**.
-4. If you entered the valid expression, you'll see the starting part of the response under the **Response Preview** column. To see the complete response, click on the **Preview** icon.
-5. If the returned response is a list of items, by default, **Is List** will be checked; however, if you want to convert the response into the list explicitly, checkmark it.
-6. We also recommend all the possible JSON paths (under the **Recommended** tab) that might include what you are looking for.
-
- 1. To add the recommended JSON path, checkmark the **Selected**, open the **Selected** tab,
- and give it a name.
-
-
+Under the **Recommended** section, you'll find suggested JSON paths that might contain the data you need.
+
+
+
+
+
### Using JSON Path
-While accessing values from an API Call, you can either enter the custom JSON path or use the already created JSON path.
-
-To use the already added JSON path:
+While accessing values from an API Call, you can either enter the custom JSON path or use the [predefined JSON path](#add-json-predefined-path).
-1. Select your API response.
-2. Set the **API response Options** to **JSON Body**.
-3. Set the **Available Options** to **JSON Path**.
-4. Set the **JSON Path Name** to the one that you created earlier.
+To use a predefined JSON Path, first, select your API response. Then, set the **API Response Options** to **JSON Body** and the **Available Options** to **JSON Path** or **Predefined Path**. Finally, specify the JSON Path Name or select from the predefined JSON Path to map the extracted data for use in your app.
-
+
+
+
+
+
## Advanced Settings
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**.
+
+
+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:
- **Use Custom Name for Cloud Function**: When enabled, allows you to specify a custom name for the deployed Cloud Function. By default, this option is disabled and Cloud Function is named as `ffPrivateApiCall`.
@@ -627,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).
-:::
+
:::
+
+
+## FAQs
+
+
+Why is my Predefined Path not showing any options?
+
+
+This often happens if you added the Predefined Path but forgot to save the API call in FlutterFlow. Ensure you click Save after making any changes to your API call so FlutterFlow can properly recognize and display your predefined paths.
+
+
+
+
+
+Why am I getting a “Current variable is not valid” error?
+
+
+This error typically indicates that the widget isn’t receiving the data type it expects. For example, passing a list of colors directly to a text widget will trigger the error. In such cases, convert or supply the data as a string (or another compatible type) so the widget can properly display it.
+
+
diff --git a/docs/resources/control-flow/backend-logic/api/soap-api.md b/docs/resources/control-flow/backend-logic/api/soap-api.md
index 24a15e58..a0794493 100644
--- a/docs/resources/control-flow/backend-logic/api/soap-api.md
+++ b/docs/resources/control-flow/backend-logic/api/soap-api.md
@@ -309,7 +309,7 @@ You can now proceed to display the country list in *HomePage*. Here are the step
4. On ListView, [generate dynamic children](../../../ui/widgets/composing-widgets/generate-dynamic-children.md) using the page state variable.
-5. The page state variable stores the country name and code as a single string (e.g., Australia - AT). To display the name and code separately in a *ListTile*, we can use a [code expression](../../../control-flow/functions/utility-functions.md#code-expressions). To display the country name, we can use `var1.split("-")[1].trim()`, where `var1` is the current item in the list. To display the country code, we can use the same expression and replace `[1]` with `[0]`.
+5. The page state variable stores the country name and code as a single string (e.g., Australia - AT). To display the name and code separately in a *ListTile*, we can use a [inline function](../../../control-flow/functions/utility-functions.md#inline-function-code-expressions). To display the country name, we can use `var1.split("-")[1].trim()`, where `var1` is the current item in the list. To display the country code, we can use the same expression and replace `[1]` with `[0]`.
[Your TextField]**); and specify the optional **Max Results** to determine the number of search results.
+ width: '100%'}}>
-
-## Define Algolia Search Backend Query
-
-Once the UI of the page is ready, you can move on to the next step, that is, defining an Algolia Search Backend Query.
-
-Follow the steps below to define the Backend Query:
-
-1. Select the **widget** (or page) on which to apply the query. In this case, it's recommended to
-apply the query on the `ListView` widget.
-2. Select **Backend Query** from the [Properties Panel](../../../../intro/ff-ui/builder.md#properties-panel) (the right menu).
-3. Select the **Query Type** as ***Algolia Search***.
-4. Choose the **Firebase Collection** on which to perform the search.
-5. Define from where to get the **Search Term**. You can either choose ***Specific Value*** or ***From Variable***. If you want to use a `TextField` value as the search term, you should choose *From Variable*.
-6. If you have chosen **Specific Value**,define the term inside the field present.
-7. If you have chosen ***From Variable***, select a **Source** from the dropdown menu and then select an option from the **Available Options**. For example, if you want to use the value of a `TextField`, select the Source as ***Widget State*** and choose the field name under Available Options.
-8. Set the number of maximum search results to fetch under **Max Results**. Keep this field blank if you want to fetch all the matching search results.
-
-
-
-
-
-
-## Display Search Results
-
-Follow the step below to display the search results inside the `ListView`:
-
-1. Select a **widget** present inside the `ListView`, for example, a `Text` widget.
-2. Click **Set from Variable** from the [Properties Panel](../../../../intro/ff-ui/builder.md#properties-panel) (right menu).
-3. From the **Source** dropdown menu, choose the response of the Algolia Search that you had defined on the ListView widget.
-4. Under **Available Options** select the name of the field whose value you want to use.
-5. (Optional) You can specify a **Default Value** that would be shown if the field value is empty.
-6. Click **Save**.
-7. Repeat **Steps 1 to 6** for using the search response data on any other widget.
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/resources/control-flow/backend-logic/backend-query/api-call-query.md b/docs/resources/control-flow/backend-logic/backend-query/api-call-query.md
index 7e216926..be14b61b 100644
--- a/docs/resources/control-flow/backend-logic/backend-query/api-call-query.md
+++ b/docs/resources/control-flow/backend-logic/backend-query/api-call-query.md
@@ -81,7 +81,7 @@ Once you have the API Call query defined, you can use the data retrieved from th
4. Set the **API response Options** to **JSON Body**.
5. Set the **Available Options** to **JSON Path**.
6. Set the **JSON Path Name** to either the custom JSON path or use the already created JSON
- path. See how to [**create a JSON path**](../../backend-logic/api/rest-api.md#adding-json-path).
+ path. See how to [**create a JSON path**](../../backend-logic/api/rest-api.md#add-json-predefined-path).
7. Click **Confirm**.
-Now you can write the code expression in the **Expression** field and click on **Check Errors** to
-see if the expression is valid. If it is valid, you will see the generated code for the same.
+Now you can write the inline function in the **Expression** field and click on **Check Errors** to see if the expression is valid. If it is valid, you will see the generated code for the same.
-The arguments in a Code Expression can take the following properties:
+The arguments in a Inline Function can take the following properties:
| DataType | Supports Nullable | Supports List |
|----------|-------------------|---------------|
@@ -171,13 +166,99 @@ Here are some common expressions you can use for your business logic:
| `int.parse(s)` | Convert the **String** into an **integer.** | `int.parse(stringValue)` | `int` |
+## Custom Code Expression
+
+**Custom Code Expression** lets you write short Dart code directly in widget property fields and action flows in FlutterFlow. It’s a more powerful version of [**Inline Function**](#inline-function-code-expressions), allowing you to directly access FlutterFlow generated classes, global variables, widget properties, parameters, and more without needing to manually pass them as inputs.
+
+Custom Code Expressions also support real-time autocomplete, making it easy to discover available fields as you type. For example, when you type `FFAppState().`, it will suggest all available app state variables along with their types.
+
+In addition, inline validation provides immediate feedback as you write, helping you catch syntax errors or invalid property references.
+
+:::info
+To use Custom Code Expression, you must have an active [**FlutterFlow paid plan**](https://www.flutterflow.io/pricing).
+:::
+
+:::tip
+- To explore what you can access within a Custom code expression, refer to the [**Common Examples**](../../../ff-concepts/adding-customization/common-examples.md) page.
+- Press `^ + Space` (or `Ctrl + Space`) while typing to see suggestions for what you can access in your Custom code expression.
+- You can access values inside custom structs. For example, you can use `FFAppState().localDeviceInfo.osVersion` if that field exists in your app state.
+- To use Custom code expressions better, it's helpful to understand how FlutterFlow builds your project behind the scenes. You can check the [**State Management**](../../../generated-code/state-mgmt-gen-code.md) page and other **Generated Code** sections to learn how everything is set up.
+
+:::
+Here are a couple of examples showing how to access App State and Page State within a Custom code expression:
+- **App State Access:** For example, to check if dark mode is enabled using an App State variable:
+
+ ```jsx
+ FFAppState().enableDarkMode ? 'Dark Mode On' : 'Light Mode Off'
+ ```
+
+ This accesses the global `enableDarkMode` boolean stored in `FFAppState`, and returns a string based on its value.
+
+- **Page and Component State Access:** For example, to access a page or component state variable like `searchText`, you start with `_model.` and then select the variable from the autocomplete suggestions.
+
+ ```jsx
+ _model.searchText.isEmpty ? '' : 'Searching for "${_model.searchText}"'
+ ```
+
+ This expression checks if the `searchText` variable (defined as a page state) is empty, and returns an appropriate message. The `_model` object refers to the current page’s generated state model.
+
+Here's an example of adding a Custom Code Expression:
+
+
+
+
+
+
+
+### Execute Custom Code [Action]
+
+To use a Custom Code Expression when triggering actions in FlutterFlow (i.e., inside an Action Flow), you can use the **Execute Custom Code** action. This allows you to run a Dart expression when something happens, such as tapping a button or after a page loads.
+
+
+
+The Execute Custom Code action can be really helpful in scenarios where the home page is removed early from the navigation stack and standard navigation using the local context may fail. To prevent this, you can [use the global navigator context](../../../ff-concepts/navigation-routing/deep-dynamic-linking.md#using-global-context-to-navigate) inside a code expression.
## Custom Functions
-You can also use custom functions to handle slightly more complex calculations or to process a wider range of data types that are not supported in Code Expression.
+You can also use custom functions to handle slightly more complex calculations or to process a wider range of data types that are not supported in Inline Function.
:::info
Learn more about [**Custom Functions**](../../../ff-concepts/adding-customization/custom-functions.md).
-:::
\ No newline at end of file
+:::
+
+## FAQS
+
+
+How is a Custom Code Expression different from an Inline Function?
+
+
+Custom Code Expression is a more advanced and flexible version of Inline Function.
+
+With Inline Functions, you had to manually pass values as arguments. In contrast, Custom Code Expressions let you directly reference FlutterFlow generated resources (such as `FFAppState()`, `_model`, context, and more) without needing to pass them in.
+
+You can write any valid Dart expression in a Custom code expression, even multi-line logic using anonymous functions. Plus, Custom Code Expressions support real-time autocomplete and inline error validation, making it much easier to discover available variables and avoid mistakes.
+
+
+
\ No newline at end of file
diff --git a/docs/resources/control-flow/overview.md b/docs/resources/control-flow/overview.md
index 47ca0721..83f160f9 100644
--- a/docs/resources/control-flow/overview.md
+++ b/docs/resources/control-flow/overview.md
@@ -65,7 +65,7 @@ There are different types of functions you can use in your app. Some examples in
tasks, such as
formatting
data or performing calculations. In FlutterFlow, you can use
-[**Code Expression**](functions/utility-functions.md#code-expressions) for simple data
+[**Inline Function**](functions/utility-functions.md#inline-function-code-expressions) for simple data
manipulation tasks or use the
**[Combine Text](functions/utility-functions.md#combine-text)** built-in
function to concatenate strings.
diff --git a/docs/resources/control-flow/time-based-logic/wait-action.md b/docs/resources/control-flow/time-based-logic/wait-action.md
index 335c2ad5..f22ffac0 100644
--- a/docs/resources/control-flow/time-based-logic/wait-action.md
+++ b/docs/resources/control-flow/time-based-logic/wait-action.md
@@ -9,22 +9,13 @@ keywords: [Wait Action, Time-Based Logic, FlutterFlow]
# Wait [Action]
-**"Waiting"** on an action or function is a fundamental concept in time-based logic, allowing developers to introduce intentional pauses within a sequence of actions. This is also known as delaying execution of logic, where the execution of a sequence of actions is paused for a specified period. This action is particularly useful when there is a need to synchronize events, manage the timing of operations, or ensure that certain conditions are met before proceeding further in a workflow.
+The **Wait** action is used to pause the execution of a workflow for a specific amount of time. This is helpful when you want to delay the next step in a sequence, for example, to synchronize events, allow animations to complete, or ensure a condition is met before continuing. It’s a key concept in managing time-based logic within action flows.
-## Delayed Execution of Logic
-Delaying execution of logic involves pausing the execution of a sequence of actions for a specified period. This is useful when you need to introduce a time delay before proceeding to the next step in a workflow or process.
-
-## Use-cases
-
-- When you need to wait for a certain condition to be met (e.g., waiting for data to load or a
-user to complete an action).
-- To create pauses between actions for better user experience (e.g., displaying messages
- sequentially).
-- Waiting before performing an animation.
-
-## How to?
-
-To implement a Wait Action in your Action Flows, follow this simple tutorial:
+:::tip[Possible use cases]
+- **Show Splash Screen:** Delay the transition to the next page to allow the splash screen to be visible for a few seconds.
+- **Step-by-Step Tutorials:** Introduce timed delays between steps to guide users through a tutorial or onboarding flow.
+- **Chain Animations:** Add pauses between multiple animations for a more fluid and organized visual effect.
+:::
-
-
-
-
-
-## Adding Reset Form Field action
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button, etc.) on which you want to add the action.
-2. Select **Actions** from the properties panel, If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile (inside *Action Flow Editor*) and select **Add Action**.
-3. Search the **Reset Form Field** (under *State Management*) action and select the widget you would like to reset.
-
-You can reset the same types of widgets in a single action only. e.g., multiple *TextField* widgets.
-
-
-
-
-
-
+
:::info
You can also reset form fields that are inside the components.
-
+
:::
\ No newline at end of file
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-actions/set-form-field.md b/docs/resources/control-flow/user-interactivity/forms/form-actions/set-form-field.md
index cd08c330..6d189b81 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-actions/set-form-field.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-actions/set-form-field.md
@@ -8,73 +8,42 @@ sidebar_position: 0
---
# Set Form Field [Action]
-This action allows you to set a value for the Form widgets. For example, you could use this action to auto-populate a form based on a user's previous submission.
-
-You could also dynamically update a dropdown menu based on a user's previous selection, such as showing relevant cities based on a selected country.
-
-
-
-
-
-
+The **Set Form Field** action allows you to programmatically populate or update the value of any input widget—like a TextField, Dropdown, or other form elements—at runtime. This is especially useful when you want to quickly fill or modify user input fields based on user preferences (e.g., saved addresses) or pre-stored information.
-## Adding Set Form Field action
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button, etc.) on which you want to add the action.
-2. Select **Actions** from the properties panel. If it's the first action, click the **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile (inside *Action Flow Editor*) and select **Add Action**.
-3. Search the **Set Form Field** (under *State Management*) action and select the widget you would like to set.
-4. Now, you can set its value directly or from a variable.
-
-
-
-
-
-
+:::info[possible use cases]
+
+- **Use Saved Address:** If a user toggles "Use Saved Address," you might set the Full Name, Street Address, City, and ZIP Code fields to values pulled from a user profile or database.
+- **Edit Existing Data:** When navigating to an "Edit Profile" page, you can auto-populate the TextFields with the current user info so they only change what’s needed.
+- **Auto select Country/State Dropdown:** Automatically select the user's country and state based on location services or their account settings.
+
+:::
+
+While adding the Set Form Field action, select the target widget (e.g., `TextField`) and assign a value—this could come from a variable like `fullName` in your backend, app state, or page parameters.
+
+
+
+If you need to update several widgets (such as a TextField and a Dropdown), use a separate Set Form Field action for each and specify the appropriate value.
+
+
+
+#### Focus Field When Set
+
+You can also set additional preferences like whether the field should be focused and how the cursor should behave using the **Focus Field When Set** option. When you enable the option, it automatically sets the focus on the field once its value is assigned.
+
+This is helpful in scenarios such as an “Edit Full Name” switch—when turned on, the field preloads the existing name and positions the cursor for immediate editing.
+
+
+When **Focus Field When Set** is enabled, you can set one of the following **Cursor Position**:
+
+- **End**: Places the cursor at the end of the newly filled text, letting the user continue typing from the last character.
+- **Start**: Positions the cursor at the beginning of the text.
+- **Highlight**: Selects (highlights) the entire text, letting the user immediately overwrite it.
+- **Preserve**: Maintains the cursor location as it was (if any), which is useful when the user is already typing and only part of the text has changed.
+
+
:::info
-You can also set form fields that are inside the components.
+You can also set form fields inside the current widget’s child component.
-
+
:::
\ No newline at end of file
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-triggers.md b/docs/resources/control-flow/user-interactivity/forms/form-triggers.md
new file mode 100644
index 00000000..76b2da88
--- /dev/null
+++ b/docs/resources/control-flow/user-interactivity/forms/form-triggers.md
@@ -0,0 +1,100 @@
+---
+slug: /resources/forms/form-triggers
+title: Form Triggers
+tags: [Form, Actions, Triggers]
+keywords: [FlutterFlow, Form Triggers, User Interactivity, Dropdown, Slider, Toggle, TextField, On Selected, On Toggled, On Change, On Focus Change]
+description: Learn how to use Form Triggers in FlutterFlow to create dynamic, interactive user experiences by responding to user input on widgets like dropdowns, sliders, toggles, and text fields.
+sidebar_position: 4
+---
+
+# Form Triggers
+
+**Form Triggers** in FlutterFlow allow you to respond dynamically to user input on widgets like dropdowns, sliders, toggles, and text fields. Whether it’s selecting an option, toggling a switch, or typing in a field, these triggers help you create interactive, responsive experiences by executing actions based on user interaction.
+
+## On Selected
+
+The **On Selected** action trigger is used to perform actions when a user selects or changes a value from a widget that presents multiple options. This trigger is associated with form widgets where selection input is required, such as [Dropdown](form-widgets/dropdown.md), [RadioButton](form-widgets/radiobutton.md), [CheckboxGroup](form-widgets/checkbox.md#checkboxgroup), [ChoiceChips](form-widgets/choicechips.md), and [Slider](../../../ui/widgets/built-in-widgets/slider.md).
+
+:::tip[Possible use cases]
+
+- **Dropdown – Shipping Method Selection:** User selects a shipping method from options like "Standard", "Express", or "Next Day". Action under the *On Selected* trigger sets the app state variable `shippingOption`, which updates pricing or estimated delivery time dynamically.
+- **Slider – Show Volume Level in Snackbar:** User adjusts a Slider from 0 to 100. The *On Selected* trigger displays a Snackbar showing the current volume: Volume set to: [sliderValue].
+- **ChoiceChips – Filter Products by Category:** User taps a chip like "All", "Electronics", or "Clothing". The *On Selected* trigger might set an app state variable (e.g., `selectedCategory`) and update the product list to match the chosen category.
+
+:::
+
+To use the **On Selected** trigger:
+
+1. Start by selecting a supported widget, such as a Dropdown.
+2. Open the **Actions** tab in the properties panel and click **+ Add Action**.
+3. You will notice that the **Type of Action** (aka callback) is already set to **On Selected**. That means actions added under this will be called whenever the selection changes.
+4. Finally, define the actions you want to perform when the user makes a selection, such as setting a variable, navigating to another page, or displaying a message.
+
+
+
+## On Toggled On / On Toggled Off
+
+The **On Toggled On** and **On Toggled Off** action triggers are used to perform actions when a user turns a toggleable widget on or off. These triggers are supported by widgets such as [Checkbox](form-widgets/checkbox.md), [CheckboxListTile](form-widgets/checkbox.md#checkboxlisttile), [Switch](form-widgets/switch.md), and [SwitchListTile](form-widgets/switch.md#switchlisttile), any widget that represents a binary state.
+
+These triggers are especially useful when you want to conditionally execute different actions based on whether a user enables or disables a setting, preference, or feature.
+
+:::tip[Possible use cases]
+
+- **Switch – Enable Dark Mode:** User toggles a Switch to enable Dark Mode. Action under the *On Toggled On* trigger sets the dark mode.
+- **Checkbox – Agree to Terms:** User checks a Checkbox labeled “I agree to the terms and conditions.” The *On Toggled On* trigger enables the Submit button. If the user unchecks it, the *On Toggled Off* trigger disables the button again.
+- **CheckboxListTile – Select Notification Channels:** User checks or unchecks options like Email, SMS, or Push Notifications. Each toggle fires either *On Toggled O*n or *On Toggled Off* to update selected preferences in the backend.
+
+:::
+
+To use the **On Toggled On** or **On Toggled Off** trigger:
+
+1. Start by selecting a supported widget, such as a Switch.
+2. Open the **Actions** tab in the properties panel and click **+ Add Action**.
+3. Choose **On Toggled On** to define actions when the toggle is switched on, or **On Toggled Off** to define actions when it's switched off.
+4. Add your desired actions, such as updating a variable, showing a message, enabling a button, or triggering a backend call.
+
+
+
+## On Change
+
+The **On Change** action trigger is used to respond to real-time user input as they type or modify the contents of an input field. This trigger is supported by widgets such as [TextField](form-widgets/text-field.md) and [Pincode](../../../ui/widgets/built-in-widgets/pincode.md).
+
+It’s ideal for enabling live form validations, updating app state as the user types, or enabling/disabling UI elements based on the current input.
+
+:::tip[Possible use cases]
+
+- **TextField – Enable Button When Email Is Entered:** As the user types in an email TextField, action under the *On Change* trigger checks if the input is a valid email. If it is, it enables the Continue button.
+- **Pincode – Auto Submit When Complete:** When a user finishes entering a 6-digit code in a Pincode widget, action under the *On Change* trigger checks if the full code is entered and triggers form submission or a backend call.
+
+:::
+
+To use the **On Change** trigger:
+
+1. Start by selecting a supported widget, such as a TextField.
+2. Open the **Actions** tab in the properties panel and click **+ Add Action**.
+3. Choose **On Change** from the list of available triggers.
+4. Define the actions to trigger, such as setting a variable, showing a message, or calling an API.
+
+
+
+---
+
+## On Focus Change
+
+The **On Focus Change** trigger fires whenever an input field gains or loses focus, like when a user taps into or out of a [TextField](form-widgets/text-field.md) and [Pincode](../../../ui/widgets/built-in-widgets/pincode.md) widget. It’s useful for providing user guidance (on focus) or performing validations.
+
+:::tip[Possible use cases]
+
+- **TextField – Show Hint on Focus:** When the TextField gains focus, action under the *On Focus Change* trigger displays a helper text or tooltip with input instructions (e.g., “Enter your phone number without dashes”).
+- **Pincode – Validate on Exit:** When the user finishes entering the code and the Pincode widget loses focus, action under the *On Focus Change* trigger runs validation logic to check if the input is complete or valid, and displays an error if it's not.
+
+:::
+
+To use the **On Focus Change** trigger:
+
+1. Start by selecting a supported widget, such as a TextField.
+2. Open the **Actions** tab in the properties panel and click **+ Add Action**.
+3. Choose **On Focus Change** from the list of available triggers.
+4. Define the actions to trigger, such as showing helper text, validating input, or updating the UI based on focus.
+
+
\ No newline at end of file
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-widgets/checkbox.md b/docs/resources/control-flow/user-interactivity/forms/form-widgets/checkbox.md
index 2f47376b..661a198a 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-widgets/checkbox.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-widgets/checkbox.md
@@ -77,7 +77,8 @@ Here is a simple way to do it:
-### Setting initial value
+
+### Setting Initial Value
You might want to show the checkbox with a default value, either check or uncheck. For example, showing the checked checkbox for travel insurance.
@@ -112,45 +113,9 @@ To set the initial value:
-### Saving checkbox value
-
-You might want to save the checkbox's value as soon as it is checked or unchecked. For example, saving in an app state variable or Firestore document field. You can do so by adding the action on the checkbox widget.
-
-The checkbox widget provides you with the following types of actions (aka callbacks), and you can choose any of them to add actions under it.
-
-1. **On Toggled On**: Actions added under this will be triggered whenever the checkbox is selected/checked.
-2. **On Toggled Off**: Actions added under this will be triggered whenever the checkbox is unselected/unchecked.
+### Saving Checkbox Value
-Here's how you do it:
-
-1. Select the **Checkbox** widget, select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-2. Select **On Toggled On** or **On Toggled Off** and add an action that will update the value. (e.g., [update app state](../../../../../resources/data-representation/app-state.md#update-app-state-action), [update Firestore record](../../../../../ff-integrations/database/cloud-firestore/firestore-actions.md), etc.)
-
-
-
-
-
-
+You may want to immediately save the checkbox’s value when it is checked or unchecked. To do this, [add an action using the trigger](../../forms/form-triggers.md#on-toggled-on--on-toggled-off) that responds to changes in the widget’s selection.
### Customizing
@@ -310,7 +275,11 @@ Here's an example of how you can use the CheckboxGroup widget in your project:
-### Setting initial selection
+### Trigger Action on Change
+
+See how to [trigger an action when a selection changes](../../forms/form-triggers.md#on-selected) on this widget.
+
+### Setting Initial Selection
Sometimes you might want to display the CheckboxGroup with some options already selected. For example, selecting the topping options that are already served with Pizza itself. You can do so by setting the initial selection for the CheckboxGroup.
@@ -522,6 +491,3 @@ To customize the checkbox border:
-:::info[Trigger action on change]
-See how to [**trigger an action when a selection changes**](../../../../ui/widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
-:::
\ No newline at end of file
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-widgets/choicechips.md b/docs/resources/control-flow/user-interactivity/forms/form-widgets/choicechips.md
index 48b0b223..59a83f6c 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-widgets/choicechips.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-widgets/choicechips.md
@@ -52,11 +52,11 @@ To add the ChoiceChips widget to your app:
-## Trigger action on change
+### Trigger Action on Change
-See how to [trigger an action when a selection changes](../../../../../resources/ui/widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
+See how to [trigger an action when a selection changes](../../forms/form-triggers.md#on-selected) on this widget.
-## Select or clear all choices [Action]
+## Select or Clear All Choices [Action]
Users may need to swiftly deselect all chips or choose all available choice chips at once. You can do so by adding the **Clear All/Select All** action.
@@ -68,7 +68,7 @@ Before you add this action, ensure you [**allow multiselect**](#allow-multiselec
You can customize the appearance and behavior of this widget using the various properties available under the properties panel.
-### Allow multiselect
+### Allow Multiselect
You might want to allow users to select multiple choices to filter the result.
@@ -165,7 +165,7 @@ To add a space between the chips, you can use the **Chip Spacing** ad **Row Spac
-### Align chips
+### Align Chips
When you have chips in multiple rows, you can align them using the **Alignment** property. This is similar to setting main axis alignment for the Row widget.
@@ -195,7 +195,7 @@ When you have chips in multiple rows, you can align them using the **Alignment**
-### Customizing selected and unselected chip style
+### Customizing Selected and Unselected Chip Style
Various properties under the **Selected Chip Style** and **Unselected Chip Style** section allow you to customize chips to match your design. Here's how you do it:
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-widgets/dropdown.md b/docs/resources/control-flow/user-interactivity/forms/form-widgets/dropdown.md
index 61bfcb2b..9b2a7c54 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-widgets/dropdown.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-widgets/dropdown.md
@@ -76,7 +76,7 @@ Let's see how to add a *DropDown* widget and build an example that shows the sel
-### Setting initial value
+### Setting Initial Value
Setting a default or initial value for the DropDown is a common requirement for many apps. It can provide a better user experience by pre-selecting the most likely option.
@@ -115,20 +115,19 @@ To set an initial value:
-### Saving DropDown value on selection change
+### Saving DropDown Value on Selection Change
You might want to save the dropdown value as soon as the selection changes. This approach is useful when you want to ensure that the user's selection is immediately saved without having to wait for them to submit the form. By doing so, you can provide a better user experience and reduce the risk of data loss in case of any interruption.
-You can do so by adding an action such as [update app state](../../../../../resources/data-representation/app-state.md#update-app-state-action), [update Firestore record](../../../../../integrations/database/cloud-firestore/firestore-actions#update-document-action) that [triggers when a selection changes](../../../../ui/widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
+You can do so by adding an action such as [update app state](../../../../../resources/data-representation/app-state.md#update-app-state-action), [update Firestore record](../../../../../integrations/database/cloud-firestore/firestore-actions#update-document-action) that [triggers when a selection changes](../../forms/form-triggers.md#on-selected) on this widget.
-
## Customizing
You can customize the appearance and behavior of this widget using the various properties available under the properties panel.
-### Showing option label
+### Showing Option Label
The dropdown widget allows you to show a label than the actual option value. By adding the option label, you can have a simple/short name or abbreviation (which is quite easy to compare and process in the backend) instead of a tricky name (e.g., Falkland Islands (the) [Malvinas]).
@@ -172,7 +171,7 @@ To show option label:
-### Searchable dropdown
+### Searchable Dropdown
The *DropDown* widget is a good choice when you have a small number of options, up to around 10-20; however, If you have more options than that, consider using a searchable dropdown.
@@ -211,7 +210,7 @@ To make the dropdown widget a searchable one:

-### Disable dropdown
+### Disable Dropdown
You might need to disable a dropdown when certain conditions are not yet met or need to be fulfilled. For example, when the dropdown options are dependent on other fields, and those fields are not filled yet.
@@ -244,11 +243,11 @@ You might need to disable a dropdown when certain conditions are not yet met or
To disable the dropdown:
1. Select the **DropDown** widget, move to the **Properties Panel > DropDown Search >** enable **Disable Dropdown** option.
-2. Click on **Unset** and select the source that returns the boolean value (i.e., True or False), such as boolean variable, [Conditions](../../../../../resources/functions/conditional-logic), [Code Expression](../../../../../resources/functions/utility#code-expressions).
+2. Click on **Unset** and select the source that returns the boolean value (i.e., True or False), such as boolean variable, [Conditions](../../../../../resources/functions/conditional-logic), [Inline Function](../../../../../resources/control-flow/functions/utility-functions.md#inline-function-code-expressions).

-### Allow multi select
+### Allow Multi Select
You might want to allow users to select multiple options from the dropdown list. For example, on an e-commerce app, users might want to filter products based on multiple attributes, such as t-shirts in both 'blue' and 'red' colors.
@@ -284,12 +283,11 @@ To clear the selection, you can use the [Reset Form Fields](../form-actions/rese
-
-### Changing dropdown size
+### Changing Dropdown Size
To change the height and width of the dropdown, select the **DropDown** widget, move to the **Properties Panel > DropDown Properties > enter the Width and Height value**.
-### Set max height
+### Set Max Height
If needed, you can also control the dropdown height using the **Max Height** property.
@@ -319,7 +317,7 @@ If needed, you can also control the dropdown height using the **Max Height** pro
-### Adding margin
+### Adding Margin
Margin adds a space between the DropDown's text and its border. To change the margin, select the **DropDown** widget, move to the **Properties Panel > DropDown Properties >** find the **Margin** property, and change the values.
@@ -349,13 +347,13 @@ Margin adds a space between the DropDown's text and its border. To change the ma
-### Changing background color
+### Changing Background Color
To change the background color, move to the **Properties Panel > DropDown Style > set the Fill Color**.

-### Changing menu elevation
+### Changing Menu Elevation
Menu elevation adds a shadow to the dropdown, giving it a sense of depth and making it appear above the surface it is placed on.
@@ -365,11 +363,11 @@ To change the menu elevation (depth or Z-axis), move the **Properties Panel >**
The higher value draws the bigger size of the shadow.
:::
-### Adding border
+### Adding Border
See how to [add a border](../../../../ui/widgets/widget-commonalities.md#adding-border).
-### Show/hide underline
+### Show/hide Underline
To show or hide the dropdown underline, move the **Properties Panel >** **DropDown Style** > use the **Hides Underline** toggle.
@@ -399,12 +397,8 @@ To show or hide the dropdown underline, move the **Properties Panel >** **DropDo
-### Fix position
+### Fix Position
By default, the dropdown options are displayed over/above the dropdown button. To display beneath/below the button, move the **Properties Panel >** **DropDown Style** > switch on the **Fix Position** toggle.

-
-:::info[Trigger action on change]
-See how to [**trigger an action when a selection changes**](../../../../ui/widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
-:::
\ No newline at end of file
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-widgets/radiobutton.md b/docs/resources/control-flow/user-interactivity/forms/form-widgets/radiobutton.md
index 32532ffa..00a6df9a 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-widgets/radiobutton.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-widgets/radiobutton.md
@@ -54,6 +54,10 @@ The RadioButton widget adds a single option named **Option 1** by default.
+### Trigger Action on Change
+
+See how to [trigger an action when a selection changes](../../forms/form-triggers.md#on-selected) on this widget.
+
### Changing Option Name
To change the name of the option:
@@ -486,9 +490,4 @@ To change the color of selected and unselected options:
allow="clipboard-write">
-
-
-
-:::info[Trigger action on change]
-See how to [**trigger an action when a selection changes**](../../../../ui/widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
-:::
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-widgets/switch.md b/docs/resources/control-flow/user-interactivity/forms/form-widgets/switch.md
index dfd0227e..03e96616 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-widgets/switch.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-widgets/switch.md
@@ -74,7 +74,7 @@ Here is a simple way to do it:
-### Setting initial value
+### Setting Initial Value
You might want to show the switch with a default status, i.e., ON or OFF. For example, showing the location service setting with a default switch OFF.
@@ -109,45 +109,9 @@ To set the initial value:
-### Saving switch value
+### Saving Switch Value
-You might want to save the switch value as soon as it is toggled ON or OFF. For example, saving in an app state variable or Firestore document field. You can do so by adding the action on the switch widget.
-
-The switch widget provides you with the following types of actions (aka callbacks), which you can use to add actions under it.
-
-1. **On Toggled On**: Actions added under this will be triggered whenever the switch is ON.
-2. **On Toggled Off**: Actions added under this will be triggered whenever the switch is OFF.
-
-Here's how you do it:
-
-1. Select the **Switch** widget, select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-2. Select **On Toggled On** or **On Toggled Off** and add an action that will update the value. (e.g., [update app state](../..//../../data-representation/app-state.md#update-app-state-action), [update Firestore record](../../../../../ff-integrations/database/cloud-firestore/firestore-actions.md), etc.)
-
-
-
-
-
-
+You may want to save the switch value as soon as it is toggled ON or OFF. To do this, [add an action using the trigger](../../forms/form-triggers.md#on-toggled-on--on-toggled-off) that responds to changes in the widget’s selection.
### Customizing
diff --git a/docs/resources/control-flow/user-interactivity/forms/form-widgets/text-field.md b/docs/resources/control-flow/user-interactivity/forms/form-widgets/text-field.md
index c4342e9f..4f6a1e87 100644
--- a/docs/resources/control-flow/user-interactivity/forms/form-widgets/text-field.md
+++ b/docs/resources/control-flow/user-interactivity/forms/form-widgets/text-field.md
@@ -16,7 +16,7 @@ The TextField widget allows users to enter text, numbers, and symbols in your ap
Before diving into form widgets, check out our guide on [**Widget States**](../../../../../ff-concepts/state-management/widget-state.md) to efficiently manage the state and behavior of your form elements.
:::
-## Adding TextField widget
+## Adding TextField Widget
Let's see how to add a TextField widget and see an example of displaying its value in an Alert Dialog.
@@ -81,11 +81,11 @@ Here are the steps:
You can customize the appearance and behavior of this widget using the various properties available under the properties panel.
-### Changing width
+### Changing Width
By default, the TextField widget takes all the available space in the horizontal direction. You might want to limit its width to match your design. See how to change the width of this widget.
-### Adding multiline/auto expand support
+### Adding Multiline/auto Expand Support
By default, a TextField is only one line. So when you type in a long text that won't fit in one line, you'll be able to see an entire message using a horizontal scrollbar. You can change this default behavior and show the full message (without a horizontal scrollbar) by making the TextField multiline/auto-expand.
@@ -120,7 +120,7 @@ To make a TextField multiline/auto-expand, move the **Properties Panel *>*** fin
-### Setting prefilled value
+### Setting Prefilled Value
You might want to display a TextField with some initial value. This can be any specific value such as "*What are you looking for*", "*Input your Email*", or a value from any variable.
@@ -128,7 +128,7 @@ To set the initial value, move to the **Properties Panel > TextField Properties

-### Adding label
+### Adding Label
Showing a label helps users understand what should be entered into the TextField. If you don't have an initial value set, the *Label Text* will appear as full size in the TextField. Once the user taps the TextField, the *Label Text* will become smaller, and the *Hint Text* will appear.
@@ -165,7 +165,7 @@ When the TextField is set to [Multiline](#adding-multilineauto-expand-support) t
-### Setting hint text
+### Setting Hint Text
Showing a hint text helps users know what information is needed to enter into the TextField. For example, showing hint text as "Enter Your Email Here" clearly informs the user to enter their email.
@@ -177,7 +177,7 @@ To set the hint text, move to the **Properties Panel > Hint Properties > enter t
Various properties under the *Input Decoration Properties* allow you to customize the TextField to match your design.
-### Changing TextField background color
+### Changing TextField Background Color
To change the background color, move to the **Properties Panel > Input Decoration Properties >** enable **Filled >** set the **Fill Color**.
@@ -207,7 +207,7 @@ To change the background color, move to the **Properties Panel > Input Decoratio
-### Adding border
+### Adding Border
Here's an example of how you can add a border around the TextField:
@@ -245,7 +245,7 @@ Here's an example of how you can add a border around the TextField:
-### Add content padding
+### Add Content Padding
Content Padding adds space between the test and the border of your TextField.
@@ -277,7 +277,7 @@ To add content padding, move to the **Properties Panel > Input Decoration Proper
-### Reducing TextField height
+### Reducing TextField Height
To reduce TextField's height to as minimum as possible, select the TextField widget, move to the **Properties Panel >** enable the **Dense** property.
@@ -308,7 +308,7 @@ To reduce TextField's height to as minimum as possible, select the TextField wid
-### Changing error message styling
+### Changing Error Message Styling
You can also change the text styling for the error message. To do so, head over to **Properties Panel > Input Decoration Properties >** enable **Custom Error Style** and [change the text styling](../../../../ui/widgets/basic-widgets/text.md#common-text-styling-properties).
@@ -324,7 +324,7 @@ You can also [customize the icon's size and color](../../../../ui/widgets/basic-

-### Using TextField for passwords
+### Using TextField for Passwords
To make a TextField a Password Field, move to the **Properties Panel > Additional Properties >** enable the **Password Field**.
@@ -410,6 +410,15 @@ To autofocus a TextField, select the TextField widget, move to the **Properties
+### Enable Interactive Selection
+
+The **Enable Interactive Selection** toggle controls whether users can interact with the text selection features, such as long-press selection, copy/paste menus, and selection handles.
+
+By default, this property is set to **True**, allowing users to select, copy, and paste text using the platform's built-in text selection controls. Disabling this can help prevent unintended text copying or editing, especially in sensitive fields.
+
+
+
+
### Autocomplete a TextField
You might want to allow users to enter the text by suggesting them a list of items. The suggested items are shown if it contains the currently entered text from TextField. For example, using autocomplete to get the *Country* *name*, *Fruit* *name*, etc.
@@ -486,7 +495,7 @@ If you *Set from Variable* and run the app in preview mode, you can try entering
-### Auto fill hint
+### Auto Fill Hint
When *Auto Fill Hint* property is enabled, it uses the operating system's autofill service to suggest the relevant information to the user, such as usernames, passwords, or credit card numbers, based on the context of the text field.
@@ -527,7 +536,7 @@ The availability and behavior of the *Auto Fill Hint* may vary by platform and u
-### Update page on change
+### Update Page on Change
You might have added the TextField widget inside the search page and want to refresh the search result as the value inside the TextField changes.
@@ -538,7 +547,7 @@ Enabling this feature will refresh the page whenever a user types into TextField
Here's an example of displaying the TextField value in a Text widget in realtime:
1. Select the TextField widget, move to the **Properties Panel** **> Additional Properties >** enable the **Update Page On Change** property.
-2. Also, set the **Update Delay (ms)** after which the page will refresh its UI when the user has stopped typing. For example, If the *Update Delay (ms)* value is set to 2000 ms (2 seconds), The page will update 2 seconds after use is done typing. For this example, let's keep it to 0.
+2. Also, set the **Update Delay (ms)**, which specifies the time interval after the user stops typing before the page refreshes its UI. For example, if the *Update Delay (ms)* value is set to 2000 ms (2 seconds), the page will update 2 seconds after the user stops typing. For this example, let's set it to 0 ms.
3. Now select the **Text** widget, move to the **Properties Panel > Set from Variable > Widget State > [TextFieldName]**. Tip: You can also set the default value to be displayed until the user has entered any text.
:::tip
@@ -601,7 +610,7 @@ Sometimes you might want to restrict users from entering or updating anything in
-### Change cursor color
+### Change Cursor Color
In a form with many text fields, changing the cursor color for the currently focused field can help the user understand where their input will go when they start typing.
@@ -609,7 +618,7 @@ To change the cursor color, head over to **Properties Panel** **> Additional Pro

-### Changing keyboard type
+### Changing Keyboard Type
When the keyboard opens by default, you can type any text. You might want user input in a certain format, such as a phone number, email address, website URL, etc. In this situation, you can choose a predefined keyboard type to present the appropriate key selections.
@@ -620,7 +629,7 @@ To change the keyboard type, select the TextField widget, move to the **Properti

-### Masking input
+### Masking Input
You might want to allow users to provide input in a specific format. For example, if you want a date in a format like MM/DD/YYYY, where all input must be a number, and its length should not exceed eight digits. You can do so by formatting the user input using the specific mask.
@@ -660,7 +669,7 @@ If the required format is not on the list, you can select **Custom** and specify
-### Filtering input
+### Filtering Input
You might want to restrict the type of characters that can be entered into a TextField. Let's say you are building an app that requires its employees to enter their employee ID when they clock in and out for their shifts. The employee ID consists of only letters and numbers, and the app should only allow these characters to be entered. You can do so by filtering the user input
@@ -692,7 +701,7 @@ To filter the user input, select the TextField widget, move to the **Properties
-### Validating input
+### Validating Input
You can validate the TextField value by wrapping it inside the [Form](../form-validation.md) widget and adding the validation criteria.
@@ -715,7 +724,7 @@ To set the capitalization, select the TextField widget, move to the **Properties

-### Submit type
+### Submit Type
Showing a particular action on a keyboard can be useful in guiding users on what to do next. For example, if you have a search bar, you can display a "Search" button on the keyboard. When tapped, instead of moving to a new line or closing the keyboard, you can execute a search function. This can improve user experience by providing more intuitive keyboard actions based on the context of the input.
@@ -733,7 +742,7 @@ To set the submit type, select the TextField widget, move to the **Properties Pa

-### Set max character length
+### Set Max Character Length
Sometimes, you might want to specify the maximum number of characters users can enter into the TextField. When the user types or pastes text into the field and reaches the specified character limit, they won't be able to input more characters, or the TextField will visually indicate that the limit has been reached.
@@ -775,7 +784,7 @@ You can also hide the maximum character count by enabling the **Hide Max Length
-## Hiding keyboard on tap
+## Hiding Keyboard on Tap
Hiding the keyboard when the user taps outside of a TextField is a common user experience pattern that many apps use to improve usability. When the keyboard is open, it can obscure important information on the screen and make it difficult for the user to interact with other parts of the app.
@@ -813,7 +822,7 @@ To hide/close the keyboard, select the page, move the **Properties Panel >** ena

-## Focus change event
+## Focus Change Event
Sometimes, you may need to know whether a TextField is being used or not. For example, you can turn other parts of the app *on* or *off* depending on if the TextField is active. Also, you can start animations when someone starts or stops typing in the TextField.
@@ -876,7 +885,7 @@ To do so:
-## Trigger action / Listen callback
+## Trigger Action / Listen Callback
The TextField widget provides you with two types of actions (aka callbacks):
@@ -1037,4 +1046,4 @@ If you prefer watching a video tutorial, here's the one for you:
allow="clipboard-write">
-
\ No newline at end of file
+
diff --git a/docs/resources/control-flow/user-interactivity/forms/forms.md b/docs/resources/control-flow/user-interactivity/forms/forms.md
index 031f6cb0..82489cb1 100644
--- a/docs/resources/control-flow/user-interactivity/forms/forms.md
+++ b/docs/resources/control-flow/user-interactivity/forms/forms.md
@@ -1,6 +1,6 @@
---
slug: /resources/forms
-title: Overview
+title: Forms Overview
tags: [Forms]
keywords: [FlutterFlow, forms, input fields, user interface, mobile app development, data collection, user interaction]
description: Learn how to work with Forms in FlutterFlow app.
@@ -8,9 +8,9 @@ sidebar_position: 0
---
-# Overview
+# Forms Overview
Forms are a fundamental part of many applications, serving as the primary method for users to input and submit data. Whether you're building a simple contact form or a complex multi-step survey, FlutterFlow provides a comprehensive set of tools to create, validate, and manage forms effectively.
:::tip
In this section, you'll learn how to add form widgets such as [**TextField**](form-widgets/text-field.md), [**Dropdown**](form-widgets/dropdown.md), [**RadioButton**](form-widgets/radiobutton.md), [**Checkbox Widgets**](form-widgets/checkbox.md) and add [**Validations**](form-validation.md) and [**set**](form-actions/set-form-field.md)/[**reset**](form-actions/reset-form-field.md) actions on these widgets.
-:::
\ No newline at end of file
+:::
diff --git a/docs/resources/control-flow/user-interactivity/forms/imgs/interactive-selection.avif b/docs/resources/control-flow/user-interactivity/forms/imgs/interactive-selection.avif
new file mode 100644
index 00000000..63910e8a
Binary files /dev/null and b/docs/resources/control-flow/user-interactivity/forms/imgs/interactive-selection.avif differ
diff --git a/docs/resources/control-flow/user-interactivity/forms/imgs/on-change.avif b/docs/resources/control-flow/user-interactivity/forms/imgs/on-change.avif
new file mode 100644
index 00000000..a4b308bb
Binary files /dev/null and b/docs/resources/control-flow/user-interactivity/forms/imgs/on-change.avif differ
diff --git a/docs/resources/control-flow/user-interactivity/forms/imgs/on-focus-change.avif b/docs/resources/control-flow/user-interactivity/forms/imgs/on-focus-change.avif
new file mode 100644
index 00000000..14749352
Binary files /dev/null and b/docs/resources/control-flow/user-interactivity/forms/imgs/on-focus-change.avif differ
diff --git a/docs/resources/control-flow/user-interactivity/forms/imgs/on-selected.avif b/docs/resources/control-flow/user-interactivity/forms/imgs/on-selected.avif
new file mode 100644
index 00000000..0b4bd1b5
Binary files /dev/null and b/docs/resources/control-flow/user-interactivity/forms/imgs/on-selected.avif differ
diff --git a/docs/resources/control-flow/user-interactivity/forms/imgs/on-toggle.avif b/docs/resources/control-flow/user-interactivity/forms/imgs/on-toggle.avif
new file mode 100644
index 00000000..df4315a5
Binary files /dev/null and b/docs/resources/control-flow/user-interactivity/forms/imgs/on-toggle.avif differ
diff --git a/docs/resources/data-representation/app-state.md b/docs/resources/data-representation/app-state.md
index 32609b3f..f022f034 100644
--- a/docs/resources/data-representation/app-state.md
+++ b/docs/resources/data-representation/app-state.md
@@ -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
@@ -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.
:::
@@ -114,3 +114,21 @@ Here's a quick guide to updating the app state variable. We need to add an actio
+:::tip
+If you want to rebuild a page or component without updating any state variables, use the [**Rebuild**](../../ff-concepts/state-management/state-variables.md#rebuild-action) state action.
+:::
+
+## FAQs
+
+
+
+Why are some variable types not available in App State?
+
+
+Certain variable types, e.g., **Firestore Documents** and **Supabase Row**, can be used in Page State or Component State, but not in App State. This is because App State variables are designed to be global, meaning they stay in memory throughout the app. When App State variables are marked as persisted, the variable’s value is saved to the device’s local storage.
+
+Storing large or complex data types like documents in App State could lead to **performance or size issues**, especially on lower-end devices. For this reason, FlutterFlow limits App State to lightweight types, while Page/Component State allows for more flexibility since their scope is smaller and temporary.
+
+If you need to work with such data types, it's recommended to store them in Page or Component state instead.
+
+
\ No newline at end of file
diff --git a/docs/resources/data-representation/constants.md b/docs/resources/data-representation/constants.md
index a2d1c151..2e46cecb 100644
--- a/docs/resources/data-representation/constants.md
+++ b/docs/resources/data-representation/constants.md
@@ -42,4 +42,8 @@ Constants don't change. Once you set its value (in builder), you can't change it
allowFullScreen
allow="clipboard-write">
-
\ No newline at end of file
+
+
+:::tip[Naming Convention]
+Prefer using a lowercase `k` prefix for constants to indicate their immutability, especially for project-specific constants. This approach is more concise and aligns with Dart's common practices. To learn more, refer to the guide on **[Naming Variables & Functions](../../resources/style-guide.md)**.
+:::
diff --git a/docs/resources/data-representation/custom-data-types.md b/docs/resources/data-representation/custom-data-types.md
index 1aa647cb..2d5d0a68 100644
--- a/docs/resources/data-representation/custom-data-types.md
+++ b/docs/resources/data-representation/custom-data-types.md
@@ -62,9 +62,48 @@ To create a custom data type, specify its name and the corresponding fields. Eac
+:::tip[Naming Convention]
+When naming custom data types, always use **UpperCamelCase**, as recommended by the Dart Style Guide. To learn more, refer to the guide on **[Naming Variables & Functions](../../resources/style-guide.md)**.
+:::
+
## Accessing Custom Data Type
-After creating the custom data type, you can use it to create variables, such as an app state variable, and then access them. Here's an [example](app-state.md#app-state-variables).
+After creating a custom data type, it’s treated internally as a [Dart class](https://dart.dev/language/classes). However, just defining the custom data type doesn’t hold any real data. To work with actual data, such as storing a user profile or a review, you need to create an **instance** of custom data type.
+
+Creating an instance allows you to:
+
+- Assign specific values to each field in your custom data type.
+- Store the instance in app state, page state, or pass it between widgets.
+- Access individual fields wherever needed.
+
+To create an instance of a custom data type, first you need to [create a state variable](../../ff-concepts/state-management/state-variables.md#creating-state-variables) (of type **Data Type**) that will hold the instance. Then, to create and add the instance to the state variable, open the **Set from Variable** dialog and select **Create Data Type Object > Project Data Type**. Choose the data type you want to use. After that, set values for each of the required fields.
+
+
+
+
+
+
+
### Custom Data Type in Custom Code
Sometimes, you might want to access the custom data type in your custom code. Our custom code editor allows you to receive and pass data into a variable of a custom data type. For example, you could manipulate or analyze the data as needed, and then return the modified result in the custom data type.
diff --git a/docs/resources/data-representation/data-types.md b/docs/resources/data-representation/data-types.md
index 053b92a2..331efa94 100644
--- a/docs/resources/data-representation/data-types.md
+++ b/docs/resources/data-representation/data-types.md
@@ -23,7 +23,7 @@ Composite data types are made up of primitive data types. They can hold multiple
You can also create your own custom data types. This can be especially useful when you need a specific structure for your data that doesn't fit into the predefined types. For example, you might create a custom data type for a user profile, which includes several pieces of data like a name, an email address, and a profile picture.
:::info
-Learn more about creating and using custom data types [**here**](custom-data-types).
+Learn more about creating and using [**Custom Data Types**](custom-data-types.md).
:::
## Built-in Data Types
@@ -54,6 +54,6 @@ Enums, or enumerated types, are a special kind of data type that consists of a s
:::info
-Learn more about creating and using enums [**here**](enums).
+Learn more about creating and using enums [**here**](enums.md).
:::
diff --git a/docs/resources/data-representation/enums.md b/docs/resources/data-representation/enums.md
index d488ce28..a6088852 100644
--- a/docs/resources/data-representation/enums.md
+++ b/docs/resources/data-representation/enums.md
@@ -53,4 +53,8 @@ Here are some real-world examples where using Enums is beneficial:
2. Access the Enum values by navigating to the **Set from Variable** menu, then selecting **Enums > [your enum name] > Values**.
-
\ No newline at end of file
+
+
+:::tip[Naming Convention]
+When naming enums, always use **UpperCamelCase**, and for enum values, use **lowerCamelCase**, as recommended by the Dart Style Guide. To learn more, refer to the guide on **[Naming Variables & Functions](../../resources/style-guide.md)**.
+:::
diff --git a/docs/resources/data-representation/global-properties.md b/docs/resources/data-representation/global-properties.md
index c8438cce..0cd28919 100644
--- a/docs/resources/data-representation/global-properties.md
+++ b/docs/resources/data-representation/global-properties.md
@@ -31,9 +31,12 @@ A list of all the available global properties is as follows:
- **Current Time**: Fetches the current date and time. Explore [custom formatting](#current-time) options to tailor the DateTime display to your needs.
-- **Current Device Location:** Obtains he user's current location, ideal for updating their position on Google Maps or storing it in a backend database. [Check out examples](#current-device-location) on how to retrieve and save the current device location.
+- **Current Device Location:** Returns the user's current location, ideal for updating their position on Google Maps or storing it in a backend database. [Check out examples](#current-device-location) on how to retrieve and save the current device location.
-- **Link To Current Page:** Provides the deep link of the current page. Learn more about [adding deep links here](../../ff-concepts/navigation-routing/deep-dynamic-linking.md#adding-deep-link).
+- **Link To Current Page:** Provides the [Deep Link](../../ff-concepts/navigation-routing/deep-dynamic-linking.md#deep-link) of the current page.
+
+- **Current Route Path**: Provides the route name of the currently active or visible page in your app. This property is especially helpful in scenarios where you want to adjust or block specific actions if the active page isn't the one you expect. For example, if you launch the app through a push notification, the home page might still run in the background, even if the notification directs you to a different page. Using this property, you can prevent unnecessary action triggers, such as On Page Load from the home page. See details on avoiding [this issue](https://github.com/FlutterFlow/flutterflow-issues/issues/2765#issuecomment-2598915946).
+- **Current Route Stack:** Returns a list of route names representing every active page in your app’s navigation stack. It’s helpful for understanding how many pages deep the user is and what sequence of pages they’ve visited. You may need this data to manage custom back navigation, breadcrumb displays, or logging analytics. For instance, in an e-commerce app, you could examine the route stack to see if the user arrived at the checkout page from a specific page and tailor your promotional messages or apply discount accordingly.
- **Fraction of Screen Width:** Determines the proportional width of the device's screen.
- **Fraction of Screen Height:** Determines the proportional height of the device's screen.
- **Screen Width:** Provides the total width of the current device's screen in pixels.
@@ -45,10 +48,10 @@ A list of all the available global properties is as follows:
- **Is Dark Mode:** Checks if the app's current theme mode is set to dark.
- **Is Light Mode:** Checks if the app's current theme mode is set to light.
- **Is On-Screen Keyboard Visible:** Checks if the on-screen or soft keyboard is visible. This is helpful in making UI adjustments if keyboard is visible on screen. See a [quick example](#is-on-screen-keyboard-visible).
-
+- **Current Environment**: Returns 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
diff --git a/docs/resources/data-representation/variables.md b/docs/resources/data-representation/variables.md
index d2b20ac8..d03a3f20 100644
--- a/docs/resources/data-representation/variables.md
+++ b/docs/resources/data-representation/variables.md
@@ -34,7 +34,7 @@ When creating variables in FlutterFlow, there are a few important considerations
Start by giving your variable a meaningful and descriptive name that reflects its purpose. This name will be used throughout your app to reference the variable, so it's important to keep it clear and consistent with your naming conventions.
:::tip[Recommended naming convention]
-We recommend the `lowerCamelCase` naming convention for variables.
+We recommend the `lowerCamelCase` naming convention for variables. Learn more about the **[recommended naming conventions](../style-guide.md)** used in FlutterFlow and Flutter projects.
:::
### Assigning a Data Type to a Variable
diff --git a/docs/resources/imgs/comp-style-guide.png b/docs/resources/imgs/comp-style-guide.png
new file mode 100644
index 00000000..72628282
Binary files /dev/null and b/docs/resources/imgs/comp-style-guide.png differ
diff --git a/docs/resources/imgs/dt-style-guide.png b/docs/resources/imgs/dt-style-guide.png
new file mode 100644
index 00000000..3f5fd339
Binary files /dev/null and b/docs/resources/imgs/dt-style-guide.png differ
diff --git a/docs/resources/imgs/func-style-guide.png b/docs/resources/imgs/func-style-guide.png
new file mode 100644
index 00000000..bac856e7
Binary files /dev/null and b/docs/resources/imgs/func-style-guide.png differ
diff --git a/docs/resources/imgs/various-naming-styles.png b/docs/resources/imgs/various-naming-styles.png
new file mode 100644
index 00000000..7a44d9c6
Binary files /dev/null and b/docs/resources/imgs/various-naming-styles.png differ
diff --git a/docs/resources/projects/how-to-collaborate-on-projects.md b/docs/resources/projects/how-to-collaborate-on-projects.md
index f7f49c21..d7f31968 100644
--- a/docs/resources/projects/how-to-collaborate-on-projects.md
+++ b/docs/resources/projects/how-to-collaborate-on-projects.md
@@ -8,44 +8,94 @@ sidebar_position: 3
keywords: [Collaboration, FlutterFlow, Project Management]
---
-FlutterFlow allows for multiple ways to collaborate on a project as well as the
-ability to manage the collaboration through permissions.
+In FlutterFlow you can share projects with your entire organization (team), with individual users within your organization, or external users.
-## Sharing a Project with a User
+## Sharing a Project with Team
+
+To share a project with team members, use the **Share with team** dropdown in the **Collaboration** page of your project's settings, and select how you want the project to be shared:
+
+
+
+- **Team project:** A project associated with your team and automatically visible to all team members. When a project is a Team Project, team members are automatically added as Editors. You can specifically designate team members as Viewers, but you cannot remove them.
+- **Restricted team project:** A project associated with your team but only visible to specific team members who are added directly. After selecting this option, you’ll need to manually choose the team members you want to share the project with.
+- **Personal project:** A project not associated with any team, where editing capabilities depend on the type of personal plan you have.
+
+:::info
+- The Team owner always has edit access to the project, regardless of who created or shared it, and retains full team plan capabilities.
+- The Team owner can also selectively share the project with any number of team members.
+- A [**Library**](../../resources/projects/libraries.md) project will not have the *Restricted Team Project* option.
+- Sharing a project with team members is only available on the **Growth** plan and **higher**. Check out our [**pricing**](https://www.flutterflow.io/pricing) section.
+:::
+
+
+## Sharing a Project with External Collaborators
You can invite users to your project who are not part of your organization.
For instance, you might want to share your work with clients, stakeholders, or
team members of the client.
-
+You can add users as Read Only users to any project regardless of your pricing plan in the **Collaborators** page of your project's settings.
-When you invite users to your project, you have the flexibility to assign them
-different roles depending on their level of involvement. For example, you can
-grant **editing** privileges to collaborators who are actively working on the
-project while assigning **read-only access** who need to view the progress.
-Alternatively, you can also make them the **owner** of the project, giving them full
-control.
:::info
-
-- When you add a user, the default role assigned is the *Editor* role.
- Users with read-only access will only be able to access that specific project
and won't be able to access any shared *Teams* libraries (e.g., custom code,
design system).
-- Read-only users added to *Teams*/*Organization* will not count against your
- *Teams* seat count.
- You must verify your email before inviting users.
-- If a user isn't already a FlutterFlow user, we will send them an invite email.
- Their status will be shown as **Pending** until they create an account.
-- FlutterFlow subscriptions are seat based. A user added to your project will
- only have access to the features of their account plan.
- :::
+- If a user isn't already a FlutterFlow user, we will send them an invite email. Their status will be shown as Pending until they create an account.
+:::
+
+To add an external user as a collaborator as an Editor to a project, you first need to purchase a collaborator pass.
+
+To purchase a collaborator pass, go to the [My Teams](https://app.flutterflow.io/team) page and, under the **Collaborator Passes** section, click **Add Pass** and complete the checkout process. Once the pass is created, enter the user email and select the project (Team Project or Restricted Team Project) you’d like to grant them access to.
+
+:::info
+- You must be a Team Owner to purchase and assign a Collaboration Pass.
+- Collaborator Passes can only be assigned to users who have a paid plan (Basic, Growth, or Business).
+:::
+
+
+
+
+
+
+
+
+
+## Transferring Project
+
+:::danger
+This step can not be undone. If you want to regain project ownership, the new
+project owner will need to transfer ownership back to you.
+:::
+To transfer ownership to another user, navigate to **Settings & Integrations > Project Setup > Collaboration > Project-Level Access**, click on the current role and select **Owner**.
-## Sharing a Project with an Organization
+:::info
+You can transfer a project to any FlutterFlow user (including [external collaborators](#sharing-a-project-with-external-collaborators)) as long as they have an active paid plan.
+:::
-To share a project with all current and future team members in your organization, enable the **Grant team members access** option.
+
-
## Real-Time Collaboration
@@ -63,31 +113,17 @@ When multiple builders are on the same page, it looks like this:

:::info
-
-Real-Time collaboration is a feature of our Teams and Enterprise plans.
- :::
-
-## Transferring Project
-
-:::danger
-This step can not be undone. If you want to regain project ownership, the new
-project owner will need to transfer ownership back to you.
+Real-Time collaboration is only available on the **Growth** plan and **higher**. Check out our [**pricing**](https://www.flutterflow.io/pricing) section.
:::
-To transfer ownership to another user, navigate to **Settings & Integrations > Project Setup > Collaboration > Project-Level Access**, click on the current role and select **Owner**.
-
-
## Project Activity
You can see a running history of changes made while building that helps you
-track progress and stay up to date on project changes. This feature allows team
-members to see all the updates made to a project in real-time, enabling them to
-understand how the project is evolving and collaborate more efficiently.
-
-
+track progress and stay up to date on project changes.
:::info
-Teams users can access the last 7 days of project edits, while FlutterFlow
-Enterprise users can access and download all previous project edits.
-:::
\ No newline at end of file
+Project Activity is only available to **Enterprise** users. Check out our [**pricing**](https://www.flutterflow.io/pricing) section.
+:::
+
+
diff --git a/docs/resources/projects/imgs/NavBar-settings-for-regular-and-library-page.avif b/docs/resources/projects/imgs/NavBar-settings-for-regular-and-library-page.avif
new file mode 100644
index 00000000..d066fffa
Binary files /dev/null and b/docs/resources/projects/imgs/NavBar-settings-for-regular-and-library-page.avif differ
diff --git a/docs/resources/projects/imgs/share_with_team.png b/docs/resources/projects/imgs/share_with_team.png
new file mode 100644
index 00000000..1ed121c1
Binary files /dev/null and b/docs/resources/projects/imgs/share_with_team.png differ
diff --git a/docs/resources/projects/libraries.md b/docs/resources/projects/libraries.md
index 32274228..cad64967 100644
--- a/docs/resources/projects/libraries.md
+++ b/docs/resources/projects/libraries.md
@@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem';
# Libraries
-Libraries enables you to share and reuse entire FlutterFlow projects as dependencies across multiple projects. This allows teams and developers to modularize their apps by creating shared libraries that include components, API calls, custom code, and more. By using libraries, development becomes more efficient and scalable.
+Libraries enable you to share and reuse entire FlutterFlow projects as dependencies across multiple projects. This allows teams and developers to modularize their apps by creating shared libraries that include components, API calls, custom code, and more. By using libraries, development becomes more efficient and scalable.
:::info
A **Dependency** refers to an external library or resource that your project relies on to function correctly. When you create a new FlutterFlow project, certain dependencies are automatically added to support the generated code. Also, when you use a [**Custom Widget**](../../ff-concepts/adding-customization/custom-widgets.md), you are essentially adding dependencies to your project. Libraries take this concept further by allowing you to add entire FlutterFlow projects as dependencies.
@@ -74,18 +74,28 @@ To publish a FlutterFlow project as a library, start by creating a FlutterFlow p
:::info
-- You can only publish libraries if you have access to branching, which is available to Pro+ users.
+- You can only publish libraries if you have access to [**branching**](../../testing-deployment-publishing/branching-collaboration/branching.md), which is available to users on **Growth** plan and above.
- Libraries can only be published from the main branch, and each published version is linked to a specific commit, ensuring robust version control.
- You must commit your changes before publishing a new version of the library.
- It's recommended to include a message that tells users what has changed in the version your are publishing.
:::
+:::warning
+To publish a project as a library, it must meet the following requirements:
+
+- **No Prior Store Deployment**: The project must not have been deployed to the Google Play Store or Apple App Store.
+- **No Failed Deployments**: The Publish button remains disabled if a deployment process was started and failed.
+- **No Errors or Warnings**: All project errors or warnings must be addressed beforehand.
+- **Main Branch Only**: You can only publish from the main branch.
+- [**Paid Plan**](https://www.flutterflow.io/pricing): Subscription to one of the paid plans is required to publish a project as a Library.
+- **Not Cloned from Marketplace**: The project cannot be a clone of a Marketplace item.
+:::
+
### Disabled Features in a Library
When a project is converted into a library, the following features are disabled to ensure compatibility and functionality limitations:
- App settings
- - Firebase
- Supabase
- Development environments
- Authentication
@@ -98,12 +108,10 @@ When a project is converted into a library, the following features are disabled
- Google Analytics
- OneSignal
- Mux
-- Cloud functions
-- Firestore Collections
## Importing a Library
-To import a library project into another FlutterFlow project, you must go to the **Project Dependencies** page in **App Settings**. Here you can specify the library project and version you are importing.
+To import a library project into another FlutterFlow project, you must go **Settings and Integrations** > **Project Setup** > **Project Dependencies** . Here you can specify the library project and version you are importing.
+
+
+
+
+
+### Library Pages in NavBar
+
+Library pages can also be used in the NavBar, allowing users to add reusable flows into the app’s primary navigation structure. For example, in a Super App, you can import ride booking, food delivery, or payment pages from separate libraries and add them directly to the bottom navigation, giving users quick access to each module.
+
+:::tip
+Want to learn more about building modular Super Apps using libraries? Check out our [**blog post**](https://blog.flutterflow.io/scaling-super-apps-modular-architecture-with-flutterflow-libraries/).
+:::
+
+To display a library page on the NavBar, navigate to **Project Dependencies > FlutterFlow Libraries**, then click on **Pages** for the relevant library to open its details. In the list of pages, locate the desired page and click **Nav Bar Settings**, then enable **Show on NavBar**. You can also customize additional settings, such as label and icon, as needed.
+
+To confirm, go to the **Nav Bar & App Bar** section, where you’ll see the library page listed as part of the NavBar items.
+
+:::info
+NavBar settings for regular pages are available directly within the Page Settings panel in the builder. However, for Library pages, these settings are managed through the Library Details dialog.
+
+
+:::
+
+
+
+
+
+
+
+
## Library Values
-**Library values** are essentially variables created and used by a library author and intended to have their values set by the library user. These values allow library author to create configurable variables that are useful in different contexts, such as API keys, global settings, or other project-specific configurations. These values allow library users to input specific data required for the library to function properly in their project.
+**Library values** are essentially variables created and used by a library author and intended to have their values set by the library user. These values allow library author to create configurable variables that are useful in different contexts, such as public or client-side API keys, global settings, or other project-specific configurations. These values allow library users to input specific data required for the library to function properly in their project.
-For example, If someone has built a library that uses OpenAI API, they would define a Library Value for the OpenAI API key. As the user of the library, when you import, you must provide your own API key to ensure the library functions properly.
+For example, if someone builds a payment gateway library, they might define Library Values for configuration settings, such as:
-By using Library Values, the library author allows users to adapt the library to their own configurations without hardcoding sensitive or project-specific data, like API keys, into the library itself.
+- Default currency: USD
+- Region: US
+- Default Payment method: Card
+
+This allows the user importing the library to provide their own payment preferences without modifying the internal code of the library.
+
+:::danger
+**Library Values should not be used to store private or sensitive data**, such as secret API keys or credentials. These values are not currently designed to securely store or handle sensitive information.
+
+The use of *client-side* or *publishable* API key is generally acceptable, because the keys often have limited permissions, rate limits, or are intended for public use. For instance, if someone creates a library that connects to a public weather API, they might define a Library Value for the API key. Users of that library can then input their own API key to make it work.
+:::
+
+:::tip
+To avoid misuse on any type credential, make sure to apply appropriate restrictions to limit its usage. For example, see how to [**restrict a Google Maps API key**](../../ff-integrations/google-cloud/secure-keys.md#add-restrictions-to-your-api-key) in the Google Cloud Console.
+:::
### Create Library Values as Author
@@ -275,6 +389,7 @@ To create library values, navigate to **Settings and Integrations > App Settings
+
#### Use Library Values
After setting Library Values, they function just like any other variable in FlutterFlow. You can bind them to components, actions, API calls, or any property that allows you to configure dynamic values across your library project. You can access Library Values via the ****Set from Variable**** menu.
@@ -315,9 +430,28 @@ To set library values, navigate to **Settings and Integrations > Project Setup >
:::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
+You can create collections and enable various Firebase features in library projects without connecting a separate Firebase project.
+
+In library projects, you won’t see an option to link to a Firebase project. Instead, the project that imports the library handles the actual Firebase connection.
+
+Any indexes or security rules defined in the library are recognized by the importing project and deployed accordingly.
+
+:::warning[Limitations]
+Libraries work with Firebase but have **some limitations**. The **Firebase Auth** and **Firebase Storage** are not directly supported in library projects at this time. If you need these features in your library’s functionality, you can include an action that accomplishes this task as a [**callback**](../../resources/ui/components/callbacks.md).
+:::
+
+If your team has multiple projects that share a common Firebase feature, turning it into a library is a great idea. This ensures the same logic is used and connects to the same Firestore project across all apps.
+
+Here are some examples of library projects you can build with Firebase:
+
+- **Basic Analytics or Tracking**: A library that logs events to Firestore; useful for aggregating usage data at an application level.
+- **Configuration or Settings**: A library that serves app-wide configurations (like feature flags, UI themes, or layout choices) is handled in Firebase Remote Config.
+
## FAQs
@@ -328,16 +462,16 @@ Team code and API libraries will be migrated to library Projects. These projects
-Will libraries work with Marketplace?
+Do libraries work with Marketplace?
-We plan to allow users to import a marketplace project as a library, making it easier to integrate marketplace resources into your projects.
+Yes, you can add and import a Marketplace project as a library.
-How do libraries work with themes?
+How do libraries work with themes (design systems)?
-The parent project's design system takes precedence over the imported library's design system. For example, if a library uses the standard FlutterFlow color scheme, the values defined in the parent project will override those in the library. However, if the library project has a custom color that the parent project does not have, it will be used as-is in the parent project.
+By default, the design system of the parent project takes precedence over the imported library's design system. If you want to use a library's design system, you must [**select or set the library in the Design System**](../../ff-concepts/design-system/design-system.md#adding-design-system) page.
@@ -353,4 +487,15 @@ We're working on Library Values, which will allow users to set specific values w
Projects can import libraries that themselves have imported other Libraries as dependencies. However, if the project and the library share the same dependency, the version must match exactly to avoid conflicts.
-
\ No newline at end of file
+
+
+
+Why do I get collision errors when importing a duplicated project as a library?
+
+When you duplicate a project and publish it as a library, the unique identifiers (keys) for components and other resources are not automatically changed. If you then import this library back into the original project, it causes key collisions between the original and duplicated resources.
+
+To help with this, FlutterFlow shows a dialog that offers to automatically delete the original resources in your base project and update all references to point to the library versions.
+
+If you prefer to resolve this manually, you can duplicate individual components within the library after importing, this will generate new keys and avoid the collision.
+
+
diff --git a/docs/resources/projects/refactor-project.md b/docs/resources/projects/refactor-project.md
new file mode 100644
index 00000000..1572945e
--- /dev/null
+++ b/docs/resources/projects/refactor-project.md
@@ -0,0 +1,70 @@
+---
+slug: refactor-project
+title: Refactor Project
+tags: [Refactor]
+keywords: [FlutterFlow, Refactor Project, developer tools, large-scale edits, rename , key reference search, developer menu]
+description: Learn how to refactor your project in FlutterFlow.
+sidebar_position: 7
+---
+
+# Refactor Project
+
+:::tip[PLANS]
+Refactor Project is only available on the Paid Plans. Check our [**pricing plans**](https://flutterflow.io/pricing).
+:::
+
+**Refactor Project** is a developer‑focused mode that opens your FlutterFlow project as a set of YAML files so you can perform large-scale edits in a single, consistent operation.
+
+For example, if you want to use a custom data type from a Library and update all references, you don’t have to manually edit each page or component. With this mode enabled, you can update all references at once using a single refactor pass.
+
+It makes managing large projects easier and more reliable. You can make changes across hundreds of references in just seconds, saving time and effort compared to manual edits. It also lets you preview changes and dismiss anything you don’t want to update.
+
+:::tip[possible use cases]
+- **Type Refactoring**: Rename a custom data type (e.g., `OrderDetails` → `OrderInfo`) across all bindings, forms, and logic in a single pass.
+- **String Replacement**: Find and replace hardcoded (magic) strings like `"admin"`, `"true"`, or `"completed"` to improve clarity and maintainability.
+- **Library Migration**: Replace a project-based custom data type (e.g., `UserProfile`) with its Library counterpart throughout the app without manually editing each reference.
+- **Key Updates**: Update outdated keys—for example, replace all instances of `old_api_key` with the new `new_api_key` value.
+- **Cleanup Unused Items**: Locate and remove unused fields or stale references (e.g., `oldFieldName`) from your YAML files to keep your project clean.
+:::
+
+:::info
+
+You can refactor the project only if you're on a [**paid plan**](https://www.flutterflow.io/pricing).
+
+:::
+
+To refactor a project, go to **Toolbar > Developer Menu > Refactor Project**. You’ll need to commit any unsaved changes before entering the refactor view. This opens your project in a YAML-based editor, where you can search, edit, and replace values across multiple files.
+
+You can also use **key reference** search by toggling the **key** icon—currently supported for data types, enums, pages, and components. Changes are color-coded: added lines appear in green, and removed lines appear in red. As you make changes, FlutterFlow provides inline YAML validation to help you catch and fix issues in real time.
+
+When you're done, click **Commit** to save the changes. After that, test your app to make sure all widgets, actions, and bindings still work as expected.
+
+:::tip
+You can exclude any item from the replacement by right-clicking on it and selecting **Dismiss**.
+:::
+
+
+
+
+
+
diff --git a/docs/resources/projects/settings/general-settings.md b/docs/resources/projects/settings/general-settings.md
index 62d5d7f4..1569444f 100644
--- a/docs/resources/projects/settings/general-settings.md
+++ b/docs/resources/projects/settings/general-settings.md
@@ -16,7 +16,7 @@ This section allows you to customize a wide range of settings that are crucial f
### Change Project, Package, and Display Name
-If you didn't decide on the app or package name when creating a new project, you might have entered a random name. From here, you can change the name anytime.
+Modify the app or package name of your project from this settings. You can also define different package names based on the development environment selected.
You can set a different name for the *App Store* and *Play Store* using the **Display Name**.
@@ -28,8 +28,9 @@ After changing the package name, errors may appear on the toolbar due to invalid
You can specify your app's **Entry Page** and **Logged In** **Page** from this section.
-- **Entry Page**: This is the home page for your app. If authentication is enabled, users who are not logged in will see this page, which is typically set to a login/signup or onboarding page.
-- **Logged In Page** (*available only if auth is enabled*): This page is displayed on the app start if a user is already logged in. Users are automatically navigated to the page you specify here on a successful sign-in attempt.
+- **Entry Page**: This serves as the home page for your app. When authentication is disabled, all users are directed to this page by default. If authentication is enabled, this page becomes the login, signup, or onboarding page for users who are not authenticated.
+- **Logged In Page** (*available only if auth is enabled*): This page is displayed when the app starts for authenticated users. If a user successfully signs in, they are automatically redirected to the page specified here. If the user is already authenticated, this page bypasses the Entry Page.
+
To set the page, simply choose the page that you want to use from the dropdown menu.
@@ -74,35 +75,27 @@ If you want the improved folder organization for your project, **Enable Updated
### Routing & Deep Linking
-From here, you can configure the global settings for navigation and deep link in your app [here](../../../ff-concepts/navigation-routing/deep-dynamic-linking.md).
+Configure the global settings for navigation and deep link in your app. To learn, how to set up deeplinks, check out the **[Deep & Dynamic Linking](../../../ff-concepts/navigation-routing/deep-dynamic-linking.md)** guide.
+### Display Settings
+
+The **Display Settings** section allows you to configure how text scales within your app. This is particularly helpful for accessibility, ensuring that users with visual impairments can comfortably read content.
+
+- **Min Text Scaling Factor**: Defines the minimum allowable scale for text. This prevents text from shrinking below a certain threshold, helping maintain legibility for all users. For example, setting this to `1` ensures text is never rendered smaller than its base size, regardless of device settings or user preferences.
+- **Max Text Scaling Factor**: Defines the maximum allowable scale for text. This limits how large text can appear, which is useful for preserving layout consistency on devices with accessibility text scaling enabled. For example, setting this to `10` allows text to scale up to 10× its original size.
+- **Persist Text Scaling Factor**: When enabled, the current text scaling factor will be stored and applied even after the app is restarted. This ensures a consistent user experience across sessions. **Note that** this setting requires both **Min** and **Max Text Scaling Factors** to be set. If either is unset, persistence will have no effect.
+
+:::info
+Once the text scaling factors are set, you can use the [**Update Text Scaling Factor**](../../../ff-concepts/localization-accessibility/accessibility.md#update-text-scaling-factor-action) action to let users dynamically adjust text size.
+:::
+
+
+Let’s understand this better with an example. Suppose the Min Text Scaling Factor is set to 1.0 and the Max Text Scaling Factor is set to 5.0. If a user's device requests a scaling factor of 2.5, FlutterFlow will accept it because it falls within the allowed range. So, if the base font size is 16.0, the final rendered size would be: `2.5 × 16.0 = 40.0`
+
+If a device requests a scaling factor higher than 5.0 (such as 6.0), it will be capped at 5.0. Thus, for a base font size of 16.0, the final rendered size will be: `5.0 × 16.0 = 80.0`.
+
+Similarly, if a device requests a scaling factor below 1.0 (for example, 0.5), it will be raised to 1.0 to ensure readability. The resulting font size would remain: `1.0 × 16.0 = 16.0`.
-If you prefer watching a video tutorial, here is the guide for you:
-
-
-
-
-
## App Assets
@@ -185,4 +178,4 @@ See the following resources for more information on Android adaptive icons.
- [Implementing Adaptive Icons](https://medium.com/google-developers/implementing-adaptive-icons-1e4d1795470e)
## Nav Bar & App Bar
-See how to configure the [Nav Bar](../../ui/pages/page-elements.md#enable-nav-bar-in-settings) and the [App Bar](../../ui/pages/page-elements.md#appbar).
\ No newline at end of file
+See how to configure the [Nav Bar](../../ui/pages/page-elements.md#enable-nav-bar-in-settings) and the [App Bar](../../ui/pages/page-elements.md#appbar).
diff --git a/docs/resources/projects/settings/imgs/pin-version.avif b/docs/resources/projects/settings/imgs/pin-version.avif
new file mode 100644
index 00000000..3981e8ca
Binary files /dev/null and b/docs/resources/projects/settings/imgs/pin-version.avif differ
diff --git a/docs/resources/projects/settings/imgs/see-pinned-project-in-dashboard.avif b/docs/resources/projects/settings/imgs/see-pinned-project-in-dashboard.avif
new file mode 100644
index 00000000..2a8b37b3
Binary files /dev/null and b/docs/resources/projects/settings/imgs/see-pinned-project-in-dashboard.avif differ
diff --git a/docs/resources/projects/settings/imgs/semantic-versioning.png b/docs/resources/projects/settings/imgs/semantic-versioning.png
new file mode 100644
index 00000000..5ff9464e
Binary files /dev/null and b/docs/resources/projects/settings/imgs/semantic-versioning.png differ
diff --git a/docs/resources/projects/settings/imgs/standard-to-stable.png b/docs/resources/projects/settings/imgs/standard-to-stable.png
new file mode 100644
index 00000000..4b9fb9fa
Binary files /dev/null and b/docs/resources/projects/settings/imgs/standard-to-stable.png differ
diff --git a/docs/resources/projects/settings/imgs/version-in-builder.png b/docs/resources/projects/settings/imgs/version-in-builder.png
new file mode 100644
index 00000000..befd1046
Binary files /dev/null and b/docs/resources/projects/settings/imgs/version-in-builder.png differ
diff --git a/docs/resources/projects/settings/project-apis.md b/docs/resources/projects/settings/project-apis.md
new file mode 100644
index 00000000..6bc759e5
--- /dev/null
+++ b/docs/resources/projects/settings/project-apis.md
@@ -0,0 +1,565 @@
+---
+slug: project-apis
+title: Project APIs
+tags: [APIs, Projects]
+keywords: [projects, apis, refactor code]
+sidebar_position: 5
+---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# Project API
+
+The FlutterFlow **Project APIs** allow you to programmatically read, write, and validate YAML configuration files through REST endpoints. Using these APIs, you can automate project management tasks, integrate continuous integration and delivery (CI/CD) workflows, and apply bulk configuration updates without manual interactions with the FlutterFlow user interface.
+
+:::warning
+
+The Project API is currently in beta and may undergo changes that could affect functionality or compatibility.
+
+:::
+
+:::info[Prerequisites]
+
+Before using the Project YAML API, make sure you have the following:
+
+- **HTTP Client**: Use a tool like `curl`, [**Postman**](https://www.postman.com/), or an HTTP library in your preferred programming language (e.g., `axios`, `requests`).
+- **Project Access**: You must have read access for GET/validation operations and an editor access for making updates to the project.
+- **Paid Plan**: You need a paid [**FlutterFlow subscription plan**](https://www.flutterflow.io/pricing).
+
+:::
+
+## YAML Overview
+
+### What are FlutterFlow Project YAMLs?
+
+YAML (YAML Ain't Markup Language) is a human-readable data serialization format commonly used for configuration files. In FlutterFlow, **Project YAMLs represent the complete structural definition of your app,** essentially exposing the full project schema that powers your FlutterFlow app.
+
+### What's Included in the Project Schema?
+
+FlutterFlow's YAML files contain a comprehensive representation of your entire project, including:
+
+- **UI Components & Pages**: Widget trees, page layouts, component hierarchies, and styling configurations.
+- **App Configuration**: Settings like app details, authentication methods, integrations (AdMob, Firebase, etc.)
+- **Data Structures**: Database collections, API schemas, app state variables, and custom data types.
+- **Business Logic**: Actions, functions, conditional logic, and workflow definitions.
+- **Assets & Resources**: Custom code files, image references, fonts, and other project assets.
+- **Project Organization**: Folder structures, component libraries, and project metadata.
+
+### YAML vs. FlutterFlow UI
+
+Every change you make in the FlutterFlow visual editor — from dragging a widget onto a page to configuring a database collection, is ultimately stored as structured data in these YAML files. The FlutterFlow UI provides an intuitive visual interface for editing this underlying schema, while the Project API gives you direct programmatic access to the same data.
+
+### File Structure
+
+FlutterFlow automatically partitions your project into logical YAML files for optimal performance and organization. Each file represents a specific aspect of your project (e.g., `app-state`, `ad-mob`, individual pages, collections, etc.), making it easy to target specific updates without affecting the entire project.
+
+## Base URL
+
+FlutterFlow provides different API endpoints for various environments. Use the appropriate base URL below depending on your needs:
+
+
+
+```jsx
+https://api.flutterflow.io/v2/
+```
+
+
+```jsx
+https://api.flutterflow.io/v2-staging/
+```
+
+
+
+**India**
+```jsx
+ https://api-enterprise-india.flutterflow.io/v2/
+```
+
+**APAC**
+```jsx
+https://api-enterprise-apac.flutterflow.io/v2/
+```
+
+**US Central**
+```jsx
+https://api-enterprise-us-central.flutterflow.io/v2/
+```
+
+**Europe**
+```jsx
+https://api-enterprise-europe.flutterflow.io/v2/
+```
+
+
+
+## Authentication
+
+All API endpoints require authentication using a Bearer token. You'll need to include your FlutterFlow API token in the Authorization header of each request. See [how to get the API Token](../../../accounts-billing/account-management.md#how-do-i-generate-an-api-token).
+
+```jsx
+Authorization: Bearer YOUR_API_TOKEN_HERE
+```
+
+## API Endpoints
+Below is a list of available API endpoints with their methods and usage descriptions.
+
+| Endpoint | Method | Purpose |
+| --------------------------- | ------ | --------------------------------------------- |
+| `/listPartitionedFileNames` | GET | List available YAML file names for a project. |
+| `/l/listProjects` | POST | Retrieve metadata for all projects. |
+| `/projectYamls` | GET | Export/download YAML files from a project. |
+| `/validateProjectYaml` | POST | Validate YAML content before applying changes. |
+| `/updateProjectByYaml` | POST | Update project configuration via YAML. |
+
+
+### List File Names
+
+Before you read or update project files, you need to know what YAML files are available. This endpoint returns a full list of file names associated with your FlutterFlow project.
+
+#### Endpoint
+`GET /listPartitionedFileNames`
+
+#### Query Parameters
+`projectId` (required): The ID of the FlutterFlow project
+
+#### Response
+```jsx
+{
+ "success":true,
+ "reason":null,
+ "value":{
+ "versionInfo": {
+ "partitionerVersion": 6,
+ "projectSchemaFingerprint": "abc123"
+ },
+ "fileNames": [
+ "folders",
+ "app-details",
+ "collections/id-yr7z6g5a",
+ "page/id-Scaffold_l9g6ilb6/page-widget-tree-outline/node/id-Column_174wuhc4",
+ "custom-file/id-MAIN/custom-file-code",
+ ...
+ ]
+ }
+}
+```
+
+The `fileNames` array lists out all the available YAML files. The `versionInfo` section provides metadata about the schema version and its unique fingerprint. If any part of `versionInfo` changes, it indicates that the API or the structure of the YAML responses has been updated.
+
+#### Example Usage
+```jsx
+curl -X GET \
+ 'https://api.flutterflow.io/v2/listPartitionedFileNames?projectId=your-project-id' \
+ -H 'Authorization: Bearer YOUR_API_TOKEN'
+```
+
+### List Projects
+
+This endpoint retrieves a list of FlutterFlow projects associated with your account, including detailed metadata such as project name, owner email, team info, collaboration settings, and versioning data.
+
+#### Endpoint
+
+`POST /l/listProjects`
+
+#### Request Body
+
+```jsx
+{
+ "project_type": "ALL",
+ "deserialize_response": true
+}
+```
+- **`project_type: "ALL"`**: Use "ALL" to include personal, team, and shared projects, or "TEAM_RESOURCE" to include only team-associated projects.
+
+- **`deserialize_response: true`**: Ensures the response is returned as human-readable JSON instead of a base64-encoded protobuf.
+
+:::tip
+It’s recommended to use the default options: `"ALL"` for `project_type` and `true` for `deserialize_response` for the most complete and readable results.
+:::
+
+#### Response
+
+Returns a JSON object containing an array of projects under the `entries` key. Each entry contains the project ID and rich metadata, including collaborators, app icons, sessions, and branching information.
+
+```jsx
+{
+ "success": true,
+ "reason": null,
+ "value": {
+ "entries": [
+ {
+ "id": "XXXXXXXXXXXXXXX",
+ "project": {
+ "name": "Sample Project A",
+ "ownerEmail": "user1@example.com",
+ "createdAt": "2024-08-08T11:01:12.427Z",
+ "updatedAt": "2024-08-08T11:01:18.669Z",
+ "teamRef": {
+ "path": "teams/TEAM_ID_1"
+ },
+ "mainBranchRef": {
+ "path": "projects/sample-project-id"
+ },
+ "numBranches": 2,
+ "otherMembers": {
+ "USER_XYZ": {
+ "email": "editor1@example.com",
+ "accessLevel": "EDITOR"
+ }
+ },
+ "activeSessions": {
+ "SESSION_ID_1": {
+ "lastSuccessfulUpdate": "2024-08-06T18:41:56.569Z"
+ }
+ },
+ "totalNumUpdates": 2177
+ }
+ }
+ ]
+ }
+}
+```
+
+#### Example Usage
+
+```jsx
+curl 'https://api.flutterflow.io/v2/l/listProjects' \
+ -H 'authorization: Bearer YOUR_API_TOKEN' \
+ --data-raw '{
+ "project_type": "ALL",
+ "deserialize_response": true
+ }'
+```
+
+### Download Project YAML
+
+You can download specific or all YAML configuration files from your FlutterFlow project. This helps in understanding the current structure of the file before modifying it.
+
+#### Endpoint
+`GET /projectYamls`
+
+#### Query Parameters
+- `projectId` (required): The ID of the FlutterFlow project
+- `fileName` (optional): Specific file to export (without extension). If not provided, all files are exported.
+
+#### Response
+Returns a zip file encoded as a base64 string. You will need to manually decode this base64 data into a downloadable .zip file. To do so, copy the value of `projectYamlBytes` and then you can use online tools such as [base64.guru](https://base64.guru/converter/decode/file) or [b64encode.com](https://b64encode.com/tools/base64-to-zip/) to convert and download the files.
+
+```jsx
+{
+ "success":true,
+ "reason":null,
+ "value":{
+ "versionInfo": {
+ "partitionerVersion": 6,
+ "projectSchemaFingerprint": "abc123"
+ },
+ "projectYamlBytes": "UEsDBAoAAAAAAKxV..."
+ }
+}
+```
+
+#### Example Usage
+```jsx
+# Export all YAML files
+curl -X GET \
+ 'https://api.flutterflow.io/v2/projectYamls?projectId=your-project-id' \
+ -H 'Authorization: Bearer YOUR_API_TOKEN'
+
+# Export specific file
+curl -X GET \
+ 'https://api.flutterflow.io/v2/projectYamls?projectId=your-project-id&fileName=ad-mob' \
+ -H 'Authorization: Bearer YOUR_API_TOKEN'
+```
+
+### Validate Project YAML
+
+You must validate the YAML content before applying changes to ensure it's properly formatted and contains valid values.
+
+#### Endpoint
+`POST /validateProjectYaml`
+
+#### Request Body
+```jsx
+{
+ "projectId": "your-project-id",
+ "fileKey": "ad-mob",
+ "fileContent": "showTestAds: false\nappId: \"your-app-id\""
+}
+```
+
+:::info
+
+- In the `fileContent` object, you must provide the **entire content** of the file.
+- The YAML content must be passed as a **single-line string** with correct formatting and appropriate escaping for new lines and indentation. For example, in the following `fileContent` object, you see the actual multiline YAML content, which is not allowed ❌.
+
+ ```jsx
+ {
+ "projectId": "ecommerce-flow-app-ie7nl6",
+ "fileKey": "app-state",
+ "fileContent": "fields:
+ - parameter:
+ identifier:
+ name: myAppState
+ key: hg7j8z0y
+ dataType:
+ scalarType: String
+ description: "Stores the current user session state"
+ persisted: false"
+ }
+ ```
+
+ Now, here’s how the YAML content should be passed (i.e., as single line string ✅).
+
+ ```jsx
+ {
+ "projectId": "ecommerce-flow-app-ie7nl6",
+ "fileKey": "app-state",
+ "fileContent": "fields:\n - parameter:\n identifier:\n name: myAppState\n key: hg7j8z0y\n dataType:\n scalarType: String\n description: \"Stores the current user session state\"\n persisted: false"
+ }
+ ```
+
+:::
+
+#### Response
+- **Success (200):** YAML is valid - `{"success": true, "reason": null, "value": ""}`
+- **Error with validation details:**
+ ```jsx
+ {
+ "validationErrors": [
+ {
+ "message": "Expected bool value",
+ "fileKey": "ad-mob",
+ "yamlLocation": {
+ "line": 1,
+ "column": 15
+ }
+ }
+ ]
+ }
+ ```
+
+#### Example Usage
+```jsx
+curl -X POST \
+ 'https://api.flutterflow.io/v2/validateProjectYaml' \
+ -H 'Authorization: Bearer YOUR_API_KEY' \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "projectId": "your-project-id",
+ "fileKey": "ad-mob",
+ "fileContent": "showTestAds: false"
+ }'
+```
+
+
+### Update Project YAML
+
+This endpoint allows you to overwrite existing files in your FlutterFlow project by submitting updated YAML content.
+
+#### Endpoint
+`POST /updateProjectByYaml`
+
+#### Request Body
+```jsx
+{
+ "projectId": "your-project-id",
+ "fileKeyToContent": {
+ "ad-mob": "showTestAds: false",
+ }
+}
+```
+:::info
+- In the `fileKeyToContent` object, you must provide the **entire content** of the file.
+- The YAML content must be passed as a **single-line string** with correct formatting and appropriate escaping for newlines and indentation. For example, in the following `fileKeyToContent` object, you see the actual multiline YAML content, which is not allowed ❌.
+
+ ```jsx
+ {
+ "projectId": "ecommerce-flow-app-ie7nl6",
+ "fileKeyToContent": {
+ "app-state": "fields:
+ - parameter:
+ identifier:
+ name: myAppState
+ key: hg7j8z0y
+ dataType:
+ scalarType: String
+ description: "Stores the current user session state"
+ persisted: false"
+ }
+ }
+ ```
+ Now, here’s how the YAML content should be passed (i.e., as single line string ✅).
+ ```jsx
+ {
+ "projectId": "ecommerce-flow-app-ie7nl6",
+ "fileKeyToContent": {
+ "app-state": "fields:\n - parameter:\n identifier:\n name: myAppState\n key: hg7j8z0y\n dataType:\n scalarType: String\n description: \"Stores the current user session state\"\n persisted: false"
+ }
+ }
+ ```
+
+:::
+
+#### Response
+- **Success (200):** `{"success": true, "reason": null, "value": ""}`
+- **Error (400):** Validation errors or malformed request.
+- **Error (403):** Insufficient permissions or project locked.
+- **Error (404):** Project or user not found.
+
+#### Example Usage
+
+This example updates the `ad-mob` file and adds/updates app state variables.
+
+```jsx
+curl -X POST \
+ 'https://api.flutterflow.io/v2/updateProjectByYaml' \
+ -H 'Authorization: Bearer YOUR_API_TOKEN' \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "projectId": "your-project-id",
+ "fileKeyToContent": {
+ "ad-mob": "showTestAds: false",
+ "app-state": "fields:\n - parameter:\n identifier:\n name: myAppState\n key: hg7j8z0y\n dataType:\n scalarType: String\n description: \"Stores the current user session state\"\n persisted: false\n - parameter:\n identifier:\n name: userPreferences\n key: abc123xy\n dataType:\n scalarType: JSON\n description: \"User settings and preferences\"\n persisted: true"
+ }
+ }'
+```
+## API Usage Example
+
+Let’s walk through a practical example of updating an app state variable using the Project APIs.
+
+:::info
+You can download and use Postman Collection to quickly test all FlutterFlow Project APIs with pre-filled headers, parameters, and sample requests.
+:::
+
+
+
+First, we use the `/listPartitionedFileNames` endpoint to check if the `app-state` file exists in the project. Once confirmed, we call the `/projectYamls` endpoint to download the YAML file. The API returns a base64-encoded string representing a zip file, which we decode and download using tools like [Base64 to ZIP](https://b64encode.com/tools/base64-to-zip/).
+
+
+
+
+
+
+
+Next, we open the `app-state.yaml` file and update the `enableDarkMode` variable by setting its `persisted` value to `true`. We then convert the updated YAML into a properly escaped single line string and validate it using the `/validateProjectYaml` endpoint. If validation succeeds, we send the final update using the `/updateProjectByYaml` endpoint.
+
+
+
+
+
+
+
+
+## Error Handling
+This section outlines how the API handles errors, including common HTTP response codes and detailed validation feedback for YAML processing issues.
+
+### Common Error Responses
+This table outlines the most common HTTP status codes and their meanings, helping you identify and resolve API issues more effectively.
+
+| Status Code | Description | Example Response |
+| ----------- | -------------------------------------------- | -------------------------------------------------------- |
+| 400 | Bad Request - Invalid JSON or malformed YAML | `"Failed to update project: ad-mob:Expected bool value"` |
+| 403 | Forbidden - Insufficient permissions | `"You do not have write access to this project"` |
+| 404 | Not Found - Project or user doesn't exist | `"Project not found"` |
+| 500 | Internal Server Error | `"Unknown error"` |
+
+### Validation Errors
+When YAML validation fails, you'll receive detailed error information:
+
+```jsx
+{
+ "validationErrors": [
+ {
+ "message": "Unknown field name 'showTestAdsasssdaf'",
+ "fileKey": "ad-mob",
+ "yamlLocation": {
+ "line": 1,
+ "column": 1
+ }
+ }
+ ]
+}
+```
+
+
+## Best Practices
+
+- **Always Validate First**: Before updating project YAMLs, use the validation endpoint to ensure your changes are valid:
+
+ ```jsx
+ # 1. Validate the YAML
+ curl -X POST 'https://api.flutterflow.io/v2/validateProjectYaml' \
+ -H 'Authorization: Bearer YOUR_API_KEY' \
+ -H 'Content-Type: application/json' \
+ -d '{"projectId": "project-id", "fileKey": "ad-mob", "fileContent": "showTestAds: false"}'
+
+ # 2. If validation passes, apply the changes
+ curl -X POST 'https://api.flutterflow.io/v2/updateProjectByYaml' \
+ -H 'Authorization: Bearer YOUR_API_KEY' \
+ -H 'Content-Type: application/json' \
+ -d '{"projectId": "project-id", "fileKeyToContent": {"ad-mob": "showTestAds: false"}}'
+ ```
+
+
+- **Handle Project Locks**: Projects may be temporarily locked during other operations. If you receive a 403 error mentioning `Project is locked due to ongoing changes. Please try again later.`, wait and retry.
+
+- **Batch Updates**: You can update multiple files in a single request by including multiple entries in `fileKeyToContent`:
+
+ ```jsx
+ {
+ "projectId": "your-project-id",
+ "fileKeyToContent": {
+ "ad-mob": "showTestAds: false",
+ "app-settings": "appName: \"Updated Name\"",
+ "authentication": "enableEmailAuth: true"
+ }
+ }
+ ```
+
+
+## Rate Limits
+
+Please be mindful of API rate limits. If you're making many requests, implement appropriate delays between calls to avoid being rate-limited.
+
+
diff --git a/docs/resources/projects/settings/project-setup.md b/docs/resources/projects/settings/project-setup.md
index ad058c4d..10357d00 100644
--- a/docs/resources/projects/settings/project-setup.md
+++ b/docs/resources/projects/settings/project-setup.md
@@ -4,7 +4,7 @@ title: Project Setup
tags: [Setup, Permissions, Multiple Languages]
keywords: [permission message, enabling platforms, support multiple languages, adding custom permissions, walkthrough, development environments]
description: Learn how to setup your project in FlutterFlow.
-sidebar_position: 0
+sidebar_position: 1
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
@@ -98,7 +98,7 @@ This action is helpful when you add a custom widget or action that accesses the
:::info
- Request permission only works on a mobile platform.
-- There won't be any dialog shown for the *Bluetooth* and *Notifications* permissions.
+- There won't be any dialog shown for the *Bluetooth* permission.
:::
diff --git a/docs/resources/projects/settings/version-management.md b/docs/resources/projects/settings/version-management.md
new file mode 100644
index 00000000..33fe13fa
--- /dev/null
+++ b/docs/resources/projects/settings/version-management.md
@@ -0,0 +1,195 @@
+---
+slug: flutterflow-version-management
+title: Pin to FlutterFlow Version
+tags: [Versioning]
+keywords: [Versioning, FlutterFlow Version Management, Pin project FlutterFlow, Downgrade FlutterFlow version, Upgrade FlutterFlow version, FlutterFlow stable releases]
+description: Learn how to manage the FlutterFlow version used for your project.
+sidebar_position: 2
+---
+
+# Pinning Projects to Stable FlutterFlow Versions
+
+FlutterFlow is constantly evolving to provide new features, address bugs, and keep up-to-date with Flutter and third-party packages. However, frequent updates can introduce unwanted changes that break existing projects—especially those that rely on custom code with external dependencies.
+
+To mitigate these issues, FlutterFlow offers a **version management** system that allows you to pin your project to a particular [*stable release*](#stable-release) of FlutterFlow. Projects pinned to a stable release will **not automatically receive the latest FlutterFlow updates**, giving you more control over your development workflow.
+
+However, pinning to a stable release means that you will not be able to use the latest features, and there may be bugs that are not fixed until subsequent releases. **We only recommend doing this if you have a complex app with custom code dependencies.**
+
+:::info
+Currently, the ability to pin a FlutterFlow project to a stable version is only available to **Enterprise** users.
+:::
+
+## When should you pin your project to a stable version?
+
+Pinning your project to a stable version of FlutterFlow offers the following benefits:
+
+- **Prevents Unexpected Breakages:** FlutterFlow updates can introduce errors into your project—particularly when you have custom code. Pinning to a stable release reduces the risk of unexpected changes to your project.
+- **Gives Control Over Update Timing:** FlutterFlow updates might occur at inopportune times (e.g. right before you plan to release a new version of your application). Pinning your project to a stable version allows you to choose **when** to move your project to a newer release.
+
+
+## Key Concepts
+
+To understand FlutterFlow's version management system, it's important to understand **Semantic Versioning**.
+
+FlutterFlow tends to release a new version of the product each week. When a new version is released, the overall version number is incremented.
+
+The version number consists of three parts:
+
+- **Major Version:** Incremented when introducing substantial changes that significantly alter the product.
+- **Minor Version:** Incremented for changes that notably enhance or modify the FlutterFlow development experience—such as upgrading to a new Flutter version, making substantial modifications to generated code or project structure, or introducing major new features.
+- **Patch Version:** Incremented with routine releases that include bug fixes and minor improvements, ensuring stability without introducing breaking changes to the generated code or project structure.
+
+
+
+You can see what version of FlutterFlow you are using by looking at the top left hand corner of the builder.
+
+
+
+
+#### Standard Release
+
+A **Standard Release** of FlutterFlow is released approximately every week. However, this is subject to change based on user needs.
+
+When your project is **not pinned** to a stable release (default behavior), you will automatically use the **latest standard release.**
+
+#### Stable Release
+
+A **Stable Release** of FlutterFlow is published monthly if any of the following conditions are met:
+
+- Significant changes have been made to project code generation.
+- The underlying Flutter version or Pubspec dependencies in generated projects have been updated.
+- Updates affecting the project structure have been introduced (e.g., the addition of a new widget type).
+
+Each stable release is assigned a unique **Major.Minor** version number. Projects that have not been edited in a FlutterFlow version with a **Major.Minor** version higher than the stable release can be pinned to that stable version.
+
+:::note
+Each stable release will be supported for **6 months** before you are forced to upgrade to the next stable version.
+:::
+
+
+## Pinning Your Project
+
+To pin your project, navigate to **Settings and Integrations > General > App Details >Version Pinning** section and select the stable release you want to lock into.
+
+
+
+
+### Modifying the Pinned Version
+
+You have several options when it comes to modifying pinned version of your project:
+
+- **Upgrade to more recent Stable Version**: When a new stable version is released, you will see it as an option in the dropdown shown above. You can upgrade the pinned version to a more recent stable version whenever it becomes available. Newer stable versions will have higher numbers (i.e., 5.1 is newer than 5.0)
+- **Set to *Latest Version* (Unpinned):** You can unpin your project by setting it to the *Latest Version* which will use the latest [standard release](#standard-release).
+- **Opt-in to the *Next Stable*:** Your project may be on a standard version that does not have a corresponding stable version (i.e., you are on 5.0.1 but the 5.0 stable will correspond to 5.0.4). In that case, you can choose to opt-in to the *Next Stable Version*. If it is already available, it will be pinned to that version immediately.
+
+:::warning[Pinning and Unpinning Cannot Be Reversed]
+Once you unpin a project or pin it to a later version, this action cannot be undone. If you're unsure whether a newer FlutterFlow version will be compatible with your project, we recommend creating a new branch and updating the pinned version within that branch first. This allows you to preview changes before applying them to your main project.
+:::
+
+### Accessing the Proper Stable Version
+As mentioned above, once you update your project to a stable version, you can only edit the project using that version of FlutterFlow.
+
+- **For Web**: You will be automatically redirected to the URL for the stable version that your project is pinned to when you open a project from the FlutterFlow dashboard (i.e., navigating to app.flutterflow.io or enterprise-[region].flutterflow.io).
+- **For Desktop**: You will [**install**](https://www.flutterflow.io/desktop) the dedicated desktop application for the pinned stable release. The desktop app for stable releases won’t auto-update, you will need to install a new version when you upgrade your project to a new stable version.
+
+
+## Recommended FlutterFlow Version Workflow
+
+If you have a complex app with custom code that depends on specific versions of package dependencies, it may be helpful to pin your project to a specific version. This is the workflow we recommend for managing the version of your projects.
+
+1. If you think your project should be pinned to a stable release, choose to [pin a currently available stable version (if any)](#modifying-the-pinned-version).
+2. When a new stable version is released, you can choose when you would like to upgrade based on your own release schedule and development process. For instance, you might wait until you're not actively developing a new feature, or you could check the release notes first to see if there are must-have features that would prompt you to upgrade sooner.
+3. When you’re ready to upgrade, commit all your changes on main to save your progress. Create a new branch from the main branch, [update the pinned version](#modifying-the-pinned-version), and test all functionalities to ensure compatibility. If any modifications are needed, make those changes in the new branch.
+4. Run your app on the platforms you support—using a simulator, emulator, or physical device to ensure everything works as intended. See the [Local Run documentation](https://docs.flutterflow.io/testing/local-run/) for details.
+5. If everything looks good, you can merge the new branch into the main branch. However, to merge branches successfully, ensure that both the main branch and the new branch are pinned to the same FlutterFlow version! If for some reason your app is not working as expected, you can choose to leave or close the branch until you are ready to make the modifications needed to support the latest FlutterFlow version (i.e. upgrade dependencies/custom code).
+
+:::tip
+See the video [**here**](https://youtu.be/8Y1uyCC_dXE) for guidance on updating [**dependencies**](../../../ff-concepts/adding-customization/custom-code.md#manage-dependencies).
+:::
+
+## Version Management with Libraries
+
+[Libraries](../libraries.md) have their own versions. Like projects, libraries edited in FlutterFlow can only be used in FlutterFlow versions greater than or equal to the version it was last edited in.
+
+To ensure that new versions of libraries used in a pinned project are compatible with a pinned project, we recommend pinning all libraries used in a pinned project to the same (or lower) Flutterflow version as the pinned project.
+
+Library projects can also be pinned to a specific version, ensuring that all library versions use that FlutterFlow release until the pinned version is changed.
+
+:::info
+- Pinned projects cannot add a library with the version set to 'current' or to a library version that has been edited on a later release of FlutterFlow.
+
+- Projects cannot be pinned if they contain a library with the version set to 'current' or to a library version that has been edited on a later release of FlutterFlow.
+:::
+
+:::tip
+When you import a library into a project or another library, the library’s version must be lower than or equal to the version used for the project it’s being imported into; otherwise, you will encounter an error.
+:::
+
+## FAQs
+
+
+
+Can I edit my project in multiple versions of FlutterFlow?
+
+
+No. If your project is not pinned to a specific version, you’ll always use the latest FlutterFlow release. If your project is pinned to a specific version of FlutterFlow, you will be prompted to edit the project in that version.
+
+
+
+
+
+How often are new stable versions released?
+
+
+We aim to release new stable versions of FlutterFlow approximately once a month.
+
+
+
+
+
+How can I see what's included in a new stable version?
+
+
+We’re currently working on displaying release notes directly in the product, so you can easily review what’s been added or changed in each new stable version.
+
+
+
+
+
+What if there are bugs in the FlutterFlow version I’m using?
+
+
+If critical bugs arise, we may provide hotfixes or patches for older FlutterFlow versions. However, some fixes depend on updating the underlying Flutter framework or related dependencies, which isn’t always feasible for older versions. This is a risk of staying on an older version of FlutterFlow as opposed to always using the latest.
+
+
+
+
+
+
+Can I change the pinned version to be different for various branches in my project?
+
+
+Yes, you can pin different versions for different branches. We recommend first creating a new branch, updating it to a later version, making any necessary changes, and verifying that everything works as expected before merging it into your main branch.
+
+However, to merge branches successfully, ensure that both the main branch and the new branch are pinned to the same FlutterFlow version.
+
+
+
+
+
+
+What happens if there is no stable version available for me to pin my project to?
+
+
+If your project was created and edited on a [standard release](#standard-release) that does not correspond to a [stable version](#stable-release), you may not see a stable version available. Instead, you can choose to opt-in to the [*next stable release*](#pinning-your-project). If set to the next stable release, a project will immediately be pinned when opened when a new stable release becomes available.
+
+
+
+
+
+What is the recommended approach if I have multiple projects and libraries that I am working on?
+
+
+If you choose to pin your project to a stable version of FlutterFlow, we recommend pinning all your projects and dependencies to the same version - and trying to upgrade all projects to the next version around the same time. This makes it easier to ensure compatibilities between projects and libraries that depend on each other. Additionally, this makes it easier to have a single FlutterFlow desktop environment that you are working within.
+
+
diff --git a/docs/resources/style-guide.md b/docs/resources/style-guide.md
new file mode 100644
index 00000000..ce9d9e33
--- /dev/null
+++ b/docs/resources/style-guide.md
@@ -0,0 +1,145 @@
+---
+slug: /resources/style-guide
+title: Naming Variables & Functions
+description: Naming conventions for FlutterFlow, including guidelines for widgets, components, state variables, constants, and more.
+tags: [Style Guide, Variables]
+keywords: [Style Guide, Variables]
+---
+
+# Naming Variables & Functions
+
+To make your code more maintainable, readable, and consistent, it’s essential to adopt clear naming conventions for variables, functions, and components.
+
+Best practices for naming conventions in app development (especially for projects using Flutter), aim to improve code readability, maintainability, and consistency across the application. Here are some general guidelines tailored for different aspects of a Flutter project:
+
+Various naming styles (as suggested by [Dart Effective Style Guide](https://dart.dev/effective-dart/style#identifiers)):
+
+- **UpperCamelCase** (also known as PascalCase) names capitalize the first letter of each word, including the first.
+
+- **lowerCamelCase** (also known as camelCase) names capitalize the first letter of each word, except the first which is always lowercase, even if it's an acronym.
+
+- **lowercase_with_underscores** (also known as snake_case) names use only lowercase letters, even for acronyms, and separate words with _.
+
+
+
+**General Principles**
+- **Be Consistent:** Whatever conventions you choose, apply them consistently across the project.
+- **Be Descriptive:** Names should be self-explanatory, reducing the need for additional comments to explain what a variable, function, or class does.
+- **Avoid Abbreviations:** Unless it's a well-known abbreviation, spell out words to avoid confusion.
+
+
+## Variable Naming Convention
+This section outlines naming conventions for pages, components, state variables, custom data types, enums, and constants to ensure clarity and consistency throughout the project.
+
+
+### Pages & Components
+Use **UpperCamelCase** for all widgets, components, pages, and screen names to maintain consistency and readability. FlutterFlow ensures clarity by automatically adding "Widget" to widget names when generating code. For components, you can suffix the name with "Component" to clearly distinguish them.
+
+Similarly, for pages and screens, include "Page" or "Screen" in the name to indicate their purpose. This approach aligns with Dart conventions for class names and ensures a well-organized project structure.
+
+
+
+:::tip[Do's]
+- **Use UpperCamelCase for Names:** Always use **UpperCamelCase** for widgets, components, pages, and screens. Examples: `CustomButton`, `UserProfilePage`, `MainViewComponent`.
+
+- **Include "Screen" or "Page" in Page Names:** Use "Screen" or "Page" in file names to identify UI screens or pages. Examples: `LoginScreen`, `SettingsPage`.
+
+- **Use Prefixes for Clarity When Necessary:** Add a prefix if it significantly improves clarity or prevents naming conflicts. Example: `AdminUserProfile` (to differentiate it from `CustomerUserProfile` or `UserProfile`).
+
+- **Be Descriptive and Clear in File Names:** Ensure names are descriptive enough to convey their purpose at a glance. Examples: `OrderConfirmationScreen`, `ProductDetailsPage`.
+:::
+
+:::danger[Don'ts]
+- **Don’t Use Unnecessary Prefixes:** Avoid prefixes that do not add clarity or are redundant. Bad Example: `AppPrimaryButton` (if `PrimaryButton` is sufficient).
+
+- **Don’t Add "Widget" Explicitly:** Avoid adding "Widget" to class or component names manually, as FlutterFlow already appends it during code generation. Bad Examples: `ButtonWidget`, `ProfileCardWidget`.
+
+- **Don’t Use LowerCamelCase for Class Names:** Reserve **lowerCamelCase** for variables and methods, not for components, or pages. Bad Examples: `loginButton`, `userProfile`.
+
+- **Don’t Mix Naming Conventions:** Maintain consistency with UpperCamelCase for all widgets, components, pages, and screens. Bad Examples: `userLogin`, `Profilecard`, `headerView`.
+
+- **Don’t Use Generic Names Without Purpose:** Avoid overly generic names that do not clearly convey the file’s intent. Bad Examples: `Main`, `View`, `Screen1`.
+
+:::
+
+
+Note that the style guidelines for Pages and Components also apply to **[Custom Widgets](../ff-concepts/adding-customization/custom-widgets.md)**, as Pages and Components created in FlutterFlow are internally generated as widgets.
+
+
+### Custom Data Types & Enums
+
+When naming custom data types and enums, use **UpperCamelCase** for consistency and clarity. Ensure that names are descriptive, providing a clear representation of the entity or purpose.
+
+
+
+:::tip[Do's]
+
+- **Use UpperCamelCase for Custom Data Types:** Name your custom data types using **UpperCamelCase**. Ensure that names are clear, concise, and descriptive, reflecting the entity they represent. Good Examples: `UserModel`, `ProductDetails`, `OrderItem`.
+
+- **Use consistent naming for Enum Names and Values:** Use **UpperCamelCase** for the enum name such as, `Status`, `ConnectionState`, `UserRole` and **lowerCamelCase** for its values e.g., `{active, inactive, pending}`. This approach aligns with Dart's enum naming guidelines and ensures consistency.
+
+- **Use Plural Names for Lists:** If the data type represents a List, use a plural name to clarify its purpose. Good Example: `OrderItems` (to represent multiple `OrderItem` objects).
+:::
+
+:::danger[Don'ts]
+
+- **Don’t Use All Lowercase or Mixed Case for Custom Data Types:** Avoid using all lowercase or inconsistent casing in data model class names, as it reduces readability. Bad Example: `usermodel`, `product_details`.
+
+- **Don’t Use Vague or Non-Descriptive Names**: Avoid using generic or unclear names that do not clearly describe the data entity. Bad Example: `DataModel`, `Entity`, `Item`.
+
+- **Don’t Mix Naming Conventions for Enums:** Maintain consistent capitalization between enum names and their values. Bad Example: `enum UserRole { Admin, EDITOR, viewer }`
+:::
+
+For datatype fields, we use the same convention as [State variables](#variables).
+
+### Constants
+
+Flutter prefers using a lowercase `k` prefix for constants to indicate their immutability, especially for project-specific constants. This approach is more concise and aligns with Dart's common practices. Use **SCREAMING_SNAKE_CASE** only when contributing to global or legacy projects where it is already in use.
+
+:::tip[Do's]
+- **Start Constants with a k Prefix:** Always use a lowercase `k` followed by **UpperCamelCase** for constants in FlutterFlow projects.
+- **Use Descriptive and Contextual Names:** Clearly describe the purpose of the constant. Avoid using abbreviations unless they are widely understood. Examples: `kDefaultPadding`, `kMaxUploadSizeMb`
+:::
+
+:::danger[Don'ts]
+- **Don’t Omit the k Prefix for Constants:** Avoid using plain names for constants in a Flutter-specific project, as they might conflict with variables or methods. Bad Examples: `padding`, `uploadSize`.
+- **Don’t Use Vague or Generic Names:** Avoid using names that fail to describe the purpose of the constant. Bad Examples: `VALUE`, `DATA`, `X`, `Y`.
+:::
+
+### Variables
+
+State variable & Data Type field names follow the **lowerCamelCase** naming style to align with Dart's conventions.
+
+:::tip[Do's]
+- **Be Descriptive and Clear:** Use variable names that clearly describe their purpose, avoiding generic or vague terms. Examples: `isFormValid`, `errorMessage`, `availableProducts`.
+- **Prefix Boolean Variables with `is`, `has`, or `should`:** For readability, use prefixes that denote the variable's purpose when naming Boolean values. Examples: `isActive`, `hasErrors`, `shouldReload`.
+- **Use Consistent Prefixes to denote state:** When managing UI or asynchronous state, use prefixes like `current`, `selected`, or `pending` for better context. Examples: `currentTabIndex`, `selectedUserId`, `pendingAction`.
+:::
+
+:::danger[Don'ts]
+- **Don’t Use Abbreviations or Single Letters:** Avoid abbreviations or single-character names that obscure the variable's intent. Bad Examples: `usrNm`, `f`, `cnt`.
+- **Don’t Use Generic Names:** Avoid using generic terms that do not convey the variable’s purpose. Bad Examples: `data`, `value`, `temp`.
+- **Don’t Start Variables with Uppercase:** Follow Dart conventions by starting variable names with lowercase. Bad Examples: `UserName`, `IsLoading`.
+:::
+
+## Function Naming Convention
+This section defines naming conventions for custom functions, actions, and action blocks to maintain consistency, readability, and ease of understanding across the codebase.
+
+### Custom Functions & Actions
+
+Custom functions and custom actions created in the Custom Code tab of FlutterFlow should follow the **lowerCamelCase** naming convention. These typically reflect an action or behavior.
+
+
+
+:::tip[Do's]
+- **Be descriptive and concise:** Use clear, meaningful names that describe the action or purpose of the function (e.g., `validateForm` instead of `doCheck`, or `fetchUserData` instead of `userData`).
+- **Use action-oriented names:** Start with verbs to indicate behavior (e.g., `submitForm`, `processPayment`).
+:::
+
+:::danger[Dont's]
+- **Avoid using underscores or spaces:** Names like `fetch_user_data` do not align with **lowerCamelCase** conventions.
+- **Avoid redundant prefixes or suffixes:** There’s no need to prefix with `custom` or suffix with `Func` unless absolutely necessary for clarity (e.g., `customSubmitFormFunc` is redundant).
+- **Don’t use overly generic names:** Avoid vague terms like `doSomething` or `functionOne`, which don’t provide context.
+:::
+
+Note that **[Action Blocks](../resources/control-flow/functions/action-blocks.md)** should follow the same naming convention as custom actions, as they are both technically Dart functions internally in the generated code.
diff --git a/docs/resources/ui/components/component-lifecycle.md b/docs/resources/ui/components/component-lifecycle.md
index 585eec0c..168b8f3d 100644
--- a/docs/resources/ui/components/component-lifecycle.md
+++ b/docs/resources/ui/components/component-lifecycle.md
@@ -217,7 +217,7 @@ call the **Update Component State** action to toggle the value of `isFavourite`.
width: '100%'
}}>
-## Convert into a component
+## Convert into a Component
If you have already built a complex widget in your page, you can convert that entire widget into a component and reuse it throughout your app.
@@ -76,7 +76,7 @@ entire widget tree you want to convert, then select **Convert to Component.**
-## Creating a component from a popular template
+## Creating a Component from a Popular Template
FlutterFlow offers multiple popular templates for components across various use cases that you can
apply to your project in seconds, saving you a lot of time.
@@ -107,12 +107,60 @@ apply to your project in seconds, saving you a lot of time.
-## Create an AI generated component
+## Create an AI Generated Component
-FlutterFlow's **AI Gen** feature allows you to generate various elements,
-including components, from a prompt. This can be particularly useful when you're
-unsure where to start. Once the component is generated, you can preview it with different color
-schemes, in both light and dark themes, and make modifications as desired.
+You can quickly create a component using FlutterFlow AI by describing what you want in natural language. The AI uses your description or visual reference, along with your project context, to build the component.
+
+To create and add an AI-generated component, open the **Widget Tree**, click **Generate with AI** (magic wand) button and select the **Component** tab. Next, describe the component you want to build, and hit the **Send** (up arrow) button.
+
+FlutterFlow will process your request and display progress in the **AI Generation History** panel in the toolbar. Once the component is ready, you can preview it in both light and dark themes and apply various color schemes. If you're happy with the result, give it a name and add it to your project.
+
+:::tip
+
+- You can also upload a screenshot or image of the component you want to build. FlutterFlow AI will use it as a reference to generate the layout.
+- While the AI is generating your component, you can continue working on other tasks within FlutterFlow, but make sure you don’t close the FlutterFlow app.
+
+:::
+
+
+
+
+
+
+#### Import from Figma Frame
+
+You can also quickly turn your Figma designs into functional components in FlutterFlow. By providing a Figma Frame URL, FlutterFlow AI will analyze the design and automatically generate UI layouts that closely match your mockup.
+
+To import from a Figma Frame, first, connect your Figma account, [import the Figma theme](../../../ff-concepts/design-system/design-system.md#import-figma-theme), and map your colors and typography accordingly. Next, open the **Generate with AI** dialog and click the **Plus (+)** button. Select **Import from Figma**, enter your **Figma frame URL**, and press **Send**.
+
+A preview of the frame you are importing will appear. To finalize the import, click **Send** again. Once completed, the component will appear in the AI Generation History, where you can preview and add it to your project.
+
+:::warning
+
+Currently, we don't support importing SVG elements from Figma frames. However, you can manually add the SVGs directly to your project [**assets**](../../../generated-code/directory-structure.md#assets) after generation is complete, or replace them in Figma with supported image formats like PNG or JPEG.
+
+:::
diff --git a/docs/resources/ui/overview.md b/docs/resources/ui/overview.md
index ad52a542..afe433bd 100644
--- a/docs/resources/ui/overview.md
+++ b/docs/resources/ui/overview.md
@@ -46,10 +46,10 @@ Now let's apply the above concepts to what we see in FlutterFlow as we create ou
In FlutterFlow projects, a **Page** is essentially a new section or feature of your app that combines
various UI elements to form a complete screen in the app. When you create a new project in
-FlutterFLow, an empty page called `HomePage` is the first thing you see on your canvas.
+FlutterFlow, an empty page called `HomePage` is the first thing you see on your canvas.
How you define your pages defines the flow of the app and user experience for the user. For
-example, in our [**E-commerce Demo app**](https://bit.ly/ff-docs-demo-v1), after login, the user lands on `ProductListPage` which has a
+example, in our [**E-commerce Demo app**](https://bit.ly/ff-docs-demo-v2), after login, the user lands on `ProductListPage` which has a
NavigationBar at the bottom that takes the user to different Pages in the app such as
`ProfilePage`, etc.
@@ -98,7 +98,7 @@ you're creating an **instance** of the `Icon` widget class and providing differe
each use.
Think of classes as templates that outline the structure and features of
-something you want to create multiple times. For instance, in our demo app [EcommerceFlow](https://bit.ly/ff-docs-demo-v1), we
+something you want to create multiple times. For instance, in our demo app [EcommerceFlow](https://bit.ly/ff-docs-demo-v2), we
have a reusable component called `ProductListCard` with specific characteristics such as image,
product information text, and actions it should perform when clicked. Here, we've essentially
created a **class**.
diff --git a/docs/resources/ui/pages/imgs/route-settings-configs.png b/docs/resources/ui/pages/imgs/route-settings-configs.png
new file mode 100644
index 00000000..a6706c57
Binary files /dev/null and b/docs/resources/ui/pages/imgs/route-settings-configs.png differ
diff --git a/docs/resources/ui/pages/intro-pages.md b/docs/resources/ui/pages/intro-pages.md
index 4b47a7bf..b63f569d 100644
--- a/docs/resources/ui/pages/intro-pages.md
+++ b/docs/resources/ui/pages/intro-pages.md
@@ -28,16 +28,16 @@ Whether you're starting from scratch, using a template, or leveraging AI tools,
there are several pathways to achieve the desired functionality and aesthetic of your desired Page.
:::tip[Generated Code]
-When you create a page in FlutterFlow, a `Widget` class and a corresponding `Model` class are automatically generated. You can view these in the Code Viewer. To explore the details of the generated `Model` class, take a closer [**look at the code**](../../../generated-code/page-model.md).
+When you create a page in FlutterFlow, a `Widget` class and a corresponding `Model` class are automatically generated. You can view these in the Code Viewer. To explore the details of the generated `Model` class, take a closer [**look at the code**](../../../generated-code/pages-generated-code.md).
:::
FlutterFlow allows you to easily create new pages using the **Add Page, Component, or Flow** button,
-which is available from the **Page Selector** tab in the **Navgation Menu**. This will help you
+which is available from the **Page Selector** tab in the **Navigation Menu**. This will help you
quickly start and add new pages to your app.
-### Create an empty page
+### Create an Empty Page
When creating your page in FlutterFlow, one option is to start with an empty page, providing you
with a blank canvas. This approach allows you to build your UI from the ground up by composing
@@ -48,7 +48,7 @@ To create an empty FlutterFlow Page from scratch, follow the steps:
-### Create a page from a popular template
+### Create a Page from a Popular Template
FlutterFlow simplifies the process of page creation by offering a variety of
popular template use cases. These templates provide a basic structure for your
@@ -82,14 +82,20 @@ To utilize a template from FlutterFlow, follow these steps:
-### Create an AI generated page
+### Create an AI Generated Page
-FlutterFlow's **AI Gen** feature allows you to generate various elements,
-including pages, from a prompt. This can be particularly useful when you're
-unsure where to start. Once the page is generated, you can preview it with different color
-schemes, in both light and dark themes, and add new UI elements as desired.
+You can quickly create a page using FlutterFlow AI by describing what you want in natural language. The AI uses your description or visual reference, along with your project context, to build the page with relevant widgets. This is especially helpful when you're starting from scratch or prototyping ideas rapidly.
-To create an AI Generated page, follow the steps:
+To create and add an AI-generated page, open the **Widget Tree**, click **Generate with AI** (magic wand) button, and select the **Page** tab. Next, describe the page you want to build, and hit the **Send** (up arrow) button.
+
+FlutterFlow will process your request and display progress in the **AI Generation History** panel in the toolbar. Once the page is ready, you can preview it in both light and dark themes and apply various color schemes. If you're happy with the result, give it a name and add it to your project.
+
+:::tip
+
+- You can also upload a screenshot or image of the page you want to build. FlutterFlow AI will use it as a reference to generate the layout.
+- While the AI is generating your page, you can continue working on other tasks within FlutterFlow, but make sure you don’t close the FlutterFlow app.
+
+:::
+#### Import from Figma Frame
+You can also quickly turn your Figma designs into functional pages in FlutterFlow. By providing a Figma Frame URL, FlutterFlow AI will analyze the design and automatically generate UI layouts that closely match your mockup.
+To import from a Figma Frame, first, connect your Figma account, [import the Figma theme](../../../ff-concepts/design-system/design-system.md#import-figma-theme), and map your colors and typography accordingly. Next, open the **Generate with AI** dialog and click the **Plus (+)** button. Select **Import from Figma**, enter your **Figma frame URL**, and press **Send**.
+A preview of the frame you are importing will appear. To finalize the import, click **Send** again. Once completed, the page will appear in the AI Generation History, where you can preview and add it to your project.
+
+:::warning
+
+Currently, we don't support importing SVG elements from Figma frames. However, you can manually add the SVGs directly to your project [**assets**](../../../generated-code/directory-structure.md#assets) after generation is complete, or replace them in Figma with supported image formats like PNG or JPEG.
+
+:::
+
+
+
+
+
diff --git a/docs/resources/ui/pages/page-lifecycle.md b/docs/resources/ui/pages/page-lifecycle.md
index aef73651..ec68090b 100644
--- a/docs/resources/ui/pages/page-lifecycle.md
+++ b/docs/resources/ui/pages/page-lifecycle.md
@@ -74,6 +74,10 @@ To add an action to **On Page Load** action trigger, follow the steps:
+:::tip[Generated Code]
+When you add actions to the **on Page Load** action trigger, they are executed within a `SchedulerBinding.instance.addPostFrameCallback((_)` method. This ensures that the actions run after the widget tree is fully built. For more details, refer to the [**Page: Generated Code**](../../../generated-code/pages-generated-code.md#onpageload-action-generated-code) document.
+:::
+
### On Phone Shake [Action Trigger]
Actions added under this trigger are triggered when the
@@ -104,17 +108,17 @@ This action trigger allows you to bind keyboard shortcuts to actions. This is in
:::
:::info[important]
-- When a keyboard shortcut is created at the page level, it won't trigger if a TextField is in focus, and you also won’t be able to type the shortcut key into the TextField.
-- When a keyboard shortcut is created at the component level, it also won't trigger if a TextField is in focus, but you’ll still be able to type the shortcut key into the TextField.
+- When a keyboard shortcut is created at the page level, it won't trigger if a TextField is in focus, and you also won't be able to type the shortcut key into the TextField.
+- When a keyboard shortcut is created at the component level, it also won't trigger if a TextField is in focus, but you'll still be able to type the shortcut key into the TextField.
- **To avoid conflicts, it's recommended to use shortcuts that users are unlikely to type, such as Command + S, instead of a single key like 'S'.**
-- There’s currently a known issue with Flutter's autofocus functionality. If a TextField inside a component has autofocus enabled, and the component has a keyboard shortcut, the TextField will not autofocus as expected.
+- There's currently a known issue with Flutter's autofocus functionality. If a TextField inside a component has autofocus enabled, and the component has a keyboard shortcut, the TextField will not autofocus as expected.
:::
-Implementing keyboard shortcuts is a straightforward process in FlutterFlow. You can define as many shortcuts as you want, each mapped to specific actions that will trigger when the corresponding key combination is pressed. Let’s see an example of an eCommerce web app where users can quickly access the cart page by pressing the `C` key.
+Implementing keyboard shortcuts is a straightforward process in FlutterFlow. You can define as many shortcuts as you want, each mapped to specific actions that will trigger when the corresponding key combination is pressed. Let's see an example of an eCommerce web app where users can quickly access the cart page by pressing the `C` key.
-To create a shortcut, use the **On Shorcut Press** action trigger, then type the keys that you want your app to listen for.
+To create a shortcut, use the **On Shortcut Press** action trigger, then type the keys that you want your app to listen for.
-:::warning[Keyboard Shorcuts & Text Fields]
+:::warning[Keyboard Shortcuts & Text Fields]
When implementing keyboard shortcuts on a page or component with a text field, you may need to ensure the text field ignores those shortcuts.
For instance, if you have a shortcut assigned to the letter "C" and a user tries to type "C" in the text field, you likely want the input to capture the keypress without triggering the shortcut.
-To handle this, you can enable the option on the `TextField` widget to bypass keyboard shortcuts. However, it’s generally better to assign more unique combinations, like Cmd + C, which are less likely to conflict with normal typing in a text field.
+To handle this, you can enable the option on the `TextField` widget to bypass keyboard shortcuts. However, it's generally better to assign more unique combinations, like Cmd + C, which are less likely to conflict with normal typing in a text field.
:::
### On Dispose [Action Trigger]
The **On Dispose** action trigger allows you to define actions that execute when a page is navigated away from or removed from memory. It is particularly useful for stopping ongoing operations.
-Imagine a scenario where [audio recording](../../../ff-concepts/file-handling/audio/audio-recroding.md) is started when the page loads using the [On Page Load](#on-page-load-action-trigger) action trigger. The recording process runs as long as the user remains on the page. However, when the user navigates away, you need to stop the recording to save resources and ensure the recorded audio is finalized. By using the On Dispose action trigger, you can safely stop the recording and save the file.
+Imagine a scenario where [audio recording](../../../ff-concepts/file-handling/displaying-media.md#audio-recording) is started when the page loads using the [On Page Load](#on-page-load-action-trigger) action trigger. The recording process runs as long as the user remains on the page. However, when the user navigates away, you need to stop the recording to save resources and ensure the recorded audio is finalized. By using the On Dispose action trigger, you can safely stop the recording and save the file.
Additionally, if you are using a third-party package that relies on persistent connections or listeners, you can leverage [Custom Actions](../../../ff-concepts/adding-customization/custom-actions.md) with the On Dispose action trigger to close streams or cancel subscriptions.
:::tip[Possible Use Cases]
-- **Cleaning Up Resources:** Use this action trigger to cancel timers, close database connections, or unsubscribe from streams to prevent memory leaks and unnecessary processing.
+- **Cleaning Up Resources:** Use this action trigger to cancel timers, close database connections, or unsubscribe from streams to prevent memory leaks and unnecessary processing.
- For example, real-time applications, such as stock trading platforms, rely on WebSocket connections to fetch live updates. A homepage displaying a live ticker of stock prices would require opening the WebSocket connection on page load and closing it on On Dispose. Without an On Dispose trigger, the WebSocket connection could remain open unnecessarily, leading to wasted resources and app instability.
- **Finalizing Database Transactions**: Commit or roll back database transactions if the user leaves the page before completing the process.
-- **Logging or Analytics:** Track user behavior or log events (e.g., page exit or time spent on a page) to monitor user engagement and improve the application experience.
+- **Logging or Analytics:** Track user behavior or log events (e.g., page exit or time spent on a page) to monitor user engagement and improve the application experience.
:::

@@ -277,7 +281,7 @@ current value of a given Page State variable, either for directly displaying it
transactional logic.
You can set the source value of the widget wherever you see the following icon. This icon indicates
-that you can link the widget’s value to a variable.
+that you can link the widget's value to a variable.

@@ -323,13 +327,17 @@ update, create a new Action called **Update Page State**.
When updating your page state in Flutter, you'll often come across the **Update
Type** property in your Action properties. Here's what it means:
-**Rebuild Current Type:** This option triggers a re-rendering of the page,
+**Rebuild Current Page:** This option triggers a re-rendering of the page,
ensuring
that any changes to the state are reflected in the user interface (UI).
**No Rebuild:** Choose this option when you need to update the state without
immediately reflecting the changes in the UI.
+:::tip
+If you want to rebuild a page without updating any state variables, use the [**Rebuild**](../../../ff-concepts/state-management/state-variables.md#rebuild-action) state action.
+:::
+
:::warning[Expensive Rebuilds]
Too many rebuilds can impact performance because rebuilding the widget tree
frequently consumes resources and may lead to decreased responsiveness and
diff --git a/docs/resources/ui/pages/pages-properties.md b/docs/resources/ui/pages/pages-properties.md
index 9a4b404d..637efabb 100644
--- a/docs/resources/ui/pages/pages-properties.md
+++ b/docs/resources/ui/pages/pages-properties.md
@@ -33,6 +33,40 @@ customize the URL paths for web and mobile deep linking, set meaningful Page
Names as unique identifiers, integrate dynamic parameters into your routes, and
set access restrictions based on user authentication.
+
+
+**Skip On Page Load When Inactive**
+
+Ensures that actions are bypassed if the Entry Page or Logged In Page is detected as inactive. This is designed specifically for entry points in the app to prevent unnecessary operations when the page is not fully active, optimizing performance and avoiding redundant executions.
+
+:::tip[Generated Code]
+When this check is enabled, the following code is added to your `initState` of your page:
+```js
+if (RootPageContext.isInactiveRootPage(context)) {
+ return;
+ }
+ // On Page Load Actions added after this
+```
+:::
+
+**Requires Authentication**
+
+When the "Requires Authentication" option is enabled for a page, it ensures that only users who are logged in can access that page. This setting is particularly useful for protecting sensitive or personalized content, as it prevents unauthorized users from viewing or interacting with the page.
+
+:::tip[Generated Code]
+When the Route object is created for this Page, setting `requireAuth: true` ensures that only authenticated users can access this page. If "Requires Authentication" is checked, the app will automatically enforce authentication checks before navigating to this page. This is automatically enabled for **Logged In Page**.
+
+```js
+FFRoute(
+ name: 'promotionPage',
+ path: '/promotionPage',
+ requireAuth: true,
+ builder: (context, params) => PromotionPageWidget(),
+ )
+```
+:::
+
+
:::info[LEARN MORE]
Learn more about Routing [**here**](../../../ff-concepts/navigation-routing/nav-overview.md).
:::
@@ -86,8 +120,8 @@ page, submit form data, or call an API. Actions are crucial for creating
interactive and functional apps.
In the case of Scaffold (Page) actions, you can establish specific behaviors or
-functions that are triggered by certain events related to the page's lifecycle such as **On Page
-Load** or **On Phone Shake**.
+functions that are triggered by certain events related to the page's lifecycle such as [**On Page
+Load**](page-lifecycle.md#on-page-load-action-trigger) or [**On Phone Shake**](page-lifecycle.md#on-phone-shake-action-trigger).
:::info[LEARN MORE]
To learn about the page lifecycle and other methods exposed by FlutterFlow, [**refer to this resource**](page-lifecycle.md).
diff --git a/docs/resources/ui/widgets/basic-widgets/text.md b/docs/resources/ui/widgets/basic-widgets/text.md
index c4c71c52..dad99639 100644
--- a/docs/resources/ui/widgets/basic-widgets/text.md
+++ b/docs/resources/ui/widgets/basic-widgets/text.md
@@ -94,8 +94,42 @@ com/embed/62fd114580c94b0e84e837f19e5b57f8?sid=002d6a75-25c0-426f-9b09-9300f0cd5
-- **Auto Size:** This automatically adjusts the font size of the text to fit the space
-available within the widget boundaries. It ensures that the text remains legible without overflowing its container, making it especially handy for responsive designs where the display may vary across different devices.
+- **Auto Size**
+
+ The `Auto Size` option allows the `Text` widget to automatically reduce its font size to fit within its parent widget. This ensures that the text remains legible without overflowing its container, making it especially handy for responsive designs where the display may vary across different devices.
+
+ - **Configure Parent Widget Dimensions**
+
+ To enable `Auto Size`, the `Text` widget must be inside a widget that has both defined width and height. Without these constraints, the font size cannot be adjusted automatically.
+
+ 1. Select the `Text` widget.
+ 2. Check its parent widget.
+ 3. Ensure both width and height are explicitly defined.
+
+ :::warning
+ Without defined dimensions, the `Auto Size` feature may not behave as expected.
+ :::
+
+ - **Behavior Scenarios**
+
+ The following examples illustrate how `Auto Size` behaves under different container configurations:
+
+ - Container with width set to `infinity` and height set to `100px`, `Auto Size` disabled. The text may overflow beyond the container.
+ - Container with width set to `infinity` and height set to `100px`, `Auto Size` enabled. The font size adjusts to fit the defined height.
+ - Container with width set to `30%` and no height defined, `Auto Size` enabled. The feature has no visible effect due to missing height constraint.
+ - Container with width set to `70%` and height set to `50px`, `Auto Size` enabled. The text is resized to the minimum allowed font size to remain within the container.
+
+ 
+
+:::tip
+ Use `Auto Size` with percentage-based dimensions for better responsiveness. For example, set the container width to `30%` and enable `Auto Size` to allow the text size to adjust as the screen size changes.
+:::
+
+:::note
+ The `Auto Size` feature has a minimum font size threshold. If the container becomes too small, text may clip or overflow when resizing is no longer possible.
+:::
+
+
diff --git a/docs/resources/ui/widgets/built-in-widgets/imgs/20250430121459696014.png b/docs/resources/ui/widgets/built-in-widgets/imgs/20250430121459696014.png
new file mode 100644
index 00000000..96972115
Binary files /dev/null and b/docs/resources/ui/widgets/built-in-widgets/imgs/20250430121459696014.png differ
diff --git a/docs/resources/ui/widgets/built-in-widgets/imgs/tooltip-on-focus.avif b/docs/resources/ui/widgets/built-in-widgets/imgs/tooltip-on-focus.avif
new file mode 100644
index 00000000..350aa5c3
Binary files /dev/null and b/docs/resources/ui/widgets/built-in-widgets/imgs/tooltip-on-focus.avif differ
diff --git a/docs/resources/ui/widgets/built-in-widgets/media-display.md b/docs/resources/ui/widgets/built-in-widgets/media-display.md
index 90898310..a1b5763e 100644
--- a/docs/resources/ui/widgets/built-in-widgets/media-display.md
+++ b/docs/resources/ui/widgets/built-in-widgets/media-display.md
@@ -110,4 +110,4 @@ To customize the widget when image is displayed, refer [here](../../widgets/basi
### Customizing Video
-To customize the widget when video is displayed, refer [here](../../../../ff-concepts/file-handling/video/video-player.md#customization).
\ No newline at end of file
+To customize the widget when video is displayed, refer [here](../../../../ff-concepts/file-handling/displaying-media.md#videoplayer).
\ No newline at end of file
diff --git a/docs/resources/ui/widgets/built-in-widgets/pincode.md b/docs/resources/ui/widgets/built-in-widgets/pincode.md
index 4ec75bed..ee20d730 100644
--- a/docs/resources/ui/widgets/built-in-widgets/pincode.md
+++ b/docs/resources/ui/widgets/built-in-widgets/pincode.md
@@ -48,7 +48,7 @@ To add a PinCode widget:
-## Trigger action On Completed
+## Trigger Action On Completed
Let's see how to trigger an action when you are done entering the value in this widget. This is helpful when you want to compare the entered value with the one stored in your backend.
@@ -112,69 +112,12 @@ Here is an example of displaying a snackbar message that shows the entered value
-## Trigger action On Change
+## Trigger Action On Change
-Let's see how to trigger an action whenever you enter or delete the value in each field of this widget. This is helpful when you want to provide immediate feedback to the user. For instance, you can check the validity of the entered digit as soon as the user types it in and show a message that it is not valid.
+You may want to trigger an action whenever users enter or delete the value in each field of this widget. For instance, you can check the validity of the entered digit as soon as the user types it in and show a message that it is not valid. To do this, [add an action using the trigger](../../../../resources/control-flow/user-interactivity/forms/form-triggers.md#on-change) that responds to changes in this widget.
-
-
-
-
-
-
-To do so:
-
-1. Select the **PinCode** widget, select **Actions** from the Properties panel (the right menu), and click **+ Add Action**.
-2. Set the **Type of Action** (aka callback) to **On Change**. That means actions added under this will be called every time when a user enters each pin value.
-3. Now you can add any action here.
-
-Here is an example of displaying a snackbar message when a user enters a non-number value.
-
-
-
-
-
-
+## Trigger Action On Focus Change
+You may want to trigger an action when the user taps into or exits the Pincode field. For example, you can run a validation check once the user finishes entering the code and moves focus away from the field. To do this, [add an action using the trigger](../../../../resources/control-flow/user-interactivity/forms/form-triggers.md#on-focus-change) that responds to focus changes in this widget.
## Validation
diff --git a/docs/resources/ui/widgets/built-in-widgets/ratingbar.md b/docs/resources/ui/widgets/built-in-widgets/ratingbar.md
index e965b7d6..c8b40d86 100644
--- a/docs/resources/ui/widgets/built-in-widgets/ratingbar.md
+++ b/docs/resources/ui/widgets/built-in-widgets/ratingbar.md
@@ -265,7 +265,3 @@ To change the Axis:
-
-:::info[Trigger action on change]
-See how to [**trigger an action when a selection changes**](../../widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
-:::
\ No newline at end of file
diff --git a/docs/resources/ui/widgets/built-in-widgets/slider.md b/docs/resources/ui/widgets/built-in-widgets/slider.md
index 095ae84f..6b0ce00e 100644
--- a/docs/resources/ui/widgets/built-in-widgets/slider.md
+++ b/docs/resources/ui/widgets/built-in-widgets/slider.md
@@ -83,6 +83,11 @@ The steps to build the example are as follows:
+## Trigger Action on Change
+
+See how to [trigger an action when a selection changes](../../../control-flow/user-interactivity/forms/form-triggers.md#on-selected) on this widget.
+
+
## Setting initial value
Sometimes you might want to display the slider with the default value. For example, showing the volume slider with the audible volume value. You can do so by setting the initial value for the Slider.
@@ -302,7 +307,3 @@ To show the slider value:
-
-:::info[Trigger action on change]
-See how to [**trigger an action when a selection changes**](../../widgets/widget-commonalities.md#trigger-action-on-selection-change) on this widget.
-:::
\ No newline at end of file
diff --git a/docs/resources/ui/widgets/built-in-widgets/sticky-header.md b/docs/resources/ui/widgets/built-in-widgets/sticky-header.md
index c0ca36e9..829f4b72 100644
--- a/docs/resources/ui/widgets/built-in-widgets/sticky-header.md
+++ b/docs/resources/ui/widgets/built-in-widgets/sticky-header.md
@@ -166,7 +166,7 @@ com/embed/39bb5fc9068f4a759a4b0d6fd62e3f16?sid=ed5c274e-f1e0-4830-9702-dd35ac2d6
4. Now, inside the *StickyHeader* *Content* section, add the **ListView** with a **Container**
inside to display the list of matching contacts.
- 1. On this ListView, generate dynamic children from a variable that holds all the contacts. But while doing so, filter the list and extract only matching contacts using [Code expression](../../../../resources/control-flow/functions/utility-functions.md#code-expressions).
+ 1. On this ListView, generate dynamic children from a variable that holds all the contacts. But while doing so, filter the list and extract only matching contacts using [Inline Function](../../../../resources/control-flow/functions/utility-functions.md#inline-function-code-expressions).
2. Now you can display the contact's details, such as name, inside the UI.
+
+
+
+
### Change trigger mode
On touch devices, the *Tooltip* opens on tap. To make it open on long press instead, use the **Trigger Mode** property.
+### Show Tooltip on Focus
+
+The **Show Tooltip on Focus** toggle controls whether the tooltip is displayed when the child widget receives keyboard focus. This is particularly useful for improving accessibility and keyboard navigation, as it ensures users see helpful information when they tab through form fields, interactive elements or any important information.
+
+
+
### Change tooltip alignment
By default, the *Tooltip* appears below the target widget. You can change this setting using the **Preferred Direction** property. This allows you to open the Tooltip **Above**, **Left,** and **Right** directions in addition to the **Below**.
@@ -121,7 +157,7 @@ By default, the *Tooltip* appears below the target widget. You can change this s
### Customize tail size
-To change the tail's size, you can use the **Tail Width** and **Tail Lenght** properties.
+To change the tail's size, you can use the **Tail Width** and **Tail Length** properties.
** set the **Sho
allowFullScreen
allow="clipboard-write">
-
\ No newline at end of file
+
diff --git a/docs/resources/ui/widgets/composing-widgets/list-grid.md b/docs/resources/ui/widgets/composing-widgets/list-grid.md
index 356df57a..f16118af 100644
--- a/docs/resources/ui/widgets/composing-widgets/list-grid.md
+++ b/docs/resources/ui/widgets/composing-widgets/list-grid.md
@@ -29,6 +29,10 @@ Axis sets the orientation of the ListView. You can select either "Vertical" or
- **Items Spacing:** This defines the space between individual items in the ListView. You can
specify the spacing in pixels.
+:::tip[Items Spacing vs Padding]
+Prefer “Items Spacing” set on the parent row or column instead of padding on individual elements. This ensures consistency, especially on non-dynamically generated lists.
+:::
+
- **Apply to Start & End:** When enabled, the item spacing will also be applied to the start and the
end of the ListView, adding a margin at the beginning and end of the list. This effectively adds padding at the start and end of the layout in addition to between the items.
@@ -47,7 +51,7 @@ Axis sets the orientation of the ListView. You can select either "Vertical" or

-#### Make List Reorderable
+### Reorderable List
Whether to allow reordering of items in the list. On Web or Desktop this will
add drag handles, but on mobile
the reorder is triggerred by long pressing an item.
@@ -64,7 +68,7 @@ action trigger to make any necessary changes yourself.
Here's a quick tutorial to set up your Reorderable ListView:
-##### Using App State variable
+#### Using App State variable
1. First, create an app state variable with a few items of type String and display them on the
ListView widget.
@@ -116,7 +120,7 @@ return list;
com/embed/bb961c71d11a4e7d8869170727d1423d?sid=a356162d-76df-45bb-930c-bebf8358ce6c" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen>
-##### Reordering Items in a Firebase Query
+#### Reordering Items in a Firebase Query
If you want to reorder the list items retrieved via Firebase query collection, the steps are almost similar except for the following changes.
@@ -540,4 +544,4 @@ Follow the steps below to add this action to any widget.
allow="clipboard-write">
-
\ No newline at end of file
+
diff --git a/docs/resources/ui/widgets/composing-widgets/rows-column-stack.md b/docs/resources/ui/widgets/composing-widgets/rows-column-stack.md
index 5f0acda7..ff9bf513 100644
--- a/docs/resources/ui/widgets/composing-widgets/rows-column-stack.md
+++ b/docs/resources/ui/widgets/composing-widgets/rows-column-stack.md
@@ -30,6 +30,10 @@ depends on how you need to arrange your UI components:

+:::tip[Minimum Layout Nesting]
+Use the minimum amount of rows/columns necessary to achieve your layout to avoid unnecessary complexity. No page or component should nest more than 10 levels deep. Reaching this limit likely signals the need for **[converting a part of the widget tree into components](../../components/creating-components.md#convert-into-a-component)**.
+:::
+
@@ -218,6 +222,10 @@ incoming constraints and the scrolling movement, effectively managing overflow b
Column. You can specify a static numerical value that determines the pixel spacing between
adjacent children or set it from a variable.
+:::tip[Items Spacing vs Padding]
+Prefer “Items Spacing” set on the parent row or column instead of padding on individual elements. This ensures consistency, especially on non-dynamically generated lists.
+:::
+
- **Apply to Start & End:** When toggled on, this applies the specified item spacing to the
beginning and the end of the Row or Column. This effectively adds padding at the start and end of the layout in addition to between the items.
diff --git a/docs/resources/ui/widgets/imgs/Opacity.avif b/docs/resources/ui/widgets/imgs/Opacity.avif
new file mode 100644
index 00000000..a16c18c0
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/Opacity.avif differ
diff --git a/docs/resources/ui/widgets/imgs/color-from-string.avif b/docs/resources/ui/widgets/imgs/color-from-string.avif
new file mode 100644
index 00000000..501de5d2
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/color-from-string.avif differ
diff --git a/docs/resources/ui/widgets/imgs/conditional-visibility.avif b/docs/resources/ui/widgets/imgs/conditional-visibility.avif
new file mode 100644
index 00000000..48c7c00c
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/conditional-visibility.avif differ
diff --git a/docs/resources/ui/widgets/imgs/responsive-visibility.avif b/docs/resources/ui/widgets/imgs/responsive-visibility.avif
new file mode 100644
index 00000000..e9c7775a
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/responsive-visibility.avif differ
diff --git a/docs/resources/ui/widgets/imgs/test-value-keys.avif b/docs/resources/ui/widgets/imgs/test-value-keys.avif
new file mode 100644
index 00000000..30dc0a23
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/test-value-keys.avif differ
diff --git a/docs/resources/ui/widgets/imgs/ui-builder-display-value.avif b/docs/resources/ui/widgets/imgs/ui-builder-display-value.avif
new file mode 100644
index 00000000..f49608d2
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/ui-builder-display-value.avif differ
diff --git a/docs/resources/ui/widgets/imgs/use-handle-bars-to-resize.avif b/docs/resources/ui/widgets/imgs/use-handle-bars-to-resize.avif
new file mode 100644
index 00000000..7f4a6c49
Binary files /dev/null and b/docs/resources/ui/widgets/imgs/use-handle-bars-to-resize.avif differ
diff --git a/docs/resources/ui/widgets/widget-commonalities.md b/docs/resources/ui/widgets/widget-commonalities.md
index 74df796c..6e085a1d 100644
--- a/docs/resources/ui/widgets/widget-commonalities.md
+++ b/docs/resources/ui/widgets/widget-commonalities.md
@@ -1,115 +1,74 @@
---
title: Common Widget Properties
+tags: [Widgets]
+keywords: [Common Widget Properties, Visibility, Opacity, Padding, Alignment, Testing Value Key, Width and Height, Color Picker, Bulk Edits, Unsplash Images, UI Builder Display Value, Border Settings]
+description: Learn how to control common widget properties in FlutterFlow
sidebar_position: 6
---
-# Common Widget Properties
-
-While working with widgets, you may find some features or properties that are common across various widgets. This page will guide you on how to implement these common functionalities or modify properties that are applicable to multiple widgets.
-
-Here are the properties: you can also use the links on the right side to navigate to a property.
-## Use keyboard to increase/decrease property value
-
-You can adjust the property value using your keyboard's up and down arrow keys. **Tip**: Use the shift key in combination with the arrow keys, which increments or decrements the value by 10 units at a time.
+# Common Widget Properties
-
+When working with widgets in FlutterFlow, you'll encounter properties and features that are common across multiple widget types. Below is a detailed overview of such properties.
## Visibility
-### Conditional
-
-Conditional visibility allows you to control the display of UI elements (i.e., widgets) based on certain conditions or criteria. It enables you to create dynamic and personalized user experiences by showing or hiding specific content or features.
-
-For example, using this, you could display features, options, or actions based on the user's role or permissions, such as admins might see admin-only controls.
-
-Let's see how to add conditional visibility with an example that allows users to add doctors to their favorites list only if logged in. In essence, the favorite icon will only be displayed for logged-in users.
-
-Here's what the final result looks like:
-
-
- 
- Left side: user not logged in | Right side: user logged in
-
+Visibility settings in FlutterFlow allow you to dynamically control when and how widgets appear in your app.
+### Conditional
-Here are the steps:
+**Conditional** visibility allows you to control the display of UI elements (widgets) based on specific conditions or criteria. It helps you create dynamic, personalized experiences by showing or hiding certain content.
-1. Select the widget from the widget tree or canvas area.
-2. Move to the properties panel > enable Conditional.
-3. Click on the Unset and provide the condition that determines whether a UI element should be displayed or hidden. For this example, we'll directly use the Is User Logged In global property. This will show the widget if the user is logged in.
+For example, you could display specific features or actions only to users with particular roles, such as showing admin controls exclusively to administrators.
-4. You can toggle Show in UI Builder to test the effect of showing/hiding that widget in the UI builder. Note that this option is only to help you visualize the effect of visibility on the widget, and it does not affect your app.
+:::info
-
+The **Show in UI Builder** toggle only affects visibility within the design canvas, giving you a quick preview of how the layout will adjust when this widget is shown or hidden.
+:::
+
### Responsive
-When developing user interfaces with widgets, you'll notice certain properties and features that are universally applicable. This section provides guidance on adjusting these shared attributes across different widgets.
-
-Below are the common properties; you can use the navigation links on the right to quickly access detailed information about each property.
-
-
- 
- The navigation menu on the web and mobile
-
-
-
-You can achieve this by creating two separate widgets and setting their responsive visibility (under the properties panel).
-
-In the example above, the navigation menu created for the web or desktop (on the left side) is made visible only on a wider screen by enabling the desktop icon. Similarly, the navigation menu for the mobile (on the right side) is made visible only on a small screen by enabling the mobile icon.
-
-Here is how it is done:
-
-
- 
- Responsive visibility for mobile
-
+The **Responsive visibility** property allows you to show or hide widgets based on device screen size, such as mobile, tablet, or desktop. By toggling each icon, you can show or hide the widget according to your design needs.
-
- 
- Responsive visibility for web
-
+For example, you might create two separate navigation menus:
-#### Customize responsive breakpoint
+- **Desktop Menu**: A wider, left-aligned menu only visible on large screens by enabling the desktop icon and disabling all other screen size icons.
+- **Mobile Menu**: A compact drawer menu only visible on smaller screens by enabling the phone icon and disabling all other screen size icons.
-Sometimes, you might want to override the default responsive breakpoint to suit unique requirements; whether it's accommodating a specific device or catering to a particular user experience, having the flexibility to customize breakpoints can be advantageous.
+
-To customize responsive breakpoints, open **Theme Settings** (from the navigation menu) **> Design System > Breakpoints** and change the values.
-
-For example, if you define a custom breakpoint at 575 pixels, positioning it between the 'Mobile' and 'Tablet' range. In this case, when your app is accessed on a screen larger than 575 pixels, the layout will be adjusted as per the Tablet configuration.
+### Opacity
-
+The **Opacity** property controls how transparent or visible a widget appears. It accepts a value between 0 and 1, where 0 means fully transparent, 1 is fully opaque, and 0.5 results in semi-transparency.
+This property enables a wide range of creative UI effects, such as translucent buttons, overlay highlights, or smooth theme transitions.
-Furthermore, you can utilize these breakpoint values throughout your app to tweak the widget properties based on the screen size. For example, you might set different width and height values for a Container widget depending on whether the screen size matches with small, medium, or large.
+When **Animated Opacity** is enabled, any changes to the opacity value are smoothly animated based on the specified duration and curve, enhancing visual appeal and user experience.
-You can access the breakpoint values via the *Set from Variable* menu. Here's an example of setting the Container width based on the screen size.
+
-
+## Padding
+**Padding** is the space added inside a widget, between its content and its border (or edge). It ensures the content doesn't touch the borders, creating visual breathing room and contributing to a cleaner, more responsive layout across different screen sizes.
+To set padding, select the widget, go to the **Padding & Alignment** > **Padding** section in the **Properties Panel**, and enter the values in **pixels (px)**, which represent logical pixels.
-### Opacity
+You can choose from two options:
-Controlling the opacity of any widget opens up a plethora of creative opportunities. For instance, you can create an aesthetically pleasing effect using transparent buttons, dynamic themes, overlay effects, etc.
+- **Uniform Padding**: Apply the same value to all four sides.
+- **Independent Padding**: Set different padding values for top, bottom, left, and right.
-You can control the transparency from **Properties Panel > Visibility > Opacity** property. It accepts value between 0 and 1. e.g., 0 means full transparency, one is opaque, and 0.5 is half transparent.
-
-## Padding & Alignment
-
-### Add padding
-
-Padding is the empty space around the outer side of the widget.
-
-To add a padding:
-
-1. Select the widget from the widget tree or from the canvas area.
-2. Move to the [Properties Panel](../../../intro/ff-ui/builder.md#properties-panel) and navigate to the **Padding & Alignment** section.
-3. Enter values for Left (L), Top (T), Right (R), Bottom (B).
-4. To apply the same padding on all sides, switch to the **Uniform Padding** option. You can then adjust the padding by either moving the slider or entering the desired value directly.
-5. Use the refresh icon button to reset all values.
-
-
-
If you prefer watching a video tutorial, here is the guide for you:
-
-
-
-
-### Adjust alignment
-
-This property helps you position the widget in two ways.
-
-**Horizontal Alignment** determines where the widget will be placed horizontally inside of its parent. A value of -1 will place the widget to the left, while a value of 1 will place the widget to the right.
-
-**Vertical Alignment** determines where the widget will be placed vertically inside of a parent. A value of -1 will place the widget at the top, while a value of 1 will place the widget at the bottom.
-
-To change the alignment:
-
-1. Select the widget, and head over to [Properties Panel](../../../intro/ff-ui/builder.md#properties-panel) **> Padding & Alignment** section.
-2. Use the alignment box to align the widget at a fixed position or directly enter a value in the **Horizontal** and **Vertical** input box.
-
-
-
+
+
+
+
-If you prefer watching a video tutorial, here is the guide for you:
+## Alignment
-
+**Alignment** determines how a widget is positioned within its parent container. It helps you control where your widget appears—left, right, center, top, bottom, or any point in between.
+To set alignment, select the widget and go to the **Padding & Alignment** > **Alignment** section in the **Properties Panel**. You'll see a 3×3 grid representing all nine positions:
+- Top Left
+- Top Center
+- Top Right
+- Center Left
+- Center (Default)
+- Center Right
+- Bottom Left
+- Bottom Center
+- Bottom Right
-## Testing
+Simply click the dot representing where you'd like the widget to be positioned. Alternatively, you can input a specific value (between -1 to 1) for the precise horizontal and vertical alignment.
-This property enables you to specify the **Value Key** for the current widget, which serves as a reference point during automated test runs. Please refer to the detailed guide provided [here](../../../testing-deployment-publishing/testing/automated-tests.md).
+- **X (Horizontal Alignment)** controls the widget’s position along the horizontal axis within its parent. A value of `-1` aligns it to the left, `0` centers it, and `1` aligns it to the right.
+- **Y (Vertical Alignment)** controls the widget’s position along the vertical axis. A value of `-1` places it at the top, `0` centers it vertically, and `1` places it at the bottom.
-## Changing the size
+:::info
-To change the size, navigate to the **Width** and **Height** properties, and then you have three choices for setting the size:
+Values beyond this range will push the widget outside the visible screen area.
-* For a specific size, choose **PX** and type in the size you want.
-* For a size based on the screen, choose **%** and type in the percentage.
-* To make the widget fill the whole screen width or height, click on the infinity symbol (**∞**).
+:::
-
+
+
+
+
+
-## Change color
+## Add Testing Value Key
-To change color for any widget property:
+A **Value Key** is used to uniquely identify widgets during [**Automated Testing**](../../../testing-deployment-publishing/running-your-app/automated-tests.md) in FlutterFlow. For example, on a Create Account page, you might use descriptive keys like `signupFirstNameField`, `signupEmailField`, `signupPasswordField`, and `signupSubmitButton`. This helps testing tools reliably locate and interact with the correct widgets. For more details, refer to the [complete guide here](../../../testing-deployment-publishing/running-your-app/automated-tests.md).
-1. Navigate to a widget property that allows you to set a color.
-2. Click on the currently selected color to either pick a new color or enter the Hex Code directly.
-3. By default, theme colors are displayed. Simply click on a color to apply it.
-4. For a custom color, switch to the **Custom Color** tab, select your desired color, and then click **Use Color**.
-5. You can also set a [color from variable](#setting-color-from-variable).
+
-
+## Set Width & Height
+To adjust a widget's size, click on the widget you wish to resize and navigate to the right-side Properties Panel. There, you can set the size in the following ways:
-## Setting color from variable
+- **PX (Pixels):** Enter a fixed size in pixels for a consistent dimension.
+- **% (Percentage):** Set the size relative to the screen or parent container.
+- **∞ (Infinity):** Make the widget expand to fill the available width or height.
-You may want to apply dynamic colors to widget properties like Container backgrounds or Text colors, which can be achieved by assigning colors from a variable. For instance, you can display temperature color dynamically based on an app state variable, data from a Firestore document, responses from API calls, or other similar sources.
+ width: '100%'}}>
-
-To set a color from a variable:
-
-1. Navigate to a widget property that allows you to set a color.
-2. From the **Set from Variable** menu, you can select the source of your color. Below is an example of setting color from an app state variable.
+You can also drag the handle bars on the right and bottom sides of a selected widget to resize. The measurements appear while resizing to show the current pixel values.
-
+
-
+:::tip[Responsive Width & Height]
-You can also set the color from a [conditional value](../../../resources/control-flow/functions/conditional-logic.md#setting-widget-properties-with-conditional-logic).
+You can also use a **Responsive Value** to apply different width or height values based on screen size. To set it up, open the **Set from Variable** menu and select **Responsive Value**. Then, assign specific size values for each screen size category, such as mobile (Screen Width < Breakpoint Small), tablet (Screen Width < Breakpoint Medium), and desktop (Screen Width < Breakpoint Large).
-## Copy variable
-
-If you have a complex variable value (e.g., using [Conditional Logic](../../../resources/control-flow/functions/conditional-logic.md)) and want to use the same logic in another variable value, you can do so by copying a variable.
+:::
-To copy-paste a variable:
+## Use Keyboard to Adjust Property Values
-1. Open the **Set from Variable** menu and select the **Variable Options** (three dots) icon.
-2. Select the **Copy Variable**.
-3. Move to the place where you want to paste the variable, and open the **Set from Variable** menu.
-4. Click on the **Paste Variable** icon.
-5. Click **Confirm**.
+You can quickly increase or decrease the property value using your keyboard's up and down arrow keys. This allows for precise control without needing to type in new values each time.
-
+:::tip
-
+Hold down the **Shift** key while pressing the arrow keys to change the value by 10 units at a time.
-## Edit multiple widgets simultaneously
+:::
-We also allow you to modify the properties of multiple widgets at once. This can be a time-saving and efficient way to make bulk changes to the user interface of an app.
+## Change Color
-For example, imagine that you want to change the background color of multiple buttons in an app from blue to green. Without the ability to edit multiple widgets simultaneously, you would need to select and edit each button individually. However, with this feature, you can select all of the buttons at once and modify their fill color property.
+To change the color, navigate to a widget property that allows you to set a color, and then click on the currently selected color. This opens the **Color Picker**, where you have multiple ways to set the desired color:
-To edit multiple widgets simultaneously, you can select all the widgets you want to modify by clicking on each one while holding down the shift key. Once you have selected all the desired widgets, you can access and modify their common properties all at once from the properties panel.
+- **Custom Color**: Use the gradient area to select any shade and fine-tune it using:
+ - The **hue slider** (rainbow bar) to adjust the base color.
+ - The **transparency slider** (checkered bar) to control opacity (alpha value).
+- **Use RGB or HEX**: Manually input a **HEX code** (e.g., `#A489F5`) or set the **RGB values** directly for precise color control. The **Alpha (A)** value defines transparency (e.g., 100% = fully opaque).
+- **Theme Colors**: Below the picker, you’ll find a list of your app’s predefined **Theme Colors** like Primary, Secondary, and Background. Using theme colors ensures design consistency across your app and makes global updates easier.
+- **Set from Variable**: You can also dynamically assign a color based on your app logic. For example, changing the background color based on the selected item or theme.
-
+
+
+
+
-## Add an image from Unsplash
+:::tip
-You can also add images directly from the [Unsplash](https://unsplash.com/) right inside the properties panel. To do so, simply click on the search icon and search and select the image. **Tip**: You can also choose the size of the image to add (i.e., Small, Regular, Full).
+You can also assign a color using a **String variable** that contains a **CSS-style color value** (e.g., `"#FF5733"`, `"rgba(255, 87, 51, 1)"`, or `"red"`). This is especially useful when colors are stored in a database or returned from an API. Make sure the string format follows valid CSS color syntax, as FlutterFlow uses the [**`from_css_color`**](https://pub.dev/packages/from_css_color) package under the hood to parse these values.
-
+This allows you to dynamically theme parts of your app based on user preferences or remote configurations.
-
+
-## UI builder display value
+:::
-For widgets like **Text** and **RichText**, when their content is coming from a variable, you have the option to set a placeholder value that will be displayed only in the app builder. Keep in mind that this display value is solely for visualization purposes within the canvas and will be replaced with the actual variable value when the app is running.
+## Copy Variable
-This is helpful in assessing spacing and alignment without the need to remove variable bindings.
+If you’ve created a complex variable value (e.g., using Conditional Logic) and want to reuse the same logic elsewhere, you can easily do so by copying the variable.
+To copy and paste a variable, open the **Set from Variable** menu, click the **three dots**, and select **Copy Variable**. Then go to the target location, open the same menu, click **Paste Variable**, and confirm.
+
+
+
+
+
-
-## Trigger action on selection change
+## Bulk Edits Properties
-Here, you will see how to trigger an action when the selection changes for any Form widget such as Dropdown, RadioButton, ChoiceChips, Slider, and RatingBar.
+You can easily modify the properties of multiple widgets at once. For example, if you want to change the background color of several buttons from blue to green, there's no need to edit each one individually. Simply select all the buttons and update their fill color in one go.
-:::info
-To simplify, we've used the Dropdown widget as an example. However, the same instructions apply to other Form widgets as well.
-:::
+To do this, hold down the **Shift** key and click on each widget you want to edit. Once selected, their shared properties will appear in the **Properties Panel**, where you can apply changes.
-To do so:
+## Use Images from Unsplash
+
+You can easily display high-quality images directly from [Unsplash](https://unsplash.com/) using the Properties Panel. Just click the **search icon**, type in your desired keyword, and select an image from the results.
+
+:::tip
+
+You can also choose the image size (i.e., Small, Regular, or Full) before adding it, depending on your layout.
-1. Select the widget.
-2. Select **Actions** from the properties panel, and click **+ Add Action**.
-3. You will notice that the **Type of Action** (aka callback) is already set to **On Selected**. That means actions added under this will be called whenever the selection changes.
-4. Now you can add any action here.
+:::
-Here is an example showing the snackbar message when the Dropdown selection changes.
-## Adding border
+## UI Builder Display Value
+
+For widgets like `Text` and `RichText`, if the content is set from a variable, you can add a placeholder value that appears only in the FlutterFlow builder. This placeholder helps you visualize how the text will look on the canvas, but it won’t appear in the live app, it's replaced by the actual variable at runtime.
+
+This is especially helpful for previewing layout, spacing, and alignment without removing or disrupting your variable bindings.
+
+
+
+## Adding Border
-To add a border to any widget:
+You can add a border to any widget using the following properties:
-1. Find the **Border Color** property and change the color.
-2. To create the rounded border, use the **Border Radius** property.
-3. Enter values for TL (Top left), TR (top right), BL (bottom left), and BR (bottom right).
-4. To apply the same radius on all sides, switch to the **Uniform Radius** option. You can then adjust the radius by either moving the slider or entering the desired value directly.
-5. Use the refresh icon button to reset all values.
-6. To increase the border thickness, use the **Border Width** property.
+- **Border Color**: Choose a color manually or bind it to a variable. You can select from your theme colors (like `Primary`) or use the color picker.
+- **Border Width**: Set the thickness of the border in pixels.
+- **Border Radius**: Adjust how rounded the corners should be using the options below:
+ - **Independent Radius**: Set different radius values for top, bottom, left, and right.
+ - **Uniform Radius**: Apply the same value to all four sides. The slider and numeric input allow you to have precise control.
+- **Button Padding**: Controls the space inside the widget (between the content and the border).
+
+:::tip
+
+Use consistent border and padding styles for buttons, cards, and containers to maintain a clean and cohesive UI.
+
+:::
-
+
\ No newline at end of file
diff --git a/docs/testing-deployment-publishing/branching-collaboration/branching.md b/docs/testing-deployment-publishing/branching-collaboration/branching.md
index b0a958e8..0973d2b0 100644
--- a/docs/testing-deployment-publishing/branching-collaboration/branching.md
+++ b/docs/testing-deployment-publishing/branching-collaboration/branching.md
@@ -5,15 +5,16 @@ description: Learn how branching in FlutterFlow allows you to add new features w
tags: [Branching, Collaboration]
sidebar_position: 1
keywords: [Branching, Collaboration, FlutterFlow, Concepts]
+toc_max_heading_level: 4
---
# Branching
Branching creates a separate copy of your work, so you can add new features without disrupting your current progress. It enables multiple developers or teams to work simultaneously on different features without interfering with each other.
-Suppose you have an eCommerce app and you want to add a new feature, such as a product recommendation system. Instead of incorporating it directly into your `main` branch and potentially causing problems, you can create a branch to work on this new feature in isolation. Once it's complete, you can integrate it back into the `main` branch.
+Suppose you have an eCommerce app and you want to add a new feature, such as a product recommendation system. Instead of incorporating it directly into your existing `main` branch and potentially causing problems, you can create a branch to work on this new feature in isolation. Once it's complete, you can integrate it back into the `main` branch.
:::info
-This feature is only available for Pro, Teams and Enterprise users.
+While all users can access the branching menu and create commits, only **Growth** plan and above support creating new branches.
:::
@@ -27,12 +28,18 @@ FlutterFlow. You can also learn more about
## Branching Overview
Before you create and merge a branch, it is essential to understand the general workflow. Here's what it looks like:
-
+
-First, create a new branch from the `main` branch. After making your changes and finalizing the
-feature, merge this new branch back into the `main` branch. If there are any conflicts,
+First, create a new branch from the `main` branch. After making your changes in a new branch and finalizing the feature, merge this new branch back into the `main` branch. If there are any conflicts,
you must resolve them first.
+:::note
+It’s important to understand what merging actually means. Merging does not perform a "union" of data between branches. Instead, Git merge reconciles differences (diffs) between the branches. When you merge, Git compares the changes made in the new branch with the main branch and applies these changes directly.
+
+For instance, if a branch is created and all existing data is deleted before new content is added, Git interprets this as a replacement. When the branch is merged back into the main branch, those deletions will also be applied removing the original data. This behaviour can be surprising to those expecting Git to automatically preserve all content from both branches. Learn more about [**Merging**](#merging).
+
+To avoid accidental data loss, ensure that your branch workflow involves incremental and intentional changes rather than deleting and replacing all existing content unless that's specifically your goal.
+:::
## Creating a New Branch
To create a new branch from the current branch, simply go to the **Branching Options** button next to current branch in the **Branching menu.**
@@ -116,7 +123,11 @@ To create a commit, follow these steps:
Once the commit is created, you can see the list of all commits under the **Branch History** section. Here, each commit is displayed with a timestamp, the user who made the changes, and a commit message. You can also search and filter through commits by specific users and date range.
-To see the commit changes, simply click on the commit.
+To see the commit changes, simply click on the commit. You’ll then land on a **Commit View** page where you can:
+
+- **Review Changed Files**: In the left panel, files that have been modified are marked with a gray dot, making it easy to spot which parts of your project have updates.
+- **Compare Before and After**: The center pane provides a side-by-side diff of the YAML for each changed file. Lines highlighted in red indicate removed or altered content, while lines in green show newly added or updated content.
+- **See Commit Statistics**: At the top of the page, you’ll see a quick summary of how many files were changed and the total lines added (+) or removed (-).
+ width: '100%'}}>
-Next, you'll see a screen that will display if there are any conflicts. If you don’t have any conflicts, you can simply go ahead and click **Merge Branch**.
+When performing a merge in FlutterFlow, you’ll see a screen with multiple panels and info sections. Here are the details of it.
+
+
+
+**Top Panel**
+
+- **Branch Information**: At the top of the merge interface, you’ll see exactly which branches are being merged. You have two options for merging directions:
+ - **Parent → Child**: Pulls changes down from the parent into the child branch, often used to keep a feature branch in sync with the parent branch.
+ 
+ - **Child → Parent**: Pushes features (or other changes) from the child branch back up to the parent, commonly done once a feature is ready to go into the parent branch.
+ 
+- **YAML Validation Errors**: These occur when the resulting data is not in a “FlutterFlow-friendly” format—whether that’s due to manual edits or merges that generate incompatible YAML. For example, imagine you have two pages in your project, and each branch independently deletes a different one. After merging, there are zero pages left. Even though no lines of code are edited or directly have a conflict, this results in a YAML Validation Error. Clicking on these errors should redirect you to the specific file. Invalid lines will be underlined in red within the file, and, you cannot complete the merge while YAML errors exist.
+
+- **Project Errors**: Project errors occur when the result of a merge creates a problem in your project. For example, this might happen if the merge results in two data types having the same name. These errors need to be resolved to ensure your project works as expected. You have several options to deal with project errors:
+ - **Fix Errors During the Merge**: This approach ensures that the merged project is error-free right from the start. Here’s how you can do it:
+ - **Edit the YAML files:** Update the project YAML files (in the Right Lower Panel) to fix issues, such as renaming a data type that causes a conflict.
+
+
+
+
+
+
+
+ - **Edit the Project Directly while Merging:** While still in the merge process, open the project, make the necessary changes (like renaming the conflicting data type), and then continue.
+ - **Fix Errors After the Merge**: If you prefer, you can complete the merge first and address the errors later. For example, finish the merge process as it is. After merging, go back to the project and resolve any issues.
+- **Cancel**: Abandons the merge process and discards any conflict resolutions you’ve already applied during this merge session.
+- **Merge**: Finalizes the merge once all merge conflicts and YAML validation errors are cleared. Project errors can remain if you choose to resolve them later.
+- **Bulk Accept Changes**: Accessible via the **arrow** next to **Merge** button. This option lets you accept all changes from one branch at once—handy if you already know which branch’s changes take precedence.
+
+
+**Left Panel**
+
+The left-hand side panel displays all the project files in YAML format. YAML (Yet Another Markup Language) files use a simple, human-readable format to define configuration data. They are particularly useful during a merge because they allow you to directly review, understand, and resolve any changes or conflicts in your project’s file.
+
+- **Filter Files:** You can use filters to narrow down the list of YAML files based on specific criteria:
+
+ - **All Files (Unchanged Files)**: Shows every YAML file in the project that has no changes.
+ - **Files with Changes**: Displays only files where a change has been made on either branch.
+ - **Files with Conflicts**: Shows only files that have merge conflicts, where the changes in one branch directly contradict the changes in the other.
+
+ :::info
+ - A **change** refers to any update, addition, or deletion made in one of the branches. For example, modifying a field name or changing the properties of a widget.
+ 
+ - A **conflict** occurs when the same part of a file has been changed in both branches, making it unclear which version to keep. For instance, if one branch changes the color of the Container to blue and the other changes it to red, this creates a conflict.
+ 
+ :::
+
+- **Search File:** If you’re looking for a particular file, you can use the search bar to locate it quickly. This is especially useful in larger projects with many files.
+
+Clicking on a file in the panel opens it in the editor, allowing you to view, edit, and resolve issues directly.
+
+**Right Upper Panel**
+
+The Upper Right Panel offers a quick, side-by-side comparison of file changes from both branches, along with easy one-click accept buttons and previews. This panel makes it simple to decide which changes to keep or discard.
-
+:::info
+The edits are highlighted using green and red (Git) color coding:
-### Resolve merge conflicts
-A merge conflict occurs when multiple team members make changes to the same part of the project.
+- **Green** indicates lines or values **added** (or unique) in one branch.
+- **Red** indicates lines or values **removed** (or replaced) by that branch.
+:::
-For example, imagine two developers, Alice and Bob, are working on the same FlutterFlow project and both decide to update the same button widget.
+- **Accept Change Button**: Quickly accept changes from one branch if you know it has the correct edits.
+- **Eye (Preview) Icon**: Open or view the file in the FlutterFlow builder to see how the changes look. For example, you can preview a theme color change visually rather than just reading its name in the file.
-| **Developer** | **Branch Name** | **Changes** |
-|---------------------|---------------------|----------------------------------------------------|
-| Alice | `feature-alice` | - Changes the button text to "Submit Form" |
-| | | - Changes the button color to blue |
-| Bob | `feature-bob` | - Changes the button text to "Send" |
-| | | - Changes the button color to green |
+**Right Lower Panel**
-When Alice's changes are merged into the main project first, her updates will be integrated without any issues. However, when Bob tries to merge his changes afterward, a merge conflict will occur because the changes to the button text and color have already been modified by Alice.
+The **Lower Panel** displays the final merged files after Git applies its merging logic. It gives you a chance to manually inspect and edit the outcome—whether or not a conflict occurs.
-In your project, if you get merge conflicts, here’s how you resolve them.
+Git attempts to combine changes from both branches automatically. If Git can’t reconcile certain lines, it flags a **merge conflict** in the file. Conflicts appear with special markers like `<<<<<<<`, `=======`, and `>>>>>>>`.
-
-
-
-
-
+- `<<<<<<<`: Marks the beginning of other branch’s changes
+- `=======`: Separates your current branch’s changes from the other branch’s changes.
+- `>>>>>>>`: Marks the end of the conflict, indicating your current branch’s changes.
-For certain conflicts, such as those involving variables and API configurations, you'll see a **View Configuration** option. Enabling this option opens the split screen view displaying changes from the new branch, allowing you to easily identify what has changed. In this view, you can see things that were removed highlighted in red, and things that were added highlighted in green.
+:::tip
+You might decide to keep certain lines from `<<<<<<<` (from the other branch) or `>>>>>>>` (from your branch) or combine them manually.
+:::
+
+You can modify files or edit the project directly from the lower panel at any time—even if there’s no conflict.
-
+After editing, click **Save Changes** to confirm your changes. A red reset button appears if you want to undo your changes and restore the file to its initial state before you began editing.
-### Resolve conflicts manually
-If you choose to resolve manually, you can directly make changes in the **Accepted Changes** section. Note that if you cancel a manual resolution, you can choose to either keep or discard the changes you have made since starting the manual resolution.
+For more information, check out the video below.
+ width: '100%'}}>
-:::info
+### Resolve Merge Conflicts
+A merge conflict occurs when multiple team members make changes to the same part of the project.
-If the visual editor doesn't display something in the split screen UI that you need to manage during a merge, click the **Edit Project** button and edit the project as usual.
+For example, imagine two developers, Alice and Bob, are working on the same FlutterFlow project and both decide to update the same button widget.
-::::
+| **Developer** | **Branch Name** | **Changes** |
+|---------------------|---------------------|----------------------------------------------------|
+| Alice | `feature-alice` | - Changes the button text to "Submit Form" |
+| | | - Changes the button color to blue |
+| Bob | `feature-bob` | - Changes the button text to "Send" |
+| | | - Changes the button color to green |
+When Alice's changes are merged into the main project first, her updates will be integrated without any issues. However, when Bob tries to merge his changes afterward, a merge conflict will occur because the changes to the button text and color have already been modified by Alice.
+
+When you initiate a merge using Git, the system attempts to automatically reconcile your project files. Any conflicts that cannot be automatically resolved are flagged for your attention.
+
+You can review each file with merge conflicts and choose to:
+
+- Accept all changes from one branch.
+
+- Pick specific changes from any branch.
+
+- Manually edit the YAML files. **Note that** it’s essential to correct any YAML validation errors that arise from manual edits.
+
+
+
+
+
+
+Finally, complete the merge by clicking **Merge**.
+:::tip
+- If you merged a child branch into its parent and are confident everything looks correct, you may delete the child branch.
+- If you find any issues after the merge, you can revert the branch to an earlier commit. However, be aware that any changes made after that commit will be lost.
+:::
## Branch-level Permissions
In your project, you have the ability to assign specific roles such as **Editors** and **Mergers** to project members for each branch.
@@ -318,15 +436,9 @@ To configure these permissions, navigate to **Settings & Integrations > Project
Closing a branch is a common practice after the branch has served its purpose, typically once its changes have been merged into another branch (like the `main` or `development` branch). By regularly closing inactive or merged branches, you help maintain a clean, efficient, and well-organized project.
-### When to Close a Branch
-
+:::info[When to Close a Branch]
- **After a Merge:** Once the branch’s changes have been merged into the `main` branch (or another target branch), it’s safe to close the branch. This often happens after a feature is complete or a bug is fixed.
- **Unused Branch:** If a branch is no longer needed (e.g., a feature was abandoned or changes were made in another branch), it’s a good idea to close it.
-
-:::warning
-
-Once a branch is closed, it will no longer appear in the list of active **Branches**, meaning no further changes can be made. **This action is permanent and cannot be undone**, so ensure that all necessary work is completed or merged before closing the branch.
-
:::
Here’s how you can close a branch:
@@ -361,4 +473,93 @@ Here’s how you can close a branch:
- **Review before deletion:** Before closing a branch, ensure that all necessary changes have been merged or no longer need to be kept.
- **Coordinate with your team:** If you’re working in a team, ensure that no one is actively using the branch before you close it, to avoid disrupting ongoing work.
-:::
\ No newline at end of file
+:::
+
+Once a branch is closed, it will no longer appear in the list of active branches. However, you can restore a closed branch within **30 days** of its closure.
+
+### Restore Branch
+To restore a branch, open the **Branch Filter** menu and enable **Show Closed Branches**. Search for or select the branch you want to restore, and it will open in a new browser tab. Then, within the closed branch, open the **Branching Options** menu and select **Restore Branch** to reactivate it.
+
+
+
+
+
+
+
+
+
+
+## FAQs
+
+
+How YAML files are helpful during a merge?
+
+
+YAML files play a key role in managing and resolving conflicts during the merge process because:
+- YAML files hold important configuration data, such as settings, resource definitions, and project properties. During a merge, changes in these files reflect modifications to the structure or behavior of the project.
+- The simple and hierarchical nature of YAML makes it easy to spot changes or conflicts, even in complex files.
+- YAML files allow you to manually edit and resolve conflicts during the merge process.
+- Since YAML files are text-based, they are version-controlled effectively, enabling multiple team members to make changes and merge their work.
+
+
+
+
+
+Why didn’t all my changes appear after merging two branches?
+
+
+Merging in Git is not like copying everything from one branch into another. It’s more like combining changes from two versions of a document based on a common starting point.
+
+Let’s say you and your friend both made changes to the same project:
+- You both started with the same original version (this is called the common ancestor).
+- You made your changes in `Branch A`.
+- Your friend made changes in `Branch B`.
+
+When you merge `Branch B` into `Branch A`, Git compares:
+- What changed in `Branch A` since the common starting point.
+- What changed in `Branch B` since the common starting point.
+
+If both of you changed different parts, Git can merge them easily. But if you both changed the same part in different ways, Git won’t know which one to keep, that's called a conflict, and you'll need to resolve it manually.
+
+
+
+
+Here are a few other things to know:
+
+
+
No conflicts ≠ no changes: “No conflicts” doesn’t mean “no changes” and it definitely doesn’t mean the project is error-free.
+
Project errors are not bugs: Project errors let you know that you are making mistakes when merging data. Even if changes are successfully merged, project errors indicate areas you should double-check to ensure everything merged as expected.
+
If a change was previously accepted or rejected during a merge, it won’t appear as a diff the next time you merge the same branches. That’s expected behavior.
+
+
+
+For example, you merge `Branch B` into `Branch A`, and `change C` (which exists in `Branch B`) gets copied over to `Branch A`. Later, you decide to undo `change C` directly on `Branch A`. Now, if you merge `Branch B` into `Branch A` again, Git will not re-flag `change C` as a difference. This is because Git considers it already merged and no longer a diff.
+
+
+
+
+Best Practice: Keep your branch histories short and simple. After each merge, delete the merged branch to avoid unnecessary complexity. For example, if you merge `Branch B` into `Branch A`, and later want to undo or revise those changes, don’t go back and modify `Branch B`. Instead, create a new branch (e.g., `Branch C`) from `Branch A` to make your updates.
+
+This approach prevents intertwining branch histories, avoids confusing merge behavior, and ensures clean, trackable diffs. Keeping branches focused and temporary makes merging more predictable and manageable.
+
+
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/accept-all-from-one-branch.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/accept-all-from-one-branch.avif
new file mode 100644
index 00000000..3d138ebf
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/accept-all-from-one-branch.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/accept-specific-change-from-file.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/accept-specific-change-from-file.avif
new file mode 100644
index 00000000..14e3f7b3
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/accept-specific-change-from-file.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/branching-overview.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/branching-overview.avif
new file mode 100644
index 00000000..b91cae27
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/branching-overview.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/bulk-accept.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/bulk-accept.avif
new file mode 100644
index 00000000..ee39ad79
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/bulk-accept.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/change.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/change.avif
new file mode 100644
index 00000000..23bf6e99
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/change.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/child-parent.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/child-parent.avif
new file mode 100644
index 00000000..b46cf576
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/child-parent.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/conflict.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/conflict.avif
new file mode 100644
index 00000000..76eed82e
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/conflict.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/git-merging-behavior.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/git-merging-behavior.avif
new file mode 100644
index 00000000..1e2162c1
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/git-merging-behavior.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/merging-window.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/merging-window.avif
new file mode 100644
index 00000000..c3c3813d
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/merging-window.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/parent-child.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/parent-child.avif
new file mode 100644
index 00000000..efeb43a3
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/parent-child.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/imgs/yaml-validation-error.avif b/docs/testing-deployment-publishing/branching-collaboration/imgs/yaml-validation-error.avif
new file mode 100644
index 00000000..c9b8e7b8
Binary files /dev/null and b/docs/testing-deployment-publishing/branching-collaboration/imgs/yaml-validation-error.avif differ
diff --git a/docs/testing-deployment-publishing/branching-collaboration/saving-versioning.md b/docs/testing-deployment-publishing/branching-collaboration/saving-versioning.md
index c8b619cc..e708a533 100644
--- a/docs/testing-deployment-publishing/branching-collaboration/saving-versioning.md
+++ b/docs/testing-deployment-publishing/branching-collaboration/saving-versioning.md
@@ -1,8 +1,8 @@
---
slug: /collaboration/saving-versioning
title: Saving and Versioning
-description: Learn about the crucial concepts of saving and versioning in your FlutterFlow project.
-tags: [Saving, Versioning, Collaboration]
+description: Learn about versioning in your FlutterFlow.
+tags: [Versioning]
sidebar_position: 2
keywords: [Saving, Versioning, Collaboration, FlutterFlow, Concepts]
---
@@ -13,40 +13,10 @@ In this section, we discuss the important concepts of saving and versioning in y
## Versions
-Versions enable you to save specific named states of your project. This function is particularly useful for recovery purposes. If you accidentally delete a page or component or change settings, you can easily revert to a saved version.
+:::warning[Project Versions are now deprecated]
+You can no longer create new versions in FlutterFlow. However, any previously created versions will remain accessible. Moving forward, we recommend using [**Commits**](#commits), which provides a more robust way to track changes and manage your project history.
+:::
-### Saving a version
-
-Saving the latest changes will store the current state of your app in the version control. In the future, if anything goes wrong, you can restore your app to the currently saved state.
-
-Ideally, you should save the version whenever you accomplish something important, for example, after finishing a page, adding configuration, etc.
-
-
-
-
-
-
### Restoring a version
@@ -66,7 +36,9 @@ Snapshots are automatic saves of your project's state as you build it. They allo

:::info
-
-Users on the *Free* and *Standard* plans can access only one day of snapshots.
-
+- Users on the **Free** plan can access automated snapshot backups from **up to 1 hour prior**.
+- The **Basic** plan allows access to backups from **up to 1 day prior**.
+- The **Growth** plan provides access to backups from **up to 3 days prior**.
+- The **Business** plan extends this to **up to 7 days prior**.
+- For **Enterprise** users, snapshot retention is **customized**.
:::
\ No newline at end of file
diff --git a/docs/testing-deployment-publishing/development-environments/development-environments.md b/docs/testing-deployment-publishing/development-environments/development-environments.md
index 9fcedd63..53a20425 100644
--- a/docs/testing-deployment-publishing/development-environments/development-environments.md
+++ b/docs/testing-deployment-publishing/development-environments/development-environments.md
@@ -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]
---
@@ -54,14 +55,15 @@ You can create and switch environments in the **Dev Environments** page in **App
-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`:
-:::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#get-dev-environment-values-in-custom-code)**.
:::
+#### 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.
@@ -159,6 +177,8 @@ It's recommended that you keep schemas consistent between the different Supabase
+
+
### FAQ
diff --git a/docs/testing-deployment-publishing/exporting-code/ff-cli.md b/docs/testing-deployment-publishing/exporting-code/ff-cli.md
index 0a928e40..06aee5af 100644
--- a/docs/testing-deployment-publishing/exporting-code/ff-cli.md
+++ b/docs/testing-deployment-publishing/exporting-code/ff-cli.md
@@ -75,7 +75,28 @@ To use the CLI, you'll need to create an API token and use it in your requests.
## Filtered exports
-We've developed [a solution](https://github.com/krabhishek/flutterflow-filtered-pull) that allows you to use the CLI tool without overwriting specific files or directories. This is especially useful if you're managing code outside of FlutterFlow and want to prevent it from being overwritten during a code export.
+If you are updating an existing project and do not want certain files to be overwritten during a code export, you can create a `.flutterflowignore` file in the root of your project directory. This file should contain a list of files to be ignored using globbing syntax.
+
+### Example:
+If your project is located at:
+```
+/Users/yourname/projects/my_flutterflow_app/
+```
+Then, place the `.flutterflowignore` file in:
+```
+/Users/yourname/projects/.flutterflowignore
+```
+
+### Example `.flutterflowignore` contents:
+```
+my_flutterflow_app/android/app/build.gradle # Prevents FlutterFlow from overwriting native Android build configuration
+my_flutterflow_app/ios/Runner/Info.plist # Keeps iOS app metadata unchanged
+my_flutterflow_app/web/index.html # Ensures custom modifications to the web entry file are retained
+```
+This ensures that the specified files and directories are not overwritten during code export.
+
+For more details on globbing syntax, refer to [this guide](https://pub.dev/packages/glob#syntax).
+
## FAQ
@@ -87,4 +108,4 @@ dart pub global activate flutterflow_cli
```
This should update the CLI and fix the issue.
-
\ No newline at end of file
+
diff --git a/docs/testing-deployment-publishing/imgs/branching.avif b/docs/testing-deployment-publishing/imgs/branching.avif
deleted file mode 100644
index 309473d0..00000000
Binary files a/docs/testing-deployment-publishing/imgs/branching.avif and /dev/null differ
diff --git a/docs/testing-deployment-publishing/publishing/imgs/deploy-web-app-for-environments.avif b/docs/testing-deployment-publishing/publishing/imgs/deploy-web-app-for-environments.avif
index 82776854..4641ddf9 100644
Binary files a/docs/testing-deployment-publishing/publishing/imgs/deploy-web-app-for-environments.avif and b/docs/testing-deployment-publishing/publishing/imgs/deploy-web-app-for-environments.avif differ
diff --git a/docs/testing-deployment-publishing/publishing/pre-checks-publishing.md b/docs/testing-deployment-publishing/publishing/pre-checks-publishing.md
index 4d1ef122..f4d3b254 100644
--- a/docs/testing-deployment-publishing/publishing/pre-checks-publishing.md
+++ b/docs/testing-deployment-publishing/publishing/pre-checks-publishing.md
@@ -13,10 +13,10 @@ This page outlines the important steps and checks to be made before publishing y
Here’s a comprehensive list of these prechecks:
-1. **Functionality Testing**: Test the app manually across devices. You can also implement integration tests using FlutterFlow’s [**Automated Tests**](../testing/automated-tests.md) framework to cover various scenarios.
+1. **Functionality Testing**: Test the app manually across devices. You can also implement integration tests using FlutterFlow’s [**Automated Tests**](../running-your-app/automated-tests.md) framework to cover various scenarios.
2. **Get Feedback**: Run your app in Run Mode to generate a shareable link to the session. You can share these links to gather feedback from users and testers, providing valuable insights and potential areas of improvement before the public release.
-3. **Optimizations & Enhancements**: Improve performance by implementing [optimization and enhancement](../../intro/ff-ui/toolbar.md#optimizations--enhancements) suggestions. Ensure that images are properly sized, consider using higher compression for assets, and remove unused assets and custom widgets. These will help improve your app's speed and size.
+3. **Optimizations & Enhancements**: Improve performance by implementing [optimization and enhancement](../../intro/ff-ui/toolbar.md#project-suggestions) suggestions. Ensure that images are properly sized, consider using higher compression for assets, and remove unused assets and custom widgets. These will help improve your app's speed and size.
4. **User Interface:** Check UI consistency across different screen sizes and resolutions using the [Canvas Size](../../intro/ff-ui/canvas.md) option.
5. **Accessibility Checks**: Add semantic labels to make the app more accessible to users with disabilities by providing meaningful descriptions.
6. **Security Measures**: Make sure all data handling practices comply with legal standards, including GDPR if applicable. Use HTTPS for all network connections and ensure that sensitive data is encrypted.
diff --git a/docs/testing-deployment-publishing/publishing/web-publishing.md b/docs/testing-deployment-publishing/publishing/web-publishing.md
index ace2f1ad..4a0309c1 100644
--- a/docs/testing-deployment-publishing/publishing/web-publishing.md
+++ b/docs/testing-deployment-publishing/publishing/web-publishing.md
@@ -38,16 +38,6 @@ To add platform support, navigate to the **Setting and Integrations > Project Se

-#### Advanced Web Settings
-
-1. **Use Original Engine Initialization**: This uses original Flutter web engine initialization, which sometimes helps in better loading time in the deployed web app.
-
-2. **Use CanvasKit**: Enabling this option can provide high-quality graphics and text rendering on web platforms. **Note** that when using CanvasKit, some images can be blocked from loading if the server is not configured to allow loading them from other websites. To deal with this issue, you can set any of the following options, depending on where the images are hosted.
- - **None:** If you are only loading images from your Firebase Storage, select this option and follow the steps [here](#).
- - **Deploy with Firebase**: If images are not hosted on Firebase Storage *but you use Firebase to build your app*, choose this option and hit Deploy button.
- - **Custom Proxy URL**: If you are not using Firebase or prefer to set up your own CORS proxy, you can specify your own Custom Proxy URL. If you don't have one, you can create one by following the steps [here](https://github.com/Rob--W/cors-anywhere).
-3. **Import Emoji library**: Importing the Emoji library is necessary if your app may use emojis anywhere in any text widget. However, this will increase the size of your app on web.
-
:::info
Enabling web support automatically enables
@@ -55,6 +45,44 @@ Enabling web support automatically enables
:::
+#### Advanced Web Settings
+
+1. **Use CanvasKit**: Enabling this option can provide high-quality graphics and text rendering on web platforms.
+
+2. **CORS Proxy for Images (Optional)**: When using CanvasKit, some images can be blocked from loading if the server is not configured to allow loading them from other websites. This happens because Flutter web uses WebGL for rendering, which requires access to raw image data and is subject to browser security restrictions called [Cross-Origin Resource Sharing (CORS)](https://docs.flutter.dev/platform-integration/web/web-images#cross-origin-resource-sharing-cors).
+
+ Choose the appropriate option based on where your images are hosted:
+
+ - **None**: If you are only loading images from your Firebase Storage, select this option and configure Firebase Storage for web access. FlutterFlow automatically excludes Firebase Storage images from CORS proxy requirements.
+
+ - **Deploy with Firebase**: If images are hosted on external servers (not Firebase Storage) *but you use Firebase for your app*, choose this option. FlutterFlow will automatically deploy a regional CORS proxy function to your Firebase project for optimal performance. Simply click the **Deploy** button that appears below this option.
+
+ - **Custom Proxy URL**: If you're not using Firebase or prefer to manage your own CORS proxy, specify your custom proxy URL here. If you don't have one, you can create one using services like [cors-anywhere](https://github.com/Rob--W/cors-anywhere) or CloudFlare Workers.
+
+ :::warning
+ **Performance Note**: Using a CORS proxy adds a network hop for external images, which may slightly increase loading times. For best performance, host images on Firebase Storage or a CORS-enabled CDN when possible.
+ :::
+
+3. **Import Emoji Library**: Importing the Emoji library is necessary if your app may use emojis anywhere in any text widget. However, this will increase the size of your app on web.
+
+4. **Use Wasm (Beta)**: Enabling this option will build your app using Flutter’s **Wasm (WebAssembly) web renderer**. For more details, see the [Flutter Documentation on Wasm](https://docs.flutter.dev/platform-integration/web/wasm).
+
+ :::warning
+ - This feature is currently in *Beta*, so it should be used with caution.
+ - Wasm is not supported in *Test Mode*.
+ :::
+
+
+
+#### Troubleshooting CORS Issues
+
+If you're experiencing image loading issues on web:
+
+1. **Check browser console**: Look for CORS-related error messages
+2. **Verify image sources**: Ensure external image servers allow cross-origin requests
+3. **Test proxy configuration**: Verify your custom proxy URL is accessible and functioning
+4. **Firebase Storage setup**: Confirm Firebase Storage rules allow public read access for web
+
### 2. Make design adjustments (optional)
If you're creating a web-only application, setting the canvas size to desktop and building pages accordingly can work well. However, if you plan to target both mobile and web users, some design adjustments may be necessary to ensure that the UI is optimized for both platforms.
@@ -83,7 +111,7 @@ In such a situation, you can try to find a replacement package on [pub.dev](http
In this step, you must provide general information about your web app by following the steps below:
-1. Navigate to the **Setting and Integrations >** **App Settings >** **Web Publishing**.
+1. Navigate to the **Setting and Integrations >** **App Settings >** **Web Deployment**.

@@ -91,7 +119,7 @@ Inside the **General Information** section, enter the following details:
- **Site URL**: You can define the *Site URL* by adding the subdomain, for example, *mywebapp.flutterflow.app*. You can only change the subdomain, i.e., the part before *flutterflow.app*.
:::warning
- - You can remove or change the existing subdomain by simply entering the new one and hitting the publish button. Note that when you change your subdomain, it only takes effect the next time you publish.
+ - You can remove or change the existing subdomain by simply entering the new one and hitting the publish button. Note that when you change your subdomain, it only takes effect the next time you deploy.
- Old addresses can stop working anytime and be given to another user.
- There is a limit on the number of subdomains you can register per user. *Paying users can register up to 20 subdomains*. You will receive an in-app warning if you are approaching the limit.
:::
@@ -112,7 +140,7 @@ Inside the **General Information** section, enter the following details:
:::info
-Tip: Only *Standard*, *Pro*, and *Teams* users can remove the FlutterFlow watermark.
+Tip: Only users on the paid plans can remove the FlutterFlow watermark.
:::
@@ -124,7 +152,7 @@ When you are ready to deploy, click **Publish.** This will take approximately 2-
By default, you will publish to a subdomain based on your project id. These default subdomain addresses do not count toward the subdomain quota, and you can deploy as many projects as you'd like. The URL would look like this: `your-project-id-1234.flutterflow.app`
-You can also modify the address by specifying a custom subdomain address, in the **Settings > Web Publishing** tab's **Site URL** field, as long as it's available. You can have up to **3** custom subdomain URLs on the Free plan, and up to **20** custom subdomain URLs on any of our Paid plans.
+You can also modify the address by specifying a custom subdomain address, in the **Settings > Web Publishing** tab's **Site URL** field, as long as it's available. You can have up to **2** custom subdomain URLs on the Free plan, up to **20** on any of our Paid plans, and **unlimited** custom subdomain URLs on the Enterprise plan.
:::info
@@ -154,8 +182,7 @@ Adding a custom domain to your web app can give it a more professional look and
:::info[Important]
-- Only *Pro* and *Teams* plans include **one** free custom domain. The *Teams* plan comes with one custom domain for the whole team. If you are on the *Standard* plan, you will need to purchase a custom domain, as it is not included in the plan for free.
-- Only paid plans can purchase domains. *Standard* and *Pro* users can buy from their *Account* page, and Teams owners can buy it from **[My Organization](../../resources/projects/how-to-collaborate-on-projects.md#sharing-a-project-with-an-organization)**.
+- All our paid plans include one free custom domain, with the option to purchase more if needed.
- A single custom domain slot can be linked to only one domain or subdomain.
- You can connect only one domain to a project, which can be either a root domain (like 'myapp.com') or a subdomain (such as 'beta.myapp.com'). That means if you connect a root domain, none of the subdomains under it will connected to the project. This leads to the rule of '*One project => One domain OR subdomain'*.
diff --git a/docs/testing-deployment-publishing/running-your-app/_category_.json b/docs/testing-deployment-publishing/running-your-app/_category_.json
index 97aee821..8ec2edd2 100644
--- a/docs/testing-deployment-publishing/running-your-app/_category_.json
+++ b/docs/testing-deployment-publishing/running-your-app/_category_.json
@@ -1,4 +1,4 @@
{
- "label": "Running your App",
+ "label": "Testing your app",
"position": 3
}
\ No newline at end of file
diff --git a/docs/testing-deployment-publishing/testing/automated-tests.md b/docs/testing-deployment-publishing/running-your-app/automated-tests.md
similarity index 96%
rename from docs/testing-deployment-publishing/testing/automated-tests.md
rename to docs/testing-deployment-publishing/running-your-app/automated-tests.md
index 391c42bf..09cdc734 100644
--- a/docs/testing-deployment-publishing/testing/automated-tests.md
+++ b/docs/testing-deployment-publishing/running-your-app/automated-tests.md
@@ -3,7 +3,7 @@ slug: /testing/automated-tests
title: Automated Tests
description: Discover how to effectively utilize automated testing in FlutterFlow to ensure your app performs as intended.
tags: [Automated Tests, Testing]
-sidebar_position: 0
+sidebar_position: 2
keywords: [Automated Tests, Testing, FlutterFlow]
---
@@ -18,10 +18,10 @@ FlutterFlow doesn’t support running tests on the platform yet.
:::
:::info[Pricing Details]
-
-- **Free users:** This feature is not available.
-- **Standard plan:** Limited to creating up to 3 tests (Note: Limit may vary).
-- **Pro and Team plan:** Unlimited test creation allowed.
+- **Free and Basic plans:** Automated testing is not available.
+- **Growth plan:** Includes **1 test per project**.
+- **Business plan:** Allows **up to 3 tests per project**.
+- **Enterprise plan:** Supports **unlimited automated tests**.
:::
## Basics
diff --git a/docs/testing-deployment-publishing/running-your-app/local-run.md b/docs/testing-deployment-publishing/running-your-app/local-run.md
index 7245547a..65a68616 100644
--- a/docs/testing-deployment-publishing/running-your-app/local-run.md
+++ b/docs/testing-deployment-publishing/running-your-app/local-run.md
@@ -65,7 +65,7 @@ Here are the steps to use local run:

-7. From the test menu, click on the **Get Devices** button. This will list devices connected to your system. You can add or remove devices from the list by clicking on the **+** and **-** buttons, respectively. Once you've finalized your selection, simply click on the **Test** button to see your app running on selected devices. **Tip**: In the Mac OS desktop app, you can directly open the simulator by clicking on the **Launch iOS Simulator** text.
+7. From the test menu, click on the **Get Devices** button. This will list devices connected to your system. You can add or remove devices from the list by clicking on the **+** and **-** buttons, respectively. Once you've finalized your selection, simply click on the **Test** button to see your app running on selected devices. **Tip**: In the Mac OS desktop app, you can directly open the simulator by clicking on the **Launch iOS Simulator** text. To test app on a real device, see how to [setup a physical device](#setup-physical-device).
About phone**, tap **Build number** seven times to activate Developer Options, then go to **Settings > System > Developer options** and enable **USB debugging**.
+
+Connect your device to your computer via USB, authorizing the connection if prompted. Verify the setup by running `flutter devices` in Android Studio’s terminal; your device should appear in the list of connected devices.
+
+:::info
+
+For more detailed guidance, refer to the [**Android Flutter documentation**](https://docs.flutter.dev/get-started/install/macos/mobile-android#configure-your-target-android-device).
+
+:::
+
+### Setup iOS Device
+
+To setup iOS physical device, you must configure your **Apple Developer account** and set up **code signing** in Xcode. First, add your **Apple ID** by opening **Xcode > Preferences > Accounts**, clicking **"+"**, selecting **Apple ID**, and signing in.
+
+Next, assign your project to a development team. Open your project in Xcode, select the **Runner** project, go to **Signing & Capabilities**, and choose your **Apple Developer team** in the **Team** dropdown. If your team is not listed, ensure that your Apple ID has been properly added to Xcode.
+
+Finally, configure code signing to allow your app to run on a real device. Ensure **"Automatically manage signing"** is enabled. Xcode will attempt to create and download a **provisioning profile** for your project. If issues arise, you may need to manually create a provisioning profile in the **Apple Developer Certificates, Identifiers & Profiles** section. Once created, download and double-click the provisioning profile to install it in Xcode.
+
+:::info
+
+For more detailed guidance, refer to the [**iOS Flutter documentation**](https://docs.flutter.dev/get-started/install/macos/mobile-ios#configure-your-target-ios-device).
+
+:::
+
+## Access Device Logs in Local Run
Device logs provide a way to access and view the logs generated by your app while it's running on a device or simulator. They are invaluable for understanding the inner workings of your app. If something isn't functioning as expected, the device logs can reveal the reasons behind it.
@@ -109,7 +141,7 @@ To access the device logs, first run your app using the local run. Then, open th

-### Console input
+### Console Input
The console input in local run is particularly useful for performing hot reload and hot restart directly from the device logs. To initiate a hot reload, press `r` followed by `Enter`, and for a hot restart, press `R` followed by `Enter`. Additionally, any terminal commands commonly used with Flutter while running an app should work with the console input.
@@ -141,24 +173,24 @@ The console input in local run is particularly useful for performing hot reload
-### Checking errors
+### Checking Errors
Any errors displayed in the red box on your screen are also recorded in the Device logs, where you can find detailed information about the app's state and the events leading up to the issue.
-## Reconfigure local run setup
+## Reconfigure Local Run Setup
If you need to update the Flutter SDK version, run Flutter Doctor, or start the simulator again, simply open the test menu and click **Configure**.

-## Access project code
+## Access Project Code
To access the project code, open the test menu and ensure the project is not running. Click on the **code icon**, and you'll be presented with options to either open the project folder, project in your preferred IDE or directly launch the project in Xcode (for macOS users).

-## Manually download code and run
+## Manually Download Code and Run
There may be certain situations where you, as a developer, may prefer not to have local runs overwrite any changes that have been made in the code. In such cases, you can manually download the code onto your local system and then make any modifications as needed.
@@ -169,11 +201,11 @@ Here’s how you do it:
3. [Installing IDE and Plugins](#3-installing-ide-and-plugins)
4. [Running app on device](#4-running-app-on-device)
-### 1. Download code
+### 1. Download Code
:::warning
-- This feature is only included in our *Standard* and *Pro* plans.
+- Project code download is available only on the paid plans.
- Make sure to address any project issues before downloading the code.
:::
@@ -225,10 +257,14 @@ You can choose to install either [Visual Studio Code](https://code.visualstudio.
- To install Visual Code with Flutter and Dart plugins, check out [this link](https://flutter.dev/docs/get-started/editor?tab=vscode).
- To install Android Studio with Flutter and Dart plugins, check out [this link](https://flutter.dev/docs/get-started/editor?tab=androidstudio).
-### 4. Running app on device
+### 4. Running App on Device
You can choose to run your app on a real device or an emulator.
+:::tip
+To test app on a real device, see how to [**setup a physical device**](#setup-physical-device).
+:::
+
To run your app on a device:
1. First open the downloaded project in your preferred IDE.
@@ -258,7 +294,7 @@ Running your app on a Desktop involves:
visibility using [Responsive Visibility](../../ff-concepts/layout/responsive-layout.md#responsive-visibility).
3. **Run the app on a desktop**: Use the Local Run feature in the FlutterFlow Desktop app or manually download and run the code, choosing your target device (e.g., macOS) before running.
-## Video guide
+## Video Guide
If you prefer watching a video tutorial, here's the one for you:
diff --git a/docs/testing-deployment-publishing/testing/_category_.json b/docs/testing-deployment-publishing/testing/_category_.json
deleted file mode 100644
index c920a2e3..00000000
--- a/docs/testing-deployment-publishing/testing/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "Testing",
- "position": 4
- }
\ No newline at end of file
diff --git a/docs/troubleshooting/ github/_category_.json b/docs/troubleshooting/ github/_category_.json
new file mode 100644
index 00000000..4befa748
--- /dev/null
+++ b/docs/troubleshooting/ github/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "GitHub"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/ github/initialize_github_repository.md b/docs/troubleshooting/ github/initialize_github_repository.md
new file mode 100644
index 00000000..2b62fcd6
--- /dev/null
+++ b/docs/troubleshooting/ github/initialize_github_repository.md
@@ -0,0 +1,55 @@
+---
+keywords: ['github', 'push', 'repository', 'initialize', 'error']
+slug: /troubleshooting/github/initialize-github-repository
+title: Initialize GitHub Repository
+---
+
+# Initialize GitHub Repository
+
+When pushing code to GitHub, the following error may occur:
+
+```js
+Error pushing repository. Make sure your repository is initialized
+```
+
+This typically happens if the GitHub repository was not initialized correctly or if the project exceeds GitHub’s file size limits.
+
+:::info[Prerequisites]
+- Access to your GitHub account.
+- A FlutterFlow project with GitHub integration enabled.
+:::
+
+Follow the steps below to initialize a GitHub repository:
+
+1. **Create a New Repository**
+
+ - Go to **[GitHub](https://github.com/)** and click **New** to create a repository.
+ - Enable the option **Add a README file** during creation.
+
+2. **Connect Repository to FlutterFlow**
+
+ - Open your FlutterFlow project.
+ - Navigate to **GitHub Integration** and follow the instructions to connect the new repository.
+
+ 
+
+3. **Download and Inspect Your Project**
+
+ - Download the full source code from FlutterFlow.
+ - Navigate to the `assets` folder.
+ - Identify any files larger than **25MB**.
+
+ :::warning[Check Your Asset Size]
+ GitHub does not allow individual files larger than 25MB. Large image or video files may cause push failures.
+ :::
+
+
+ :::tip[Tips to Reduce Project Size]
+ - Use **network assets** instead of uploading large media files directly to FlutterFlow.
+ - Optimize images using tools like TinyPNG or ImageOptim before uploading.
+ :::
+
+:::info[Additional Resources]
+- **[Connect a GitHub Repo](/exporting/push-to-github/#connect-a-github-repo)**
+- **[State Management](/concepts/state-management/)**
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/ github/repository_head_deployment_failure.md b/docs/troubleshooting/ github/repository_head_deployment_failure.md
new file mode 100644
index 00000000..b92379cd
--- /dev/null
+++ b/docs/troubleshooting/ github/repository_head_deployment_failure.md
@@ -0,0 +1,56 @@
+---
+keywords: ['deployment', 'github', 'repository', 'codemagic']
+slug: /troubleshooting/github/repository-head-deployment-failure
+title: Repository Head Deployment Failure
+---
+
+# Repository Head Deployment Failure
+
+This error may occur when deploying your FlutterFlow app to GitHub using Codemagic. The message `Failed to set the repository head` indicates a problem with repository access, configuration, or connectivity.
+
+:::info[Prerequisites]
+- A connected GitHub repository with appropriate access permissions.
+- GitHub deployment enabled within FlutterFlow.
+:::
+
+**The Error Message**
+
+ ```js
+ Failed to set the repository head
+ ```
+ This message typically appears in the build log during deployment.
+
+Below are the possible causes of this error:
+
+ - The GitHub repository does not exist or was deleted.
+ - The branch specified in build settings does not exist.
+ - Insufficient permissions to push or write to the branch.
+ - GitHub API or network connectivity issues.
+ - Local build errors in the codebase.
+
+**Steps to Fix the Deployment Error:**
+
+1. **Confirm the Repository Name**
+
+ Ensure the repository name in your FlutterFlow deployment settings exactly matches the name in GitHub.
+
+2. **Verify the Branch**
+
+ Check that the branch exists in the repository and is correctly specified in your build settings. Avoid typos or casing mismatches.
+
+3. **Review Repository Permissions**
+
+ Confirm that your GitHub account or connected GitHub App has push/write access to the repository and branch.
+
+4. **Check Network Access**
+
+ Make sure your environment is not blocking GitHub via VPN, firewall, or DNS restrictions.
+
+5. **Validate the Codebase Locally**
+
+ Run the downloaded Flutter project locally to confirm that it builds without errors.
+
+:::info[Additional Resources]
+- **[GitHub Deployment Overview](/deployment/deploy-from-github/#steps-to-deploy)**
+- **[Codemagic Deployment Error Identification](/troubleshooting/deployment/codemagic-deployment-error-identification/)**
+:::
diff --git a/docs/troubleshooting/api/_category_.json b/docs/troubleshooting/api/_category_.json
new file mode 100644
index 00000000..38c866f5
--- /dev/null
+++ b/docs/troubleshooting/api/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "API"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/api/api_charset_and_encoding_fix_guide.md b/docs/troubleshooting/api/api_charset_and_encoding_fix_guide.md
new file mode 100644
index 00000000..7f085a04
--- /dev/null
+++ b/docs/troubleshooting/api/api_charset_and_encoding_fix_guide.md
@@ -0,0 +1,55 @@
+---
+keywords: ['api', 'encoding', 'charset']
+slug: /troubleshooting/api/api-charset-and-encoding-fix-guide
+title: API Charset and Encoding Fix Guide
+---
+# API Charset and Encoding Fix Guide
+
+When working with API calls in FlutterFlow, you might encounter issues where the response returns with strange characters, incorrect formatting, or unreadable content. These problems are often caused by improper charset or encoding settings either in the API request or the server response.
+
+This guide shows you how to resolve such issues and ensure your API outputs are correctly displayed in your FlutterFlow project.
+
+Follow the steps below:
+
+1. **Set Proper Request Headers**
+
+ Make sure your API call includes the appropriate headers to instruct the server on how to format the response. Add the following headers to your API configuration:
+
+ - `Content-Type: application/json`
+
+ - `Charset: utf-8`
+
+
+ These headers tell the server to return the data in JSON format using UTF-8 encoding, which is compatible with FlutterFlow.
+
+ 
+
+2. **Enable UTF-8 Decoding in FlutterFlow**
+
+ If the server does not specify encoding—or if you're still getting corrupted text—you can configure FlutterFlow to decode the API response as UTF-8 manually.
+
+ To do this:
+
+ 1. Go to your API call setup in FlutterFlow.
+ 2. Scroll to **Advanced Settings**.
+ 3. Enable **Force response decoding as UTF-8**.
+
+ This setting helps FlutterFlow correctly interpret the API response, especially from servers that don’t return standard headers.
+
+ 
+
+
+:::tip[Final Tips]
+- Always test your API calls in FlutterFlow’s API Test tab to ensure the response is properly formatted.
+- Confirm that the external API supports UTF-8 and returns a valid JSON response.
+- Review your server settings if you control the backend, to ensure it sends the correct headers.
+:::
+
+:::note
+Incorrect API call outputs due to charset or encoding can be quickly resolved by:
+- Adding proper headers like `Content-Type: application/json` and `Charset: utf-8`.
+- Enabling **Force response decoding as UTF-8** in FlutterFlow’s API advanced settings.
+These simple steps will help you get accurate and readable data from your APIs, resulting in a smoother app development experience.
+:::
+
+If you still face challenges, don't hesitate to reach out to our support team through Live chat or by emailing support@flutterflow.io
diff --git a/docs/troubleshooting/api/client-server_errors_during_the_api_call.md b/docs/troubleshooting/api/client-server_errors_during_the_api_call.md
new file mode 100644
index 00000000..d13dd1cc
--- /dev/null
+++ b/docs/troubleshooting/api/client-server_errors_during_the_api_call.md
@@ -0,0 +1,119 @@
+---
+keywords: ['api', 'error', 'client']
+slug: /troubleshooting/api/client-server-errors-during-the-api-call
+title: Client-Server Errors during the API call
+---
+# Client-Server Errors During the API Call
+
+
+When calling an API in FlutterFlow, you may run into client-server errors. These typically come as status codes that indicate what went wrong, either on your end (the client) or on the server you're requesting data from.
+
+This guide will help you understand the most common API error codes and how to fix them.
+
+To learn more about APIs, check out our **[API documentation guide](/resources/backend-logic/rest-api/)**.
+
+## Common Client-Side Status Codes
+
+These errors are usually caused by incorrect requests from the client side.
+
+- **400 – Bad Request**
+
+ The 400 error is a generic response indicating that the server could not understand the request due to malformed syntax. Common causes include incorrect query parameters or missing fields in the request body. Ensure your request is correctly formatted and all required information is included.
+
+ :::tip
+ Check the API's own documentation to ensure you're including the correct fields and headers.
+ :::
+
+ 
+
+- **401 – Unauthorized**
+
+ This status code appears when authentication has not yet been provided. To resolve this, ensure you have signed up for the API and included your API key in the HTTP header of your request.
+
+ 
+
+- **403 – Forbidden**
+
+ Receiving a 403 error means you're authenticated but do not have permission to access the requested resource. This could be due to using the wrong API key or attempting to access features not available in your subscription plan.
+
+ 
+
+- **404 – Not Found**
+
+ The 404 error indicates that the requested URL does not exist on the server. This could be due to a typo in the URL or changes in the API endpoints. Always verify the URL and check for any recent API updates.
+
+ :::tip
+ Always double-check your request URL before troubleshooting further.
+ :::
+
+ 
+
+- **407 – Proxy Authentication Required**
+
+ You haven't authenticated with the proxy server. This is less common but can happen in restricted network environments.
+
+- **422 – Unprocessable Entity**
+
+ Your request was well-formed but couldn’t be processed. For example, passing a `latlng` without a comma.
+
+- **429 – Too Many Requests**
+
+ This error occurs when too many requests are sent in a short period, exceeding the API's rate limits. To avoid this, implement request throttling or review your API subscription plan to ensure it meets your needs.
+
+ :::tip
+ Check your API plan limits and consider throttling requests from your app.
+ :::
+
+## Common Server-Side Status Codes
+
+These errors occur on the API server side.
+
+- **500 – Internal Server Error**
+
+ A 500 error can occur for various reasons, often indicating that the API server has crashed. Check your request for accuracy and consult the API documentation for any known issues.
+
+- **501 – Not Implemented**
+
+ This error occurs when the HTTP method used in the request is not supported by the server. Trying a different HTTP method or checking the API documentation for supported methods can resolve this issue.
+
+- **502 – Bad Gateway**
+
+ This error means that the server, acting as a gateway or proxy, received an invalid response from the upstream server. It's usually a temporary issue that should be resolved by the API provider.
+
+- **503 – Service Unavailable**
+
+ The 503 status code indicates that the server is temporarily unable to handle the request due to overload or maintenance. Waiting before sending another request is often the best approach.
+
+- **504 – Gateway Timeout**
+
+ A 504 error suggests that the server, acting as a gateway, did not receive a timely response from the upstream server. This could be due to network latency or the API server processing the request too slowly.
+
+
+**Troubleshooting Steps**
+
+- **Clear Browser Cache and Cookies**
+
+ If you're encountering a 400 Bad Request error, clearing your browser's cache and cookies can resolve issues related to expired or invalid data.
+
+- **Verify the Requested URL**
+
+ Ensure the URL or endpoint is correct. Remember, domain names are case-sensitive.
+
+- **Adjust Request Parameters**
+
+ For 400 errors, check if the file size is too large (for POST requests) or if there are any other incorrect parameters.
+
+- **Consult API Documentation**
+
+ Always refer to the API's official documentation for specific requirements and troubleshooting tips.
+
+- **Contact API Support**
+
+ If you continue to face issues, reaching out to the API's support team can provide further assistance and insights into resolving the problem.
+
+Understanding these common API error status codes and their solutions can significantly smooth the development process, ensuring more efficient and effective communication between your application and the APIs you rely on.
+
+:::tip[Final tips]
+- Always check the API's own documentation, inspect your request, and look up error messages. If the issue persists, contact the API provider.
+- Once you fix the issue, your calls should return a `200 OK`, which means everything is working as expected!
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/api/securing_your_api_keys_in_private_api_calls.md b/docs/troubleshooting/api/securing_your_api_keys_in_private_api_calls.md
new file mode 100644
index 00000000..4cd558ab
--- /dev/null
+++ b/docs/troubleshooting/api/securing_your_api_keys_in_private_api_calls.md
@@ -0,0 +1,50 @@
+---
+keywords: ['api', 'calls', 'private']
+slug: /troubleshooting/api/securing-your-api-keys-in-private-api-calls
+title: Securing Your API Keys in Private API Calls
+---
+# Securing Your API Keys in Private API Calls
+
+
+Ensuring the security of API keys is a critical aspect of building and maintaining a safe and reliable application. In the realm of private API calls, it's especially important to make sure your API keys are not exposed. This article aims to provide a best-practices guide on where to place your API keys to increase security in a FlutterFlow environment.
+
+**The Misconception: Private API Calls Secure Everything**
+
+Many users assume that simply marking an API call as 'private' is enough to protect all associated data. However, this is not the case. Private API calls run in a Cloud Function, which means any keys or sensitive data in the body will be secure, as long as they're not passed in from the frontend. Even in private API calls, if you're loading an API key from the frontend (like from Firebase remote configs), then you're still exposing it.
+
+## Secure Placement of API Keys in Your Project
+
+ The ideal way to secure an API key is to include it in a request header or directly within the API endpoint URL. This ensures that it is never passed in from the client, thereby maintaining its confidentiality.
+
+ For example, you can hard-code the key directly into your API call header like this:
+
+ ```js
+ { "Authorization": "Bearer YOUR_API_KEY_HERE" }
+ ```
+
+ Or directly within the API endpoint URL:
+
+ ```js
+ https://api.example.com/resource?api_key=YOUR_API_KEY_HERE
+ ```
+ The key should never be a variable that gets passed in from the frontend, as that would make it accessible via the client-side code, defeating the purpose of using private API calls for secure operations.
+
+## Verifying the Security of Your API Key
+
+ After implementing these changes, a straightforward way to verify that your key is secured is by downloading your application code and checking to make sure the API key doesn’t appear in any frontend files.
+
+ Example: Not Secure
+
+ 
+
+ Example: More Secure
+
+ 
+
+
+By adhering to these best practices, you can increase the safety of your API keys even while making private API calls.
+
+:::info
+The goal is to keep all sensitive data, including API keys, away from the client side of the application to ensure optimal security.
+:::
+
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/_category_.json b/docs/troubleshooting/apple-store-deployment/_category_.json
new file mode 100644
index 00000000..6bc0f9fa
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Apple Store Deployment"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/fetch-signing-files/_category_.json b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/_category_.json
new file mode 100644
index 00000000..300ca981
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Fetching Signing Files"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/fetch-signing-files/codemagic_install_pods_failure.md b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/codemagic_install_pods_failure.md
new file mode 100644
index 00000000..1290af83
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/codemagic_install_pods_failure.md
@@ -0,0 +1,56 @@
+---
+keywords: ['deployment', 'flutter', 'exited']
+slug: /troubleshooting/apple-store-deployment/codemagic-install-pods-failure
+title: Codemagic Install Pods Failure
+---
+
+# Codemagic Install Pods Failure
+
+During Codemagic deployment, errors may occur at the **Install Pods** step due to iOS dependency conflicts, unstable code branches, or pod version mismatches. This guide outlines steps to identify and resolve these issues effectively.
+
+:::info[Prerequisites]
+- You are deploying an iOS app using Codemagic.
+- Your project includes custom code or third-party packages.
+:::
+
+## Fix Dependency Conflicts from Custom Code
+
+Custom code or third-party packages may introduce conflicting versions of dependencies that prevent CocoaPods from resolving successfully.
+
+**Steps to Resolve Install Pods Failure:**
+
+- **Check for Dependency Conflicts from Custom Code**
+ Custom or third-party packages may cause version mismatches with FlutterFlow-supported dependencies.
+
+ - Review documentation to ensure package compatibility.
+ - Adjust versions in your `pubspec.yaml` file accordingly.
+ - Run:
+
+ ```bash
+ flutter pub get
+ ```
+
+ 
+
+- **Use a Stable GitHub Branch for Deployment**
+ Deploying from unstable branches can introduce unexpected errors during pod installation.
+
+ - Ensure you're using a branch that passed previous Codemagic deployments.
+ - Remove untested or experimental code.
+ - Revert or refactor recent commits that might break dependencies.
+
+ 
+
+- **Fix Pod Version Compatibility Issues**
+ CocoaPods may fail to resolve dependencies due to incompatible versions or incorrect iOS deployment targets.
+
+ - Update packages like `app_settings` in `pubspec.yaml` to versions compatible with your Flutter version.
+ - Raise the iOS minimum deployment target in Xcode if necessary.
+
+ 
+
+:::tip[Deployment Best Practices]
+- Confirm dependency compatibility before pushing changes.
+- Always deploy from tested GitHub branches.
+- Verify your deployment target supports all pods used.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/fetch-signing-files/codemagic_signing_certificate_limit.md b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/codemagic_signing_certificate_limit.md
new file mode 100644
index 00000000..6e7b8329
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/codemagic_signing_certificate_limit.md
@@ -0,0 +1,46 @@
+---
+keywords: ['signing', 'codemagic', 'certificate']
+slug: /troubleshooting/apple-store-deployment/codemagic-signing-certificate-limit
+title: Codemagic Signing Certificate Limit
+---
+
+# Codemagic Signing Certificate Limit
+
+During iOS deployment, Codemagic attempts to create distribution certificates in your Apple Developer Account. If the maximum number of certificates has already been reached, the build will fail with a certificate creation error.
+
+## Error Message
+
+```bash
+Build failed :|Step 3 script `Fetch signing files` exited with status code 1
+Returned 409: There is a problem with the request entity - You already have a current Distribution certificate or a pending certificate request.
+```
+
+This message indicates that Codemagic cannot proceed because no additional distribution certificates can be created.
+
+:::info[Prerequisites]
+- You are deploying an iOS app using Codemagic.
+- Your Apple Developer Program account is active and linked.
+:::
+
+**Steps to Resolve Certificate Limit Error:**
+
+1. **Access Your Apple Developer Account**
+ Log into your Apple Developer account to manage certificates:
+
+ - Go to the **[Apple Developer Certificates List](https://developer.apple.com/account/resources/certificates/list)**.
+
+2. **Navigate to the Certificates Section**
+ In the **Certificates, Identifiers & Profiles** section:
+
+ - Click on **Certificates**.
+ - Locate all existing **Distribution Certificates**.
+
+3. **Remove Unused or Expired Certificates**
+ Review and delete any unused, expired, or redundant distribution certificates to free up space.
+
+4. **Re-run Deployment**
+ After deleting the certificates, initiate the build process again in FlutterFlow. Codemagic will automatically generate a new certificate as needed.
+
+ :::note
+ The deleted distribution certificates will be recreated automatically by Codemagic during the next build.
+ :::
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/fetch-signing-files/ios_deployment_authentication_error.md b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/ios_deployment_authentication_error.md
new file mode 100644
index 00000000..056281fb
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/fetch-signing-files/ios_deployment_authentication_error.md
@@ -0,0 +1,59 @@
+---
+keywords: ['authentication', 'deployment', 'ios']
+slug: /troubleshooting/apple-store-deployment/ios-deployment-authentication-error
+title: iOS Deployment Authentication Error
+---
+
+# iOS Deployment Authentication Error
+
+During iOS deployment using Codemagic, an authentication credentials error can occur due to misconfigured or expired API tokens for App Store deployment.
+
+The API token used for App Store Connect may be invalid or expired.
+
+:::info
+For details on generating valid tokens, see the **[Apple API Token Documentation](https://developer.apple.com/go/?id=api-generating-tokens)**.
+:::
+
+Here is the error message:
+
+```bash
+Failed Step: Fetch signing files
+GET https://api.appstoreconnect.apple.com/v1/bundleIds?limit=100&sort=name&filter%5Bidentifier%5D=appname.com&filter%5Bplatform%5D=IOS returned 401: Authentication credentials are missing or invalid. Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens
+```
+
+:::info[Prerequisites]
+- Access to your Apple Developer App Store Connect account.
+- Permission to manage API keys under **Users and Access**.
+:::
+
+**Steps to Resolve the Authentication Error:**
+
+1. Open **App Store Connect** and navigate to **Users and Access → Keys**.
+
+2. If prompted, click **Request Access**.
+
+3. Select **Generate API Key** or click the **Add (+)** button.
+
+4. In the popup, provide the following details:
+ - **Name**: Enter a descriptive name for the API Key.
+ - **Access**: Choose the appropriate access level for the key.
+
+5. Click **Generate** to create the API Key.
+
+6. Download the newly created API Key by selecting **Download API Key**.
+
+ :::note
+ If the download option does not appear immediately, refresh the page.
+ :::
+
+7. In **FlutterFlow**, go to **Settings & Integrations → Deployment**.
+
+8. Under **Private Key**, click **Upload Private Key**, select the downloaded API Key file, and click **Open**.
+
+9. Retry your iOS deployment.
+
+ 
+
+:::note
+If the error persists after completing these steps, contact FlutterFlow support via in-app messenger or email at [support@flutterflow.io](mailto:support@flutterflow.io).
+:::
diff --git a/docs/troubleshooting/apple-store-deployment/ios-Signing/_category_.json b/docs/troubleshooting/apple-store-deployment/ios-Signing/_category_.json
new file mode 100644
index 00000000..0e983b8b
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/ios-Signing/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "iOS Signing"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/ios-Signing/download_dsym_file_from_app_store_connect.md b/docs/troubleshooting/apple-store-deployment/ios-Signing/download_dsym_file_from_app_store_connect.md
new file mode 100644
index 00000000..3201fb77
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/ios-Signing/download_dsym_file_from_app_store_connect.md
@@ -0,0 +1,35 @@
+---
+keywords: ['connect', 'download', 'store']
+slug: /troubleshooting/apple-store-deployment/download-dsym-file-from-app-store-connect
+title: Download dSYM File from App Store Connect
+---
+
+# Download dSYM File from App Store Connect
+
+To download the dSYM file from the App Store Connect Developer Console, follow these steps.
+
+:::info[Prerequisites]
+- Access to your Apple Developer account.
+- Your app has at least one build uploaded to App Store Connect.
+:::
+
+**Steps to Download the dSYM File:**
+
+1. **Sign in** to **[App Store Connect](https://appstoreconnect.apple.com/)** with your Apple Developer account.
+2. Open your app.
+3. Select a build from the **TestFlight** tab on your project page.
+4. Open the **Build Metadata** tab.
+5. Under **Include Symbols**, download the dSYM file.
+
+ 
+
+ :::note
+ The dSYM file is only available for builds that have been successfully uploaded to App Store Connect and are in a "processing" or "ready for submission" state.
+ :::
+
+ If the **Download dSYM file** link is not visible, it indicates that the build submission did not complete successfully. In this case:
+
+ 1. Redeploy the build to the App Store.
+ 2. After successful processing, return to the **Build Metadata** tab and download the dSYM file.
+
+ 
diff --git a/docs/troubleshooting/apple-store-deployment/ios-Signing/imagenotification_development_team_error.md b/docs/troubleshooting/apple-store-deployment/ios-Signing/imagenotification_development_team_error.md
new file mode 100644
index 00000000..201b2e4e
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/ios-Signing/imagenotification_development_team_error.md
@@ -0,0 +1,28 @@
+---
+keywords: ['requires', 'sign', 'team']
+slug: /troubleshooting/apple-store-deployment/imagenotification-development-team-error
+title: ImageNotification Development Team Error
+---
+
+# ImageNotification Development Team Error
+
+This error occurs when the **ImageNotification** entitlement is missing in your Apple Developer account. To resolve it, create a new Identifier for `ImageNotification` in your Apple Developer account.
+
+:::info[Prerequisites]
+- Access to your **Apple Developer account**.
+- Permission to manage **Certificates, Identifiers & Profiles**.
+:::
+
+**Steps to Create the Identifier:**
+
+1. Sign in to your **[Apple Developer account](https://developer.apple.com/)**.
+2. Navigate to **Certificates, Identifiers & Profiles**.
+3. Select **Identifiers**.
+4. Click the **Add (+)** button.
+5. Choose **App IDs** and click **Continue**.
+6. Under **Type**, select **App** and click **Continue**.
+7. In the **Description** field, enter `ImageNotification` (case-sensitive).
+8. In the **Bundle ID** field, enter your full bundle ID followed by `.ImageNotification` (for example: `com.example.app.ImageNotification`).
+9. Click **Continue** and then **Register** to complete the setup.
+
+Once this Identifier is added, the signing process should proceed without requiring a development team selection.
diff --git a/docs/troubleshooting/apple-store-deployment/publishing/_category_.json b/docs/troubleshooting/apple-store-deployment/publishing/_category_.json
new file mode 100644
index 00000000..b97faa02
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/publishing/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Publishing"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/apple-store-deployment/publishing/custom_domain_connection_error.md b/docs/troubleshooting/apple-store-deployment/publishing/custom_domain_connection_error.md
new file mode 100644
index 00000000..32cec90c
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/publishing/custom_domain_connection_error.md
@@ -0,0 +1,47 @@
+---
+keywords: ['configuration', 'connect', 'domain']
+slug: /troubleshooting/apple-store-deployment-issues/custom-domain-connection-error
+title: Custom Domain Connection Error
+---
+
+# Custom Domain Connection Error
+
+If you encounter the error shown below after clicking **Connect**, follow these steps to resolve it:
+
+
+
+:::info[Prerequisites]
+- Access to your domain registrar or DNS provider dashboard.
+- DNS management permissions to add or modify DNS records.
+:::
+
+**Steps to Resolve the Error:**
+
+1. **Verify DNS Records**
+
+ - Ensure that you have correctly configured the DNS records required for your custom domain connection.
+ - Add the keys provided by FlutterFlow to your domain’s DNS settings.
+
+ :::note
+ For A records, if your DNS provider requires a name, you can use `"@"`. When you see an empty value, it typically refers to `"@"`.
+ :::
+
+ 
+
+2. **Check for Conflicting Records**
+
+ - Review your DNS configuration to ensure there are no extra or unnecessary records that conflict with the FlutterFlow-provided keys.
+ - For example, if you already have an A record using `"@"`, remove it to avoid conflicts.
+
+ :::note
+ Before removing any existing DNS records, take screenshots and save them for reference.
+ :::
+
+
+ Below are examples of correct configurations in FlutterFlow and your DNS provider:
+
+ 
+
+ 
+
+ By following these steps, you can ensure your custom domain is connected correctly.
diff --git a/docs/troubleshooting/apple-store-deployment/publishing/custom_domain_connection_issues.md b/docs/troubleshooting/apple-store-deployment/publishing/custom_domain_connection_issues.md
new file mode 100644
index 00000000..5daf9c9f
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/publishing/custom_domain_connection_issues.md
@@ -0,0 +1,66 @@
+---
+keywords: ['error', 'custom', 'domains']
+slug: /troubleshooting/apple-store-deployment-issues/custom-domain-connection-issues
+title: Custom Domain Connection Issues
+---
+
+# Custom Domain Connection Issues
+
+This article provides solutions for common problems encountered when connecting custom domains.
+
+:::info[Prerequisites]
+- Access to your domain registrar or DNS provider dashboard.
+- DNS management permissions to add or modify DNS records.
+- Familiarity with DNS record types (A, CNAME, CAA).
+:::
+
+**Steps to Resolve DNS Record Errors:**
+
+1. **Verify DNS Records**
+
+ - Use tools like **[nslookup.io](https://www.nslookup.io)** to verify that your DNS A and CNAME records match the configuration provided in FlutterFlow.
+ - Ensure no conflicting A, AAAA, or CNAME records exist.
+
+ 
+
+2. **Allow Time for DNS Propagation**
+
+ - DNS updates may take up to 24 hours.
+ - Wait at least one hour after making changes before attempting to reconnect your domain.
+
+3. **Retry Connection**
+
+ - After verifying DNS settings and allowing propagation, attempt to reconnect your domain.
+
+4. **Contact Registrar Support If Necessary**
+
+ - If settings are correct and the issue persists after 48 hours, contact your domain registrar to confirm DNS configuration.
+
+**Handling Difficulty Creating DNS Records:**
+
+- Different registrars require different formats for DNS record names:
+ - For root domains (e.g., `example.com`), some require an empty name, others `"@"`, or the full domain name.
+ - For subdomains (e.g., `test.example.com`), some require just `"test"`, others `"test.example.com"`.
+- Consult your registrar’s documentation for exact instructions.
+
+**Resolving 404 Errors After Domain Connection:**
+
+ - Publish the project again after connecting the domain.
+ - This usually resolves most 404 errors related to domain connections.
+
+**Fixing DNS Restrictions for SSL Certificates:**
+
+1. **Check for CAA Records**
+
+ - Use **[nslookup.io](https://www.nslookup.io/domains/your-site-name/dns-records/caa/)** (replace `your-site-name` with your domain) to check CAA records.
+
+2. **Adjust CAA Records**
+
+ - Add `"letsencrypt.org"` to your allowed certificate authorities.
+ - Remove any conflicting CAA records.
+
+ :::note
+ Once CAA records allow `"letsencrypt.org"`, FlutterFlow will be able to generate SSL certificates and complete the domain connection.
+ :::
+
+If issues persist after following these steps, contact FlutterFlow support via Live Chat or email at [support@flutterflow.io](mailto:support@flutterflow.io).
diff --git a/docs/troubleshooting/apple-store-deployment/publishing/web_publishing_faqs.md b/docs/troubleshooting/apple-store-deployment/publishing/web_publishing_faqs.md
new file mode 100644
index 00000000..39941271
--- /dev/null
+++ b/docs/troubleshooting/apple-store-deployment/publishing/web_publishing_faqs.md
@@ -0,0 +1,35 @@
+---
+keywords: ['faqs', 'publishing', 'web']
+slug: /troubleshooting/apple-store-deployment-issues/web-publishing-faqs
+title: Web Publishing FAQs
+---
+
+# Web Publishing FAQs
+
+This article provides answers to frequently asked questions related to web publishing.
+
+:::info[Prerequisites]
+- Basic understanding of FlutterFlow and Flutter web projects.
+- Access to FlutterFlow exported web project files.
+- Familiarity with web hosting concepts.
+:::
+
+- **What certifications does FlutterFlow web hosting comply with?**
+
+ FlutterFlow web hosting runs on Google Compute Engine. For detailed information about compliance and certifications, see **[Google Cloud Compliance](https://cloud.google.com/security/compliance)**.
+
+- **What are the system requirements for self-hosting a FlutterFlow web project?**
+
+ FlutterFlow exports standard Flutter code. To compile and host Flutter web apps yourself, review the **[Flutter Web Deployment Guide](https://docs.flutter.dev/deployment/web)**.
+
+ Compiled Flutter projects produce static files that can be hosted on most web servers without backend technology like Node.js or PHP.
+
+- **Do I need backend technologies to host my FlutterFlow web project?**
+
+ No, compiled Flutter web projects are static content. You can host them on any server capable of serving static files with proper MIME types.
+
+- **What should I consider when hosting on a custom domain?**
+
+ You need to configure DNS settings correctly and ensure SSL certificates are in place for HTTPS. See domain connection guides for more information.
+
+For further questions, contact FlutterFlow support via in-app messenger or email at [support@flutterflow.io](mailto:support@flutterflow.io)
diff --git a/docs/troubleshooting/assets/20250430121118024255.png b/docs/troubleshooting/assets/20250430121118024255.png
new file mode 100644
index 00000000..04960e51
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121118024255.png differ
diff --git a/docs/troubleshooting/assets/20250430121118320891.png b/docs/troubleshooting/assets/20250430121118320891.png
new file mode 100644
index 00000000..14281db6
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121118320891.png differ
diff --git a/docs/troubleshooting/assets/20250430121118592064.png b/docs/troubleshooting/assets/20250430121118592064.png
new file mode 100644
index 00000000..88a773fa
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121118592064.png differ
diff --git a/docs/troubleshooting/assets/20250430121119193097.png b/docs/troubleshooting/assets/20250430121119193097.png
new file mode 100644
index 00000000..d5755690
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121119193097.png differ
diff --git a/docs/troubleshooting/assets/20250430121119493481.png b/docs/troubleshooting/assets/20250430121119493481.png
new file mode 100644
index 00000000..8072147d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121119493481.png differ
diff --git a/docs/troubleshooting/assets/20250430121119754142.png b/docs/troubleshooting/assets/20250430121119754142.png
new file mode 100644
index 00000000..b064a715
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121119754142.png differ
diff --git a/docs/troubleshooting/assets/20250430121120027064.png b/docs/troubleshooting/assets/20250430121120027064.png
new file mode 100644
index 00000000..7132fa1c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121120027064.png differ
diff --git a/docs/troubleshooting/assets/20250430121120324713.png b/docs/troubleshooting/assets/20250430121120324713.png
new file mode 100644
index 00000000..d68a75a5
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121120324713.png differ
diff --git a/docs/troubleshooting/assets/20250430121120614698.png b/docs/troubleshooting/assets/20250430121120614698.png
new file mode 100644
index 00000000..d9fdf1de
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121120614698.png differ
diff --git a/docs/troubleshooting/assets/20250430121120833797.png b/docs/troubleshooting/assets/20250430121120833797.png
new file mode 100644
index 00000000..c42df079
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121120833797.png differ
diff --git a/docs/troubleshooting/assets/20250430121121100378.png b/docs/troubleshooting/assets/20250430121121100378.png
new file mode 100644
index 00000000..39e7b953
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121121100378.png differ
diff --git a/docs/troubleshooting/assets/20250430121121294657.png b/docs/troubleshooting/assets/20250430121121294657.png
new file mode 100644
index 00000000..a24caffb
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121121294657.png differ
diff --git a/docs/troubleshooting/assets/20250430121121827511.png b/docs/troubleshooting/assets/20250430121121827511.png
new file mode 100644
index 00000000..7132fa1c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121121827511.png differ
diff --git a/docs/troubleshooting/assets/20250430121122068343.png b/docs/troubleshooting/assets/20250430121122068343.png
new file mode 100644
index 00000000..8dc53c26
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121122068343.png differ
diff --git a/docs/troubleshooting/assets/20250430121122307123.png b/docs/troubleshooting/assets/20250430121122307123.png
new file mode 100644
index 00000000..429a1df2
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121122307123.png differ
diff --git a/docs/troubleshooting/assets/20250430121122597517.png b/docs/troubleshooting/assets/20250430121122597517.png
new file mode 100644
index 00000000..76743a5e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121122597517.png differ
diff --git a/docs/troubleshooting/assets/20250430121122925141.png b/docs/troubleshooting/assets/20250430121122925141.png
new file mode 100644
index 00000000..3ada42a9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121122925141.png differ
diff --git a/docs/troubleshooting/assets/20250430121123230941.png b/docs/troubleshooting/assets/20250430121123230941.png
new file mode 100644
index 00000000..b21bb9a4
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121123230941.png differ
diff --git a/docs/troubleshooting/assets/20250430121123502329.png b/docs/troubleshooting/assets/20250430121123502329.png
new file mode 100644
index 00000000..b7e70ffe
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121123502329.png differ
diff --git a/docs/troubleshooting/assets/20250430121124107334.png b/docs/troubleshooting/assets/20250430121124107334.png
new file mode 100644
index 00000000..f7d4d9ae
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121124107334.png differ
diff --git a/docs/troubleshooting/assets/20250430121124391823.png b/docs/troubleshooting/assets/20250430121124391823.png
new file mode 100644
index 00000000..dcd3a3d3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121124391823.png differ
diff --git a/docs/troubleshooting/assets/20250430121124669111.png b/docs/troubleshooting/assets/20250430121124669111.png
new file mode 100644
index 00000000..7a570a7c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121124669111.png differ
diff --git a/docs/troubleshooting/assets/20250430121124874853.png b/docs/troubleshooting/assets/20250430121124874853.png
new file mode 100644
index 00000000..100f8c04
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121124874853.png differ
diff --git a/docs/troubleshooting/assets/20250430121126719355.png b/docs/troubleshooting/assets/20250430121126719355.png
new file mode 100644
index 00000000..a7bde73e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121126719355.png differ
diff --git a/docs/troubleshooting/assets/20250430121126936614.png b/docs/troubleshooting/assets/20250430121126936614.png
new file mode 100644
index 00000000..d53a3efa
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121126936614.png differ
diff --git a/docs/troubleshooting/assets/20250430121127218829.png b/docs/troubleshooting/assets/20250430121127218829.png
new file mode 100644
index 00000000..f09f86ce
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121127218829.png differ
diff --git a/docs/troubleshooting/assets/20250430121127501343.png b/docs/troubleshooting/assets/20250430121127501343.png
new file mode 100644
index 00000000..c5d73706
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121127501343.png differ
diff --git a/docs/troubleshooting/assets/20250430121127844921.png b/docs/troubleshooting/assets/20250430121127844921.png
new file mode 100644
index 00000000..bb59460b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121127844921.png differ
diff --git a/docs/troubleshooting/assets/20250430121128170242.png b/docs/troubleshooting/assets/20250430121128170242.png
new file mode 100644
index 00000000..5950045f
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121128170242.png differ
diff --git a/docs/troubleshooting/assets/20250430121128453683.png b/docs/troubleshooting/assets/20250430121128453683.png
new file mode 100644
index 00000000..0e6a8cc2
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121128453683.png differ
diff --git a/docs/troubleshooting/assets/20250430121128741407.png b/docs/troubleshooting/assets/20250430121128741407.png
new file mode 100644
index 00000000..bc817cf4
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121128741407.png differ
diff --git a/docs/troubleshooting/assets/20250430121129014430.png b/docs/troubleshooting/assets/20250430121129014430.png
new file mode 100644
index 00000000..9c683a9f
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121129014430.png differ
diff --git a/docs/troubleshooting/assets/20250430121132533922.png b/docs/troubleshooting/assets/20250430121132533922.png
new file mode 100644
index 00000000..0996692f
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121132533922.png differ
diff --git a/docs/troubleshooting/assets/20250430121132883140.png b/docs/troubleshooting/assets/20250430121132883140.png
new file mode 100644
index 00000000..a2aed359
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121132883140.png differ
diff --git a/docs/troubleshooting/assets/20250430121133219967.png b/docs/troubleshooting/assets/20250430121133219967.png
new file mode 100644
index 00000000..24690709
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121133219967.png differ
diff --git a/docs/troubleshooting/assets/20250430121133833159.png b/docs/troubleshooting/assets/20250430121133833159.png
new file mode 100644
index 00000000..193a8ebd
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121133833159.png differ
diff --git a/docs/troubleshooting/assets/20250430121134186956.png b/docs/troubleshooting/assets/20250430121134186956.png
new file mode 100644
index 00000000..feeba4c1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121134186956.png differ
diff --git a/docs/troubleshooting/assets/20250430121134509618.png b/docs/troubleshooting/assets/20250430121134509618.png
new file mode 100644
index 00000000..f249fdae
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121134509618.png differ
diff --git a/docs/troubleshooting/assets/20250430121137152872.png b/docs/troubleshooting/assets/20250430121137152872.png
new file mode 100644
index 00000000..883f05b8
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121137152872.png differ
diff --git a/docs/troubleshooting/assets/20250430121137421780.png b/docs/troubleshooting/assets/20250430121137421780.png
new file mode 100644
index 00000000..0cc3051a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121137421780.png differ
diff --git a/docs/troubleshooting/assets/20250430121138021235.png b/docs/troubleshooting/assets/20250430121138021235.png
new file mode 100644
index 00000000..2c40d909
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121138021235.png differ
diff --git a/docs/troubleshooting/assets/20250430121138830209.png b/docs/troubleshooting/assets/20250430121138830209.png
new file mode 100644
index 00000000..c0cc511a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121138830209.png differ
diff --git a/docs/troubleshooting/assets/20250430121139816551.gif b/docs/troubleshooting/assets/20250430121139816551.gif
new file mode 100644
index 00000000..5ad37aad
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121139816551.gif differ
diff --git a/docs/troubleshooting/assets/20250430121142594662.png b/docs/troubleshooting/assets/20250430121142594662.png
new file mode 100644
index 00000000..c95846a7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121142594662.png differ
diff --git a/docs/troubleshooting/assets/20250430121143268592.png b/docs/troubleshooting/assets/20250430121143268592.png
new file mode 100644
index 00000000..a76633ee
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121143268592.png differ
diff --git a/docs/troubleshooting/assets/20250430121143614166.png b/docs/troubleshooting/assets/20250430121143614166.png
new file mode 100644
index 00000000..dc0bb50b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121143614166.png differ
diff --git a/docs/troubleshooting/assets/20250430121143935249.png b/docs/troubleshooting/assets/20250430121143935249.png
new file mode 100644
index 00000000..91ab9f48
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121143935249.png differ
diff --git a/docs/troubleshooting/assets/20250430121144228150.png b/docs/troubleshooting/assets/20250430121144228150.png
new file mode 100644
index 00000000..5fa6e512
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121144228150.png differ
diff --git a/docs/troubleshooting/assets/20250430121144509497.png b/docs/troubleshooting/assets/20250430121144509497.png
new file mode 100644
index 00000000..d2c999ec
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121144509497.png differ
diff --git a/docs/troubleshooting/assets/20250430121144853131.png b/docs/troubleshooting/assets/20250430121144853131.png
new file mode 100644
index 00000000..c10f94ca
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121144853131.png differ
diff --git a/docs/troubleshooting/assets/20250430121145202849.png b/docs/troubleshooting/assets/20250430121145202849.png
new file mode 100644
index 00000000..490f9555
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121145202849.png differ
diff --git a/docs/troubleshooting/assets/20250430121145711998.png b/docs/troubleshooting/assets/20250430121145711998.png
new file mode 100644
index 00000000..7132fa1c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121145711998.png differ
diff --git a/docs/troubleshooting/assets/20250430121145949036.png b/docs/troubleshooting/assets/20250430121145949036.png
new file mode 100644
index 00000000..8dc53c26
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121145949036.png differ
diff --git a/docs/troubleshooting/assets/20250430121146161973.png b/docs/troubleshooting/assets/20250430121146161973.png
new file mode 100644
index 00000000..429a1df2
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121146161973.png differ
diff --git a/docs/troubleshooting/assets/20250430121146400049.png b/docs/troubleshooting/assets/20250430121146400049.png
new file mode 100644
index 00000000..76743a5e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121146400049.png differ
diff --git a/docs/troubleshooting/assets/20250430121146604033.png b/docs/troubleshooting/assets/20250430121146604033.png
new file mode 100644
index 00000000..3ada42a9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121146604033.png differ
diff --git a/docs/troubleshooting/assets/20250430121146854018.png b/docs/troubleshooting/assets/20250430121146854018.png
new file mode 100644
index 00000000..b21bb9a4
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121146854018.png differ
diff --git a/docs/troubleshooting/assets/20250430121147068781.png b/docs/troubleshooting/assets/20250430121147068781.png
new file mode 100644
index 00000000..b7e70ffe
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121147068781.png differ
diff --git a/docs/troubleshooting/assets/20250430121147385978.png b/docs/troubleshooting/assets/20250430121147385978.png
new file mode 100644
index 00000000..e19acd1a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121147385978.png differ
diff --git a/docs/troubleshooting/assets/20250430121147683388.png b/docs/troubleshooting/assets/20250430121147683388.png
new file mode 100644
index 00000000..ed4812e9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121147683388.png differ
diff --git a/docs/troubleshooting/assets/20250430121148301014.png b/docs/troubleshooting/assets/20250430121148301014.png
new file mode 100644
index 00000000..a1659a6a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121148301014.png differ
diff --git a/docs/troubleshooting/assets/20250430121148811672.png b/docs/troubleshooting/assets/20250430121148811672.png
new file mode 100644
index 00000000..cd6e44e7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121148811672.png differ
diff --git a/docs/troubleshooting/assets/20250430121149388590.png b/docs/troubleshooting/assets/20250430121149388590.png
new file mode 100644
index 00000000..95e09803
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121149388590.png differ
diff --git a/docs/troubleshooting/assets/20250430121149749937.png b/docs/troubleshooting/assets/20250430121149749937.png
new file mode 100644
index 00000000..2a15a6a0
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121149749937.png differ
diff --git a/docs/troubleshooting/assets/20250430121150348694.png b/docs/troubleshooting/assets/20250430121150348694.png
new file mode 100644
index 00000000..dd869186
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121150348694.png differ
diff --git a/docs/troubleshooting/assets/20250430121150651702.png b/docs/troubleshooting/assets/20250430121150651702.png
new file mode 100644
index 00000000..782d0f06
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121150651702.png differ
diff --git a/docs/troubleshooting/assets/20250430121157297846.png b/docs/troubleshooting/assets/20250430121157297846.png
new file mode 100644
index 00000000..67627efc
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121157297846.png differ
diff --git a/docs/troubleshooting/assets/20250430121157601185.png b/docs/troubleshooting/assets/20250430121157601185.png
new file mode 100644
index 00000000..800ec0e1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121157601185.png differ
diff --git a/docs/troubleshooting/assets/20250430121203371000.png b/docs/troubleshooting/assets/20250430121203371000.png
new file mode 100644
index 00000000..6b9e7040
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121203371000.png differ
diff --git a/docs/troubleshooting/assets/20250430121203619318.png b/docs/troubleshooting/assets/20250430121203619318.png
new file mode 100644
index 00000000..15c8ebd6
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121203619318.png differ
diff --git a/docs/troubleshooting/assets/20250430121203911156.png b/docs/troubleshooting/assets/20250430121203911156.png
new file mode 100644
index 00000000..2f0c940b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121203911156.png differ
diff --git a/docs/troubleshooting/assets/20250430121212734475.png b/docs/troubleshooting/assets/20250430121212734475.png
new file mode 100644
index 00000000..205c45ec
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121212734475.png differ
diff --git a/docs/troubleshooting/assets/20250430121213011292.png b/docs/troubleshooting/assets/20250430121213011292.png
new file mode 100644
index 00000000..e27abaf6
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121213011292.png differ
diff --git a/docs/troubleshooting/assets/20250430121213284704.png b/docs/troubleshooting/assets/20250430121213284704.png
new file mode 100644
index 00000000..6402ac68
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121213284704.png differ
diff --git a/docs/troubleshooting/assets/20250430121213612267.png b/docs/troubleshooting/assets/20250430121213612267.png
new file mode 100644
index 00000000..37eee8cc
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121213612267.png differ
diff --git a/docs/troubleshooting/assets/20250430121213915514.png b/docs/troubleshooting/assets/20250430121213915514.png
new file mode 100644
index 00000000..ab261ae3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121213915514.png differ
diff --git a/docs/troubleshooting/assets/20250430121214190877.png b/docs/troubleshooting/assets/20250430121214190877.png
new file mode 100644
index 00000000..92c4c27c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121214190877.png differ
diff --git a/docs/troubleshooting/assets/20250430121214486513.png b/docs/troubleshooting/assets/20250430121214486513.png
new file mode 100644
index 00000000..b74ff2a1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121214486513.png differ
diff --git a/docs/troubleshooting/assets/20250430121214790195.png b/docs/troubleshooting/assets/20250430121214790195.png
new file mode 100644
index 00000000..42716d90
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121214790195.png differ
diff --git a/docs/troubleshooting/assets/20250430121215127010.png b/docs/troubleshooting/assets/20250430121215127010.png
new file mode 100644
index 00000000..5e3af22d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121215127010.png differ
diff --git a/docs/troubleshooting/assets/20250430121215442199.png b/docs/troubleshooting/assets/20250430121215442199.png
new file mode 100644
index 00000000..042b9804
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121215442199.png differ
diff --git a/docs/troubleshooting/assets/20250430121215729191.png b/docs/troubleshooting/assets/20250430121215729191.png
new file mode 100644
index 00000000..d5102dc3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121215729191.png differ
diff --git a/docs/troubleshooting/assets/20250430121216632942.png b/docs/troubleshooting/assets/20250430121216632942.png
new file mode 100644
index 00000000..af526401
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121216632942.png differ
diff --git a/docs/troubleshooting/assets/20250430121216962021.png b/docs/troubleshooting/assets/20250430121216962021.png
new file mode 100644
index 00000000..65589d27
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121216962021.png differ
diff --git a/docs/troubleshooting/assets/20250430121219360101.png b/docs/troubleshooting/assets/20250430121219360101.png
new file mode 100644
index 00000000..436addd6
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121219360101.png differ
diff --git a/docs/troubleshooting/assets/20250430121219606895.png b/docs/troubleshooting/assets/20250430121219606895.png
new file mode 100644
index 00000000..a64dca48
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121219606895.png differ
diff --git a/docs/troubleshooting/assets/20250430121219871237.png b/docs/troubleshooting/assets/20250430121219871237.png
new file mode 100644
index 00000000..7e5c9903
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121219871237.png differ
diff --git a/docs/troubleshooting/assets/20250430121220084430.png b/docs/troubleshooting/assets/20250430121220084430.png
new file mode 100644
index 00000000..577aee53
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121220084430.png differ
diff --git a/docs/troubleshooting/assets/20250430121220338400.png b/docs/troubleshooting/assets/20250430121220338400.png
new file mode 100644
index 00000000..03fd1157
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121220338400.png differ
diff --git a/docs/troubleshooting/assets/20250430121220879251.png b/docs/troubleshooting/assets/20250430121220879251.png
new file mode 100644
index 00000000..74a91eef
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121220879251.png differ
diff --git a/docs/troubleshooting/assets/20250430121221066642.png b/docs/troubleshooting/assets/20250430121221066642.png
new file mode 100644
index 00000000..aa4eca7b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121221066642.png differ
diff --git a/docs/troubleshooting/assets/20250430121224235710.png b/docs/troubleshooting/assets/20250430121224235710.png
new file mode 100644
index 00000000..fa8e51ec
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121224235710.png differ
diff --git a/docs/troubleshooting/assets/20250430121224547832.png b/docs/troubleshooting/assets/20250430121224547832.png
new file mode 100644
index 00000000..a5157380
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121224547832.png differ
diff --git a/docs/troubleshooting/assets/20250430121224874215.png b/docs/troubleshooting/assets/20250430121224874215.png
new file mode 100644
index 00000000..df356ebb
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121224874215.png differ
diff --git a/docs/troubleshooting/assets/20250430121228520630.png b/docs/troubleshooting/assets/20250430121228520630.png
new file mode 100644
index 00000000..97b6f8d9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121228520630.png differ
diff --git a/docs/troubleshooting/assets/20250430121228826304.png b/docs/troubleshooting/assets/20250430121228826304.png
new file mode 100644
index 00000000..5e3af22d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121228826304.png differ
diff --git a/docs/troubleshooting/assets/20250430121229163844.png b/docs/troubleshooting/assets/20250430121229163844.png
new file mode 100644
index 00000000..042b9804
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121229163844.png differ
diff --git a/docs/troubleshooting/assets/20250430121229476348.png b/docs/troubleshooting/assets/20250430121229476348.png
new file mode 100644
index 00000000..d5102dc3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121229476348.png differ
diff --git a/docs/troubleshooting/assets/20250430121230522324.png b/docs/troubleshooting/assets/20250430121230522324.png
new file mode 100644
index 00000000..1eb06dd7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121230522324.png differ
diff --git a/docs/troubleshooting/assets/20250430121230823138.png b/docs/troubleshooting/assets/20250430121230823138.png
new file mode 100644
index 00000000..ad4bd60e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121230823138.png differ
diff --git a/docs/troubleshooting/assets/20250430121239249713.png b/docs/troubleshooting/assets/20250430121239249713.png
new file mode 100644
index 00000000..4f3d7b71
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121239249713.png differ
diff --git a/docs/troubleshooting/assets/20250430121239492027.png b/docs/troubleshooting/assets/20250430121239492027.png
new file mode 100644
index 00000000..5cd0efd9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121239492027.png differ
diff --git a/docs/troubleshooting/assets/20250430121239708989.png b/docs/troubleshooting/assets/20250430121239708989.png
new file mode 100644
index 00000000..a8fd874f
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121239708989.png differ
diff --git a/docs/troubleshooting/assets/20250430121239967301.png b/docs/troubleshooting/assets/20250430121239967301.png
new file mode 100644
index 00000000..23289996
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121239967301.png differ
diff --git a/docs/troubleshooting/assets/20250430121240227391.png b/docs/troubleshooting/assets/20250430121240227391.png
new file mode 100644
index 00000000..4baa9bc1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121240227391.png differ
diff --git a/docs/troubleshooting/assets/20250430121240508011.png b/docs/troubleshooting/assets/20250430121240508011.png
new file mode 100644
index 00000000..751a8660
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121240508011.png differ
diff --git a/docs/troubleshooting/assets/20250430121240818334.png b/docs/troubleshooting/assets/20250430121240818334.png
new file mode 100644
index 00000000..7307d463
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121240818334.png differ
diff --git a/docs/troubleshooting/assets/20250430121241416661.png b/docs/troubleshooting/assets/20250430121241416661.png
new file mode 100644
index 00000000..58c3e224
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121241416661.png differ
diff --git a/docs/troubleshooting/assets/20250430121241690449.gif b/docs/troubleshooting/assets/20250430121241690449.gif
new file mode 100644
index 00000000..f3a3a78b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121241690449.gif differ
diff --git a/docs/troubleshooting/assets/20250430121241899370.png b/docs/troubleshooting/assets/20250430121241899370.png
new file mode 100644
index 00000000..c56fdb46
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121241899370.png differ
diff --git a/docs/troubleshooting/assets/20250430121242149430.png b/docs/troubleshooting/assets/20250430121242149430.png
new file mode 100644
index 00000000..553f9ffc
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121242149430.png differ
diff --git a/docs/troubleshooting/assets/20250430121242530889.png b/docs/troubleshooting/assets/20250430121242530889.png
new file mode 100644
index 00000000..faf628bf
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121242530889.png differ
diff --git a/docs/troubleshooting/assets/20250430121242814005.png b/docs/troubleshooting/assets/20250430121242814005.png
new file mode 100644
index 00000000..83b5788c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121242814005.png differ
diff --git a/docs/troubleshooting/assets/20250430121243410633.png b/docs/troubleshooting/assets/20250430121243410633.png
new file mode 100644
index 00000000..cef1db2a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121243410633.png differ
diff --git a/docs/troubleshooting/assets/20250430121243684493.png b/docs/troubleshooting/assets/20250430121243684493.png
new file mode 100644
index 00000000..012399b5
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121243684493.png differ
diff --git a/docs/troubleshooting/assets/20250430121243982678.png b/docs/troubleshooting/assets/20250430121243982678.png
new file mode 100644
index 00000000..07874d92
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121243982678.png differ
diff --git a/docs/troubleshooting/assets/20250430121244255037.png b/docs/troubleshooting/assets/20250430121244255037.png
new file mode 100644
index 00000000..a91a192e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121244255037.png differ
diff --git a/docs/troubleshooting/assets/20250430121248035007.png b/docs/troubleshooting/assets/20250430121248035007.png
new file mode 100644
index 00000000..b43dac23
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121248035007.png differ
diff --git a/docs/troubleshooting/assets/20250430121248379992.png b/docs/troubleshooting/assets/20250430121248379992.png
new file mode 100644
index 00000000..1a62ee22
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121248379992.png differ
diff --git a/docs/troubleshooting/assets/20250430121249048672.gif b/docs/troubleshooting/assets/20250430121249048672.gif
new file mode 100644
index 00000000..2cf8259a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121249048672.gif differ
diff --git a/docs/troubleshooting/assets/20250430121250214649.png b/docs/troubleshooting/assets/20250430121250214649.png
new file mode 100644
index 00000000..291efff1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121250214649.png differ
diff --git a/docs/troubleshooting/assets/20250430121250453056.png b/docs/troubleshooting/assets/20250430121250453056.png
new file mode 100644
index 00000000..13fd1cf1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121250453056.png differ
diff --git a/docs/troubleshooting/assets/20250430121252902305.png b/docs/troubleshooting/assets/20250430121252902305.png
new file mode 100644
index 00000000..4ffa4cc3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121252902305.png differ
diff --git a/docs/troubleshooting/assets/20250430121253238523.png b/docs/troubleshooting/assets/20250430121253238523.png
new file mode 100644
index 00000000..28ef0a15
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121253238523.png differ
diff --git a/docs/troubleshooting/assets/20250430121257965718.png b/docs/troubleshooting/assets/20250430121257965718.png
new file mode 100644
index 00000000..2fbe1899
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121257965718.png differ
diff --git a/docs/troubleshooting/assets/20250430121258232331.png b/docs/troubleshooting/assets/20250430121258232331.png
new file mode 100644
index 00000000..264ee3ac
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121258232331.png differ
diff --git a/docs/troubleshooting/assets/20250430121259958091.png b/docs/troubleshooting/assets/20250430121259958091.png
new file mode 100644
index 00000000..39d55c5c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121259958091.png differ
diff --git a/docs/troubleshooting/assets/20250430121300291232.png b/docs/troubleshooting/assets/20250430121300291232.png
new file mode 100644
index 00000000..b69f81c1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121300291232.png differ
diff --git a/docs/troubleshooting/assets/20250430121300291238.png b/docs/troubleshooting/assets/20250430121300291238.png
new file mode 100644
index 00000000..40c1ea58
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121300291238.png differ
diff --git a/docs/troubleshooting/assets/20250430121300815719.png b/docs/troubleshooting/assets/20250430121300815719.png
new file mode 100644
index 00000000..e0eeb7ed
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121300815719.png differ
diff --git a/docs/troubleshooting/assets/20250430121301101693.png b/docs/troubleshooting/assets/20250430121301101693.png
new file mode 100644
index 00000000..68f4ad9a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121301101693.png differ
diff --git a/docs/troubleshooting/assets/20250430121302960895.png b/docs/troubleshooting/assets/20250430121302960895.png
new file mode 100644
index 00000000..eb266a71
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121302960895.png differ
diff --git a/docs/troubleshooting/assets/20250430121303270464.png b/docs/troubleshooting/assets/20250430121303270464.png
new file mode 100644
index 00000000..3364ca90
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121303270464.png differ
diff --git a/docs/troubleshooting/assets/20250430121304770472.png b/docs/troubleshooting/assets/20250430121304770472.png
new file mode 100644
index 00000000..4bf03f3d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121304770472.png differ
diff --git a/docs/troubleshooting/assets/20250430121305056379.png b/docs/troubleshooting/assets/20250430121305056379.png
new file mode 100644
index 00000000..c55cb112
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121305056379.png differ
diff --git a/docs/troubleshooting/assets/20250430121305295728.png b/docs/troubleshooting/assets/20250430121305295728.png
new file mode 100644
index 00000000..27770f6c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121305295728.png differ
diff --git a/docs/troubleshooting/assets/20250430121305526883.png b/docs/troubleshooting/assets/20250430121305526883.png
new file mode 100644
index 00000000..588942db
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121305526883.png differ
diff --git a/docs/troubleshooting/assets/20250430121305771267.png b/docs/troubleshooting/assets/20250430121305771267.png
new file mode 100644
index 00000000..6487fde1
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121305771267.png differ
diff --git a/docs/troubleshooting/assets/20250430121306066982.png b/docs/troubleshooting/assets/20250430121306066982.png
new file mode 100644
index 00000000..64eb91b6
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121306066982.png differ
diff --git a/docs/troubleshooting/assets/20250430121306294908.png b/docs/troubleshooting/assets/20250430121306294908.png
new file mode 100644
index 00000000..cb8b31c7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121306294908.png differ
diff --git a/docs/troubleshooting/assets/20250430121306553330.png b/docs/troubleshooting/assets/20250430121306553330.png
new file mode 100644
index 00000000..436d248f
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121306553330.png differ
diff --git a/docs/troubleshooting/assets/20250430121306835223.png b/docs/troubleshooting/assets/20250430121306835223.png
new file mode 100644
index 00000000..d6598a5a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121306835223.png differ
diff --git a/docs/troubleshooting/assets/20250430121309740417.png b/docs/troubleshooting/assets/20250430121309740417.png
new file mode 100644
index 00000000..f2e4ca46
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121309740417.png differ
diff --git a/docs/troubleshooting/assets/20250430121310019673.png b/docs/troubleshooting/assets/20250430121310019673.png
new file mode 100644
index 00000000..838ce613
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121310019673.png differ
diff --git a/docs/troubleshooting/assets/20250430121310317285.png b/docs/troubleshooting/assets/20250430121310317285.png
new file mode 100644
index 00000000..ce14ca2a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121310317285.png differ
diff --git a/docs/troubleshooting/assets/20250430121310619096.png b/docs/troubleshooting/assets/20250430121310619096.png
new file mode 100644
index 00000000..0ed08202
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121310619096.png differ
diff --git a/docs/troubleshooting/assets/20250430121310959552.png b/docs/troubleshooting/assets/20250430121310959552.png
new file mode 100644
index 00000000..79014d47
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121310959552.png differ
diff --git a/docs/troubleshooting/assets/20250430121320431269.png b/docs/troubleshooting/assets/20250430121320431269.png
new file mode 100644
index 00000000..e360d919
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121320431269.png differ
diff --git a/docs/troubleshooting/assets/20250430121320759595.png b/docs/troubleshooting/assets/20250430121320759595.png
new file mode 100644
index 00000000..cd985acc
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121320759595.png differ
diff --git a/docs/troubleshooting/assets/20250430121321051936.png b/docs/troubleshooting/assets/20250430121321051936.png
new file mode 100644
index 00000000..96ed82cd
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121321051936.png differ
diff --git a/docs/troubleshooting/assets/20250430121322843622.gif b/docs/troubleshooting/assets/20250430121322843622.gif
new file mode 100644
index 00000000..3d10e257
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121322843622.gif differ
diff --git a/docs/troubleshooting/assets/20250430121323364253.gif b/docs/troubleshooting/assets/20250430121323364253.gif
new file mode 100644
index 00000000..db231413
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121323364253.gif differ
diff --git a/docs/troubleshooting/assets/20250430121324152439.png b/docs/troubleshooting/assets/20250430121324152439.png
new file mode 100644
index 00000000..56f993c5
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121324152439.png differ
diff --git a/docs/troubleshooting/assets/20250430121324382074.png b/docs/troubleshooting/assets/20250430121324382074.png
new file mode 100644
index 00000000..c6b9079d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121324382074.png differ
diff --git a/docs/troubleshooting/assets/20250430121324695186.png b/docs/troubleshooting/assets/20250430121324695186.png
new file mode 100644
index 00000000..343d09f3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121324695186.png differ
diff --git a/docs/troubleshooting/assets/20250430121324981835.png b/docs/troubleshooting/assets/20250430121324981835.png
new file mode 100644
index 00000000..7a8c0feb
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121324981835.png differ
diff --git a/docs/troubleshooting/assets/20250430121325311155.png b/docs/troubleshooting/assets/20250430121325311155.png
new file mode 100644
index 00000000..e9cb39ff
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121325311155.png differ
diff --git a/docs/troubleshooting/assets/20250430121325659677.png b/docs/troubleshooting/assets/20250430121325659677.png
new file mode 100644
index 00000000..feb64565
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121325659677.png differ
diff --git a/docs/troubleshooting/assets/20250430121325972589.png b/docs/troubleshooting/assets/20250430121325972589.png
new file mode 100644
index 00000000..470b2d65
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121325972589.png differ
diff --git a/docs/troubleshooting/assets/20250430121326300880.png b/docs/troubleshooting/assets/20250430121326300880.png
new file mode 100644
index 00000000..b0f40e26
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121326300880.png differ
diff --git a/docs/troubleshooting/assets/20250430121326628836.png b/docs/troubleshooting/assets/20250430121326628836.png
new file mode 100644
index 00000000..50a37b8b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121326628836.png differ
diff --git a/docs/troubleshooting/assets/20250430121327988277.gif b/docs/troubleshooting/assets/20250430121327988277.gif
new file mode 100644
index 00000000..1bdbc639
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121327988277.gif differ
diff --git a/docs/troubleshooting/assets/20250430121330484821.png b/docs/troubleshooting/assets/20250430121330484821.png
new file mode 100644
index 00000000..86c47f03
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121330484821.png differ
diff --git a/docs/troubleshooting/assets/20250430121330727549.png b/docs/troubleshooting/assets/20250430121330727549.png
new file mode 100644
index 00000000..77f0bc5e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121330727549.png differ
diff --git a/docs/troubleshooting/assets/20250430121331069027.png b/docs/troubleshooting/assets/20250430121331069027.png
new file mode 100644
index 00000000..ec470a63
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121331069027.png differ
diff --git a/docs/troubleshooting/assets/20250430121331806679.png b/docs/troubleshooting/assets/20250430121331806679.png
new file mode 100644
index 00000000..747e3473
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121331806679.png differ
diff --git a/docs/troubleshooting/assets/20250430121332062568.png b/docs/troubleshooting/assets/20250430121332062568.png
new file mode 100644
index 00000000..b45e9457
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121332062568.png differ
diff --git a/docs/troubleshooting/assets/20250430121336383410.gif b/docs/troubleshooting/assets/20250430121336383410.gif
new file mode 100644
index 00000000..bf975aa0
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121336383410.gif differ
diff --git a/docs/troubleshooting/assets/20250430121346608131.png b/docs/troubleshooting/assets/20250430121346608131.png
new file mode 100644
index 00000000..48705827
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121346608131.png differ
diff --git a/docs/troubleshooting/assets/20250430121346890273.png b/docs/troubleshooting/assets/20250430121346890273.png
new file mode 100644
index 00000000..b38450fc
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121346890273.png differ
diff --git a/docs/troubleshooting/assets/20250430121347217644.png b/docs/troubleshooting/assets/20250430121347217644.png
new file mode 100644
index 00000000..e738ccc3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121347217644.png differ
diff --git a/docs/troubleshooting/assets/20250430121347593094.png b/docs/troubleshooting/assets/20250430121347593094.png
new file mode 100644
index 00000000..e7b27b96
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121347593094.png differ
diff --git a/docs/troubleshooting/assets/20250430121347925706.png b/docs/troubleshooting/assets/20250430121347925706.png
new file mode 100644
index 00000000..a52221bb
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121347925706.png differ
diff --git a/docs/troubleshooting/assets/20250430121348293622.gif b/docs/troubleshooting/assets/20250430121348293622.gif
new file mode 100644
index 00000000..3e6daeed
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121348293622.gif differ
diff --git a/docs/troubleshooting/assets/20250430121350517804.png b/docs/troubleshooting/assets/20250430121350517804.png
new file mode 100644
index 00000000..100f8c04
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121350517804.png differ
diff --git a/docs/troubleshooting/assets/20250430121350799148.png b/docs/troubleshooting/assets/20250430121350799148.png
new file mode 100644
index 00000000..dcd3a3d3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121350799148.png differ
diff --git a/docs/troubleshooting/assets/20250430121351077308.png b/docs/troubleshooting/assets/20250430121351077308.png
new file mode 100644
index 00000000..7a570a7c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121351077308.png differ
diff --git a/docs/troubleshooting/assets/20250430121351345482.png b/docs/troubleshooting/assets/20250430121351345482.png
new file mode 100644
index 00000000..f7d4d9ae
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121351345482.png differ
diff --git a/docs/troubleshooting/assets/20250430121354480726.png b/docs/troubleshooting/assets/20250430121354480726.png
new file mode 100644
index 00000000..4967be6a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121354480726.png differ
diff --git a/docs/troubleshooting/assets/20250430121355282620.gif b/docs/troubleshooting/assets/20250430121355282620.gif
new file mode 100644
index 00000000..447875bc
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121355282620.gif differ
diff --git a/docs/troubleshooting/assets/20250430121355575413.gif b/docs/troubleshooting/assets/20250430121355575413.gif
new file mode 100644
index 00000000..6b160f0a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121355575413.gif differ
diff --git a/docs/troubleshooting/assets/20250430121357585709.png b/docs/troubleshooting/assets/20250430121357585709.png
new file mode 100644
index 00000000..f68eb3ac
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121357585709.png differ
diff --git a/docs/troubleshooting/assets/20250430121357870887.png b/docs/troubleshooting/assets/20250430121357870887.png
new file mode 100644
index 00000000..df7a333c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121357870887.png differ
diff --git a/docs/troubleshooting/assets/20250430121409119593.png b/docs/troubleshooting/assets/20250430121409119593.png
new file mode 100644
index 00000000..1ac0d65b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121409119593.png differ
diff --git a/docs/troubleshooting/assets/20250430121409391507.png b/docs/troubleshooting/assets/20250430121409391507.png
new file mode 100644
index 00000000..ade1092a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121409391507.png differ
diff --git a/docs/troubleshooting/assets/20250430121439158816.png b/docs/troubleshooting/assets/20250430121439158816.png
new file mode 100644
index 00000000..b57eb2e9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121439158816.png differ
diff --git a/docs/troubleshooting/assets/20250430121439605476.png b/docs/troubleshooting/assets/20250430121439605476.png
new file mode 100644
index 00000000..22cc8932
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121439605476.png differ
diff --git a/docs/troubleshooting/assets/20250430121440000724.png b/docs/troubleshooting/assets/20250430121440000724.png
new file mode 100644
index 00000000..e69fd5cf
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121440000724.png differ
diff --git a/docs/troubleshooting/assets/20250430121440426479.png b/docs/troubleshooting/assets/20250430121440426479.png
new file mode 100644
index 00000000..67e8395f
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121440426479.png differ
diff --git a/docs/troubleshooting/assets/20250430121440906814.png b/docs/troubleshooting/assets/20250430121440906814.png
new file mode 100644
index 00000000..68375507
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121440906814.png differ
diff --git a/docs/troubleshooting/assets/20250430121441325585.png b/docs/troubleshooting/assets/20250430121441325585.png
new file mode 100644
index 00000000..2072ce6e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121441325585.png differ
diff --git a/docs/troubleshooting/assets/20250430121441664549.png b/docs/troubleshooting/assets/20250430121441664549.png
new file mode 100644
index 00000000..77f0bc5e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121441664549.png differ
diff --git a/docs/troubleshooting/assets/20250430121442125737.png b/docs/troubleshooting/assets/20250430121442125737.png
new file mode 100644
index 00000000..ec470a63
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121442125737.png differ
diff --git a/docs/troubleshooting/assets/20250430121442525774.png b/docs/troubleshooting/assets/20250430121442525774.png
new file mode 100644
index 00000000..68375507
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121442525774.png differ
diff --git a/docs/troubleshooting/assets/20250430121442863891.png b/docs/troubleshooting/assets/20250430121442863891.png
new file mode 100644
index 00000000..2072ce6e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121442863891.png differ
diff --git a/docs/troubleshooting/assets/20250430121443139294.png b/docs/troubleshooting/assets/20250430121443139294.png
new file mode 100644
index 00000000..77f0bc5e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121443139294.png differ
diff --git a/docs/troubleshooting/assets/20250430121443525154.png b/docs/troubleshooting/assets/20250430121443525154.png
new file mode 100644
index 00000000..ec470a63
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121443525154.png differ
diff --git a/docs/troubleshooting/assets/20250430121444122926.png b/docs/troubleshooting/assets/20250430121444122926.png
new file mode 100644
index 00000000..dc509500
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121444122926.png differ
diff --git a/docs/troubleshooting/assets/20250430121444364083.png b/docs/troubleshooting/assets/20250430121444364083.png
new file mode 100644
index 00000000..765b4892
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121444364083.png differ
diff --git a/docs/troubleshooting/assets/20250430121444571412.png b/docs/troubleshooting/assets/20250430121444571412.png
new file mode 100644
index 00000000..e3948cc7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121444571412.png differ
diff --git a/docs/troubleshooting/assets/20250430121444783602.png b/docs/troubleshooting/assets/20250430121444783602.png
new file mode 100644
index 00000000..f8250d6a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121444783602.png differ
diff --git a/docs/troubleshooting/assets/20250430121445020637.png b/docs/troubleshooting/assets/20250430121445020637.png
new file mode 100644
index 00000000..e3899e1d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121445020637.png differ
diff --git a/docs/troubleshooting/assets/20250430121445238952.png b/docs/troubleshooting/assets/20250430121445238952.png
new file mode 100644
index 00000000..1bcc7670
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121445238952.png differ
diff --git a/docs/troubleshooting/assets/20250430121459400158.png b/docs/troubleshooting/assets/20250430121459400158.png
new file mode 100644
index 00000000..3f73fc59
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121459400158.png differ
diff --git a/docs/troubleshooting/assets/20250430121507937548.png b/docs/troubleshooting/assets/20250430121507937548.png
new file mode 100644
index 00000000..229fc6a7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121507937548.png differ
diff --git a/docs/troubleshooting/assets/20250430121508288240.png b/docs/troubleshooting/assets/20250430121508288240.png
new file mode 100644
index 00000000..cf3184da
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121508288240.png differ
diff --git a/docs/troubleshooting/assets/20250430121508604665.png b/docs/troubleshooting/assets/20250430121508604665.png
new file mode 100644
index 00000000..7a17da5a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121508604665.png differ
diff --git a/docs/troubleshooting/assets/20250430121508962664.png b/docs/troubleshooting/assets/20250430121508962664.png
new file mode 100644
index 00000000..97153aaf
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121508962664.png differ
diff --git a/docs/troubleshooting/assets/20250430121513060363.png b/docs/troubleshooting/assets/20250430121513060363.png
new file mode 100644
index 00000000..747e3473
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121513060363.png differ
diff --git a/docs/troubleshooting/assets/20250430121513225263.png b/docs/troubleshooting/assets/20250430121513225263.png
new file mode 100644
index 00000000..b45e9457
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121513225263.png differ
diff --git a/docs/troubleshooting/assets/20250430121514217884.jpg b/docs/troubleshooting/assets/20250430121514217884.jpg
new file mode 100644
index 00000000..c59aef87
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121514217884.jpg differ
diff --git a/docs/troubleshooting/assets/20250430121514497717.png b/docs/troubleshooting/assets/20250430121514497717.png
new file mode 100644
index 00000000..a760899b
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121514497717.png differ
diff --git a/docs/troubleshooting/assets/20250430121514756330.png b/docs/troubleshooting/assets/20250430121514756330.png
new file mode 100644
index 00000000..73e3a550
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121514756330.png differ
diff --git a/docs/troubleshooting/assets/20250430121515088626.png b/docs/troubleshooting/assets/20250430121515088626.png
new file mode 100644
index 00000000..e40d081c
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121515088626.png differ
diff --git a/docs/troubleshooting/assets/20250430121515418578.png b/docs/troubleshooting/assets/20250430121515418578.png
new file mode 100644
index 00000000..86a3dfcb
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121515418578.png differ
diff --git a/docs/troubleshooting/assets/20250430121515666267.png b/docs/troubleshooting/assets/20250430121515666267.png
new file mode 100644
index 00000000..42d102d9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121515666267.png differ
diff --git a/docs/troubleshooting/assets/20250430121515990341.png b/docs/troubleshooting/assets/20250430121515990341.png
new file mode 100644
index 00000000..6abae34e
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121515990341.png differ
diff --git a/docs/troubleshooting/assets/20250430121516228961.png b/docs/troubleshooting/assets/20250430121516228961.png
new file mode 100644
index 00000000..ad058757
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121516228961.png differ
diff --git a/docs/troubleshooting/assets/20250430121516544305.png b/docs/troubleshooting/assets/20250430121516544305.png
new file mode 100644
index 00000000..5e3af22d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121516544305.png differ
diff --git a/docs/troubleshooting/assets/20250430121516955662.png b/docs/troubleshooting/assets/20250430121516955662.png
new file mode 100644
index 00000000..042b9804
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121516955662.png differ
diff --git a/docs/troubleshooting/assets/20250430121517242675.png b/docs/troubleshooting/assets/20250430121517242675.png
new file mode 100644
index 00000000..d5102dc3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121517242675.png differ
diff --git a/docs/troubleshooting/assets/20250430121517855306.png b/docs/troubleshooting/assets/20250430121517855306.png
new file mode 100644
index 00000000..77de10ef
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121517855306.png differ
diff --git a/docs/troubleshooting/assets/20250430121518159572.png b/docs/troubleshooting/assets/20250430121518159572.png
new file mode 100644
index 00000000..2740581d
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121518159572.png differ
diff --git a/docs/troubleshooting/assets/20250430121518370897.png b/docs/troubleshooting/assets/20250430121518370897.png
new file mode 100644
index 00000000..42d102d9
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121518370897.png differ
diff --git a/docs/troubleshooting/assets/20250430121518594245.png b/docs/troubleshooting/assets/20250430121518594245.png
new file mode 100644
index 00000000..229fc6a7
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121518594245.png differ
diff --git a/docs/ff-integrations/analytics/google-analytics/adding-analytics-action-with-parameter.gif b/docs/troubleshooting/assets/20250430121522561282.gif
similarity index 53%
rename from docs/ff-integrations/analytics/google-analytics/adding-analytics-action-with-parameter.gif
rename to docs/troubleshooting/assets/20250430121522561282.gif
index 8b2a8817..a2dfbf00 100644
Binary files a/docs/ff-integrations/analytics/google-analytics/adding-analytics-action-with-parameter.gif and b/docs/troubleshooting/assets/20250430121522561282.gif differ
diff --git a/docs/troubleshooting/assets/20250430121524709613.gif b/docs/troubleshooting/assets/20250430121524709613.gif
new file mode 100644
index 00000000..90042924
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121524709613.gif differ
diff --git a/docs/troubleshooting/assets/20250430121528287666.png b/docs/troubleshooting/assets/20250430121528287666.png
new file mode 100644
index 00000000..29fb4d4a
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121528287666.png differ
diff --git a/docs/troubleshooting/assets/20250430121529004156.png b/docs/troubleshooting/assets/20250430121529004156.png
new file mode 100644
index 00000000..9c339290
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121529004156.png differ
diff --git a/docs/troubleshooting/assets/20250430121529462395.png b/docs/troubleshooting/assets/20250430121529462395.png
new file mode 100644
index 00000000..e98576fa
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121529462395.png differ
diff --git a/docs/troubleshooting/assets/20250430121529757254.png b/docs/troubleshooting/assets/20250430121529757254.png
new file mode 100644
index 00000000..10f396b3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121529757254.png differ
diff --git a/docs/troubleshooting/assets/20250430121530070855.png b/docs/troubleshooting/assets/20250430121530070855.png
new file mode 100644
index 00000000..33b05884
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121530070855.png differ
diff --git a/docs/troubleshooting/assets/20250430121530401837.jpg b/docs/troubleshooting/assets/20250430121530401837.jpg
new file mode 100644
index 00000000..d3a655d5
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121530401837.jpg differ
diff --git a/docs/troubleshooting/assets/20250430121530740313.jpg b/docs/troubleshooting/assets/20250430121530740313.jpg
new file mode 100644
index 00000000..43215d58
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121530740313.jpg differ
diff --git a/docs/troubleshooting/assets/20250430121530999303.jpg b/docs/troubleshooting/assets/20250430121530999303.jpg
new file mode 100644
index 00000000..dd8ad7b8
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121530999303.jpg differ
diff --git a/docs/troubleshooting/assets/20250430121531246146.png b/docs/troubleshooting/assets/20250430121531246146.png
new file mode 100644
index 00000000..cb189a20
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121531246146.png differ
diff --git a/docs/troubleshooting/assets/20250430121531448037.png b/docs/troubleshooting/assets/20250430121531448037.png
new file mode 100644
index 00000000..847ac466
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121531448037.png differ
diff --git a/docs/troubleshooting/assets/20250430121531723554.png b/docs/troubleshooting/assets/20250430121531723554.png
new file mode 100644
index 00000000..610dbb16
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121531723554.png differ
diff --git a/docs/troubleshooting/assets/20250430121531973906.png b/docs/troubleshooting/assets/20250430121531973906.png
new file mode 100644
index 00000000..7ca49212
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121531973906.png differ
diff --git a/docs/troubleshooting/assets/20250430121532523511.png b/docs/troubleshooting/assets/20250430121532523511.png
new file mode 100644
index 00000000..1ffa65e3
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121532523511.png differ
diff --git a/docs/troubleshooting/assets/20250430121532793176.png b/docs/troubleshooting/assets/20250430121532793176.png
new file mode 100644
index 00000000..97153aaf
Binary files /dev/null and b/docs/troubleshooting/assets/20250430121532793176.png differ
diff --git a/docs/troubleshooting/assets/uploadToGCC.png b/docs/troubleshooting/assets/uploadToGCC.png
new file mode 100644
index 00000000..69a2ca03
Binary files /dev/null and b/docs/troubleshooting/assets/uploadToGCC.png differ
diff --git a/docs/troubleshooting/authentication/_category_.json b/docs/troubleshooting/authentication/_category_.json
new file mode 100644
index 00000000..44dd4a2c
--- /dev/null
+++ b/docs/troubleshooting/authentication/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Authentication"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/authentication/app_starts_from_homepage_in_run_mode.md b/docs/troubleshooting/authentication/app_starts_from_homepage_in_run_mode.md
new file mode 100644
index 00000000..427e9828
--- /dev/null
+++ b/docs/troubleshooting/authentication/app_starts_from_homepage_in_run_mode.md
@@ -0,0 +1,26 @@
+---
+keywords: ['homepage', 'run mode', 'authentication state', 'session data']
+slug: /troubleshooting/authentication/app-starts-from-homepage-in-run-mode
+title: App Starts from HomePage in Run Mode
+---
+# App Starts from HomePage in Run Mode
+
+If your app always redirects to the **HomePage** in **Run Mode**, even after a previous login, it's likely caused by **retained authentication state** or **cached session data** in your browser.
+
+## Troubleshooting Steps
+
+- Clear your browser cache and history.
+
+ 
+
+- Try a different browser or use incognito/private browsing mode to see if the issue persists.
+
+If the problem continues, consider checking your authentication flow and session management in your app settings.
+
+:::tip[Reset Authentication State in Run Mode]
+When using **Run Mode**, FlutterFlow preserves your **authentication state** across sessions. To test your app from a clean state, add a **"Log Out"** button on your HomePage that triggers the `Sign Out` action. This ensures the app starts from the login screen during your next test.
+:::
+
+
+
+
diff --git a/docs/troubleshooting/authentication/check_firebase_login_method.md b/docs/troubleshooting/authentication/check_firebase_login_method.md
new file mode 100644
index 00000000..86e09590
--- /dev/null
+++ b/docs/troubleshooting/authentication/check_firebase_login_method.md
@@ -0,0 +1,62 @@
+---
+keywords: ['firebase', 'auth', 'authenticated']
+slug: /troubleshooting/authentication/check-firebase-login-method
+title: Check Firebase Login Method
+---
+# Check Firebase Login Method
+
+Understanding which authentication method a user has used can be useful for several reasons. For example, it can be leveraged for analytics, user support, and to customize the user's experience based on their login method. This method, however, is specific to Firebase Authentication.
+
+In our Flutter app, we can find out which method a user used to authenticate by leveraging Firebase's `User.providerData` property. Let's take a closer look at how this works in the code:
+
+
+```js
+import 'package:firebase_auth/firebase_auth.dart';
+
+String getUserSignInMethod() {
+ final user = FirebaseAuth.instance.currentUser;
+ String signInMethod;
+
+ for (var info in user!.providerData) {
+ signInMethod = info.providerId;
+ }
+
+ return signInMethod;
+}
+
+```
+
+Here's a breakdown of the code:
+
+ - We first import the [Firebase Auth](https://pub.dev/packages/firebase_auth) package which gives us access to Firebase's authentication methods.
+
+ - Next, we define a function `getUserSignInMethod`. This function will return a string indicating the sign-in method the user used.
+
+ - Inside the function, we obtain the current user from FirebaseAuth using `FirebaseAuth.instance.currentUser`.
+
+ - We then declare a string `signInMethod` that will store the name of the provider used for sign-in.
+
+ - `user.providerData` is an iterable that provides UserInfo for each sign-in method used by the user. We loop over this iterable using a `for` loop.
+
+ - In each iteration, we assign the `providerId` to our `signInMethod` string. The `providerId` can be 'google.com' for Google, 'facebook.com' for Facebook, and 'password' for email and password.
+
+ - After the loop is done, the function returns `signInMethod` string which indicates the sign-in method the user used.
+
+ - The function `getUserSignInMethod()` returns a String value which corresponds to the providerId of the user's sign-in method.
+
+Here are examples of how the return value might look like:
+
+- If the user has signed in using Google, the function will return: **`'google.com'`**
+
+- If the user has signed in using Facebook, the function will return: **`'facebook.com'`**
+
+- If the user has signed in using Email and Password, the function will return: **`'password'`**
+
+ These are the identifiers used by Firebase to represent different sign-in methods. Please thoroughly test this function to ensure it fits your specific requirements
+
+:::tip[Use Sign-In Method to Drive Dynamic UI in FlutterFlow]
+In FlutterFlow, if you want to display or use the user's sign-in method in your UI logic (example, showing different UIs for Google vs. email login), you can create a custom function using the `providerId` approach shown in the article and **connect it to a custom action**. This allows you to make dynamic decisions inside your app based on how the user authenticated.
+
+Remember to return the result from the custom function and store it in an App State variable for easy access throughout your app.
+:::
+
diff --git a/docs/troubleshooting/authentication/deleting_firebase_users_and_related_data.md b/docs/troubleshooting/authentication/deleting_firebase_users_and_related_data.md
new file mode 100644
index 00000000..d2eb4163
--- /dev/null
+++ b/docs/troubleshooting/authentication/deleting_firebase_users_and_related_data.md
@@ -0,0 +1,36 @@
+---
+keywords: ['firebase-auth', 'delete-user', 'firestore-cleanup']
+slug: /troubleshooting/authentication/deleting-firebase-users-and-related-data
+title: Deleting Firebase Users and Related Data
+---
+# Deleting Firebase Users and Related Data
+
+
+
+## Understanding the Delete Action
+
+The delete action in Firebase is designed to remove the user from the authentication table only. This means the user's document in the database will not be affected. If you want to delete the user's document from the database as well, you'll need to create a custom action with some custom code.
+
+### Logging Out After Deletion
+
+After completing the delete action, it is important to log out the user. Since the user no longer exists in the authentication system, logging out ensures the app routes the user back to the login page, which is typically the initial page of your project.
+
+## Steps for Proper User Deletion
+
+1. **Delete related data first:**
+ Before calling the delete user action, delete any related data such as Firestore documents or Storage files associated with the user. Once the user is deleted from Firebase Auth, their UID will no longer be accessible in the app session, making it difficult to reference their data afterward.
+
+2. **Handle re-login behavior:**
+ Keep in mind that if the same user signs in again using the same signup method, Firebase will create a new document in the database for them. This happens because Firebase links the new login information to the old user document.
+
+:::tip[Important Tips for Deleting Users]
+- Always delete associated user data from Firestore or Storage **before** deleting the user from Firebase Auth. This prevents orphaned data and issues with data referencing.
+- Remember that after deletion, the user will need to be logged out to avoid session errors.
+- If the user signs in again with the same signup method, Firebase creates a new document for them, reconnecting the new login to the old user document.
+:::
+
+
+
+:::note
+The delete user action in FlutterFlow performs the same operation as manually deleting a user from the Firebase Authentication table.
+:::
diff --git a/docs/troubleshooting/authentication/fix_google_sign-in_issues.md b/docs/troubleshooting/authentication/fix_google_sign-in_issues.md
new file mode 100644
index 00000000..dad812aa
--- /dev/null
+++ b/docs/troubleshooting/authentication/fix_google_sign-in_issues.md
@@ -0,0 +1,59 @@
+---
+keywords: ['firebase', 'deployment', 'android', 'google-sign-in']
+slug: /troubleshooting/authentication/fix-google-sign-in-issues
+title: Fix Google Sign-In Issues
+---
+# Fix Google Sign-In Issues
+
+If Google Sign-In isn’t working after exporting your FlutterFlow app, follow these steps based on how you’re deploying your app.
+
+1. **If Deployed to the Play Store via CodeMagic**
+
+ If you published your app to the Play Store using FlutterFlow's CodeMagic integration:
+
+ - In the **Google Play Console**, open your app from the **All apps** list.
+ - Go to **Setup → App Integrity**.
+ - Under the **App Signing** tab, copy the **SHA-1 certificate fingerprint**.
+
+ 
+
+ - In the **Firebase console**, open the same project, scroll to **Your Apps**, and select your Android app.
+ - Click **Add fingerprint**, paste the SHA-1, then click **Save**.
+
+ 
+
+ - In FlutterFlow, go to **Settings → Firebase** and click:
+ - **Regenerate Config Files**
+ - **Generate Files**
+
+ 
+
+ Re-test your app. Google Sign-In should now work correctly.
+
+
+2. **If Not Yet Published or Using Manual Signing**
+
+ If you’re not using Play Store App Signing:
+
+ - Use **Keytool** or **Gradle's Signing Report** to generate your SHA-1.
+ - In **Firebase**, open your project settings.
+ - Under **Your Apps**, select the Android app and add the SHA-1 fingerprint.
+
+ 
+
+ - In FlutterFlow, go to **Settings → Firebase**, then:
+ - **Regenerate Config Files**
+ - **Generate Files**
+
+ 
+
+ Test the app again to confirm Google Sign-In works.
+
+
+ *Refer to the [Google Play Services documentation](https://developers.google.com/android/guides/overview) for more information.*
+
+
+:::tip[Add Debug SHA-1 for Local Testing]
+- When testing Google Sign-In in FlutterFlow before publishing, add your **debug SHA-1** in Firebase.
+- Then go to `Settings → Firebase` in FlutterFlow and regenerate your config files.
+:::
diff --git a/docs/troubleshooting/authentication/permission_denied_code_403.md b/docs/troubleshooting/authentication/permission_denied_code_403.md
new file mode 100644
index 00000000..73d480af
--- /dev/null
+++ b/docs/troubleshooting/authentication/permission_denied_code_403.md
@@ -0,0 +1,43 @@
+---
+keywords: ['permission', 'permission_denied', 'code']
+slug: /troubleshooting/authentication/permission-denied-code-403
+title: 'Permission Denied: Code 403'
+---
+
+# Permission Denied: Code 403
+
+This error typically occurs when your application or service account does not have the required permissions to access a resource in Google Cloud or Firebase.
+
+## Code 403 Error Message
+
+You may encounter this error due to one or more of the following reasons:
+
+- **Invalid or misconfigured service account JSON file**
+- **Insufficient permissions** assigned to the service account
+- **Missing or incorrect IAM roles** for the service account
+- **API not enabled** in the Google Cloud project
+
+
+Do the following to fix this error:
+
+- **Check Your Service Account JSON File**
+
+ Ensure you are using the correct `service-account.json` file and that it is not corrupted or expired.
+
+- **Verify IAM Roles and Permissions**
+
+ Make sure the service account has the necessary roles like `Editor`, `Owner`, or other specific roles required for your use case.
+
+- **Enable Required APIs**
+
+ Go to the [Google Cloud Console](https://console.cloud.google.com/apis/library) and ensure all necessary APIs are enabled for your project.
+
+- **Regenerate the Service Account Key if Needed**
+
+ If you suspect the key is invalid, generate a new one and update your application configuration accordingly.
+
+:::tip[Always Use Least Privilege Principle]
+When assigning IAM roles to your service account, follow the **principle of least privilege**—only grant the minimum permissions necessary for the task. This not only reduces the risk of misconfiguration but also enhances the overall security posture of your app.
+:::
+
+If you continue to experience issues, consult the [Google Cloud IAM documentation](https://cloud.google.com/iam/docs/troubleshooting-access) or contact [FlutterFlow Support](mailto:support@flutterflow.io) for further assistance.
diff --git a/docs/troubleshooting/authentication/safetynet_phone_sign-in_issue_on_android_devices.md b/docs/troubleshooting/authentication/safetynet_phone_sign-in_issue_on_android_devices.md
new file mode 100644
index 00000000..39b1f30b
--- /dev/null
+++ b/docs/troubleshooting/authentication/safetynet_phone_sign-in_issue_on_android_devices.md
@@ -0,0 +1,84 @@
+---
+keywords: ['android', 'signing', 'release']
+slug: /troubleshooting/authentication/safetynet-phone-sign-in-issue-on-android-devices
+title: SafetyNet Phone Sign-In Issue on Android Devices
+---
+
+# SafetyNet Phone Sign-In Issue on Android Devices
+
+If you're experiencing issues with Firebase Phone Authentication on Android devices, especially when using emulators or testing in release mode, this guide will help you identify and resolve common problems.
+
+Firebase uses either **SafetyNet** or **reCAPTCHA** to verify that phone number sign-in requests originate from your app. Issues typically arise when one of these verification methods is not correctly configured.
+
+
+## Troubleshooting Checklist
+
+Ensure the following configurations are in place:
+
+- **Firebase Setup**
+ - Your project is correctly set up in the [Firebase Console](https://console.firebase.google.com/).
+ - Firebase Authentication is enabled.
+ - The Phone Sign-In method is activated.
+
+- **Phone Authentication Flow**
+ - Prompt the user to enter their phone number.
+ - Send a verification code to the user's phone.
+ - Accept and verify the code entered by the user.
+
+- **SafetyNet / reCAPTCHA Configuration**
+ - Your app includes the required Firebase and Play Services dependencies.
+ - SHA-1 and SHA-256 fingerprints are added to your Firebase project settings.
+ - Your API key is either unrestricted or allowlisted.
+
+- **Testing Environment**
+ - If you're using an emulator, test on a physical device instead. Emulators may bypass or fail certain integrity checks.
+
+
+## Firebase Verification Methods
+
+Firebase uses one of the following methods to confirm the authenticity of phone sign-in requests:
+
+1. **SafetyNet (Deprecated)**
+
+ If the device supports Google Play Services, Firebase uses **SafetyNet Attestation** to confirm the device’s legitimacy.
+
+ :::warning[Deprecated API]
+ The SafetyNet Attestation API is deprecated and has been replaced by the [Play Integrity API](https://developer.android.com/google/play/integrity). After **January 31, 2023**, you can no longer enable the SafetyNet API for new projects in the Google Cloud Console.
+ :::
+
+ To use SafetyNet (if still active for your project):
+ - Enable **Android Device Verification (Deprecated)** in the [Google Cloud Console](https://console.cloud.google.com/).
+ - Ensure your app's **SHA-256** is added in the Firebase Console under **Project Settings > General > Your Apps**.
+ - Use the default Firebase API key or request onboarding for SafetyNet if needed.
+ - Monitor your quota [here](https://developer.android.com/google/play/safetynet/quotas).
+
+ 
+
+2. **reCAPTCHA Verification**
+
+ If SafetyNet is unavailable (e.g. device without Google Play Services or running on an emulator), Firebase falls back to **reCAPTCHA verification**.The reCAPTCHA challenge usually completes without user interaction. This flow requires:
+
+ - A valid **SHA-1** fingerprint added to your Firebase project.
+ - An **unrestricted** or **domain-allowlisted** API key (e.g. `your-project-name.firebaseapp.com`).
+ - Ensure both SafetyNet and reCAPTCHA flows are working to support a wider range of Android devices.
+
+
+ :::info[Release Mode Configuration]
+ When releasing your app to the Google Play Store, ensure you include the **SHA-1** and **SHA-256** keys from your **Play Console**. Here is how to do that:
+
+ - Navigate to **Play Console → Your App → Release → Setup → App Signing**
+ - Then copy both **SHA-1** and **SHA-256** fingerprints and add them to Firebase Console under **Project Settings > General > Your Apps**.
+ :::
+
+ 
+
+
+:::info[Learn more]
+- [Firebase Phone Authentication (FlutterFire)](https://firebase.flutter.dev/docs/auth/phone/)
+- [Using Firebase Auth in FlutterFlow](https://docs.flutterflow.io/authentication)
+- [Play Integrity API Migration](https://developer.android.com/google/play/integrity)
+
+Still stuck? Check Firebase logs, test on a physical device, and ensure your API keys and fingerprints are correctly added. Proper configuration of SafetyNet or reCAPTCHA is critical to ensuring phone number sign-in works reliably across devices.
+:::
+
+
diff --git a/docs/troubleshooting/authentication/sign_in_with_apple_for_web.md b/docs/troubleshooting/authentication/sign_in_with_apple_for_web.md
new file mode 100644
index 00000000..b4246510
--- /dev/null
+++ b/docs/troubleshooting/authentication/sign_in_with_apple_for_web.md
@@ -0,0 +1,60 @@
+---
+keywords: ['firebase', 'sign', 'apple']
+slug: /troubleshooting/authentication/sign-in-with-apple-for-web
+title: Sign in With Apple (for Web)
+---
+
+# Sign in With Apple (for Web)
+
+To enable **Sign in with Apple** on the web, you must complete additional steps in both your **Apple Developer Account** and **Firebase Console**. These steps allow Apple to identify your website and authorize the use of Apple login on web platforms.
+
+:::warning
+The **Sign in with Apple (Web)** functionality cannot be tested in Test/Run Mode. You must **deploy** your app to a live domain before testing.
+:::
+
+Take the following steps to set up Sign in with App (for Web):
+
+1. **Configure Apple Developer Account**
+
+ Follow these steps in your [Apple Developer Account](https://developer.apple.com/account/):
+
+ 1. **Register a New Identifier**
+ - Select **App IDs** and fill in the required details.
+ - Enable the **Sign in with Apple** capability.
+
+ 2. **Create a New Service ID**
+ - Provide a name and a unique identifier.
+ - This will be used as the **Service ID** in Firebase.
+
+ 3. **Configure Sign in With Apple**
+ - Add your domain and return URL (from Firebase).
+ - Save the configuration.
+
+ 4. **Create a New Key**
+ - Enable **Sign in with Apple**.
+ - Download the generated private key (`.p8` file).
+
+
+2. **Set Up in Firebase Console**
+
+ After downloading the private key, configure your Firebase app by doing the following:
+
+ 1. Go to **Authentication → Sign-in method → Apple**.
+ 2. Enter the following details:
+ - **Apple Team ID**
+ - **Key ID**
+ - **Private Key** (from the `.p8` file)
+ 3. Set the **Service ID** to match the one created in the Apple Developer account.
+
+ Once these steps are completed, your **Sign in with Apple (Web)** setup should be active.
+
+:::note[Still Not Working?]
+If the sign-in process fails after completing these steps, please contact [FlutterFlow Support](mailto:support@flutterflow.io) via Chat or Email.
+:::
+
+
+:::info[Helpful Resources]
+- [Apple Developer - Sign in with Apple](https://developer.apple.com/sign-in-with-apple/)
+- [Firebase Authentication - Apple Provider](https://firebase.google.com/docs/auth/web/apple)
+- [FlutterFlow Authentication Docs](https://docs.flutterflow.io/authentication)
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/authentication/troubleshooting_custom_authentication.md b/docs/troubleshooting/authentication/troubleshooting_custom_authentication.md
new file mode 100644
index 00000000..c4953949
--- /dev/null
+++ b/docs/troubleshooting/authentication/troubleshooting_custom_authentication.md
@@ -0,0 +1,59 @@
+---
+keywords: ['authentication', 'api', 'configuration']
+slug: /troubleshooting/authentication/troubleshooting-authentication
+title: Troubleshooting Custom Authentication
+---
+# Troubleshooting Custom Authentication
+
+:::info[Prerequisites]
+- Ensure you have a **custom server** with login and sign-up endpoints that return a JWT token upon success.
+- **Custom authentication** must be enabled in FlutterFlow, with entry and logged-in pages correctly set.
+:::
+
+Here's an example:
+
+
+
+## How to Fix Custom Authentication Issues
+
+1. **Verify Server and API Endpoints**
+ - Confirm that your server correctly returns JWT tokens for login and sign-up requests. The server's response should include the **authentication token**, **refresh token**, **expiration time**, and **user ID (UID)**.
+ - Double-check the API endpoint configurations in FlutterFlow to ensure they match your server’s requirements.
+
+2. **FlutterFlow Configuration**
+ - Make sure **Custom Authentication** is enabled in your project settings.
+ - Verify that the **Entry Page** and **Logged In Page** are correctly set.
+
+3. **UI Configuration**
+ - Ensure your app includes the essential pages for the authentication flow: **Login**, **Sign Up**, and **Home Page** (the page shown when a user is authenticated).
+
+4. **API Integration and Authentication Flow**
+ - Test API calls from FlutterFlow to your custom server to confirm responses are working as expected.
+ - Use the **Backend Call** action to trigger login/signup, then handle the **Custom Login** action using the response data.
+
+5. **Handling Tokens and User Data**
+ - Parse the API response properly to extract and store:
+ - `auth token`
+ - `refresh token`
+ - `expiration time`
+ - `user ID (UID)`
+ - Store these values in local state or secure app storage.
+
+ 
+
+6. **Navigation**
+ - If navigation does not occur automatically after login/signup:
+ - Disable automatic navigation.
+ - Use a **manual navigation** action to route users to the appropriate page.
+
+:::tip[General Tips]
+- Test your flow with **dummy credentials** before using real user data. This helps debug token handling, API responses, and navigation.
+- Add **logging** on both the server and in FlutterFlow (example, using snack bars or alerts) to monitor each step of the flow.
+- Verify the full flow—from login to protected pages—to ensure everything works as expected.
+:::
+
+:::info[More Resources]
+- [FlutterFlow Custom Authentication Video](https://www.youtube.com/watch?v=hnX3CvBtGvI)
+- **Sample project:** [Custom Auth Checklist](https://app.flutterflow.io/project/custom-auth-checklist-fdjkno)
+- [FlutterFlow Custom Authentication Documentation](https://docs.flutterflow.io/data-and-backend/custom-authentication)
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/backend/_category_.json b/docs/troubleshooting/backend/_category_.json
new file mode 100644
index 00000000..3e4fed67
--- /dev/null
+++ b/docs/troubleshooting/backend/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Backend"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/backend/listview_gray_box_and_red_screen_errors.md b/docs/troubleshooting/backend/listview_gray_box_and_red_screen_errors.md
new file mode 100644
index 00000000..24b6c967
--- /dev/null
+++ b/docs/troubleshooting/backend/listview_gray_box_and_red_screen_errors.md
@@ -0,0 +1,81 @@
+---
+keywords: ['database', 'listview', 'mode']
+slug: /troubleshooting/backend/listview-gray-box-and-red-screen-errors
+title: ListView Gray Box and Red Screen Errors
+---
+
+# ListView Gray Box and Red Screen Errors
+
+When loading a list of items from the database, you might encounter a gray box or red error screen. This article explains the possible causes and how to resolve them.
+
+:::info[Prerequisites]
+- Ensure your query is correctly connected to a Firestore collection or CMS.
+- Confirm that your app builds and runs correctly in **Run** and **Test** modes.
+:::
+
+**Understanding the Error:**
+
+A **gray box** usually indicates that the backend query failed to return results. A **red screen** in Test mode suggests a runtime error caused by invalid data or query failure.
+
+**Step-by-Step Troubleshooting:**
+
+1. **Verify Query Results**
+
+ - If the query is successful and returns items, the list will populate as expected.
+ - If there are no records matching the query, you will see the **empty state** you configured.
+ - If the query fails, a gray box (in Run mode) or a red error screen (in Test mode) will appear.
+
+ 
+
+ :::tip
+ Always configure an empty state for lists. This helps distinguish between a failed query and an empty dataset.
+ :::
+
+2. **Behavior by Mode**
+
+ - **Run mode**: Displays a gray box when the query fails.
+ - **Test mode**: Shows a red screen with a specific error message.
+
+ **Example: Working Query with No Results**
+ 
+
+ **Example: Failed Query**
+ 
+
+3. **Check for Null Values in the Data**
+
+ Null values in critical fields may cause queries or widgets to fail.
+
+ Here is how to check for null values:
+
+ 1. Inspect your data in **Firebase** or **CMS** for any fields with `null` values.
+ 2. Pay attention to fields used in filters, formatting, or conditional visibility.
+ 3. For example, if `created_time` is null and you are formatting a date from this field, the query may fail.
+
+ **Example: Null Field Causing Error**
+
+ 
+ 
+
+ :::note
+ Use **visibility rules** to hide widgets that depend on potentially null values.
+ :::
+
+4. **Handle Document-From-Reference Queries Safely**
+
+ If you use document references inside a list item widget, and the reference is null or missing, it will break the query.
+
+ 
+
+ :::note
+ Always add a visibility rule to any widget performing document-from-reference queries. This ensures the widget is only visible when the reference is valid.
+ :::
+
+
+:::info[Summary]
+- A **gray box** means the backend query failed.
+- A **red screen** indicates a runtime error in **Test mode**.
+- **Null values** in your database are a common cause of failure.
+- Always configure **empty states** and apply **visibility rules** to handle null or missing data gracefully.
+:::
+
diff --git a/docs/troubleshooting/backend/listview_returning_only_one_item.md b/docs/troubleshooting/backend/listview_returning_only_one_item.md
new file mode 100644
index 00000000..d84507d9
--- /dev/null
+++ b/docs/troubleshooting/backend/listview_returning_only_one_item.md
@@ -0,0 +1,35 @@
+---
+keywords: ['listview', 'returning', 'only']
+slug: /troubleshooting/backend/listview-returning-only-one-item
+title: ListView Returning Only One Item
+---
+# Fix ListView Only Returning One Item
+
+If your **ListView** is only showing one item, this guide will walk you through the common reasons and how to resolve the issue.
+
+:::info[Prerequisites]
+- A working Firebase or CMS integration.
+- A dynamic layout widget such as `ListView`, `GridView`, or `Column`.
+- At least two documents in your Firestore collection for testing.
+:::
+
+Follow the steps below to resolve the issue:
+
+1. **Use a Dynamic Widget**
+ Make sure you're using a widget like `ListView`, `GridView`, or `Column` that supports dynamic content.
+
+2. **Confirm the Query Type**
+ Ensure the query is set to return a **list of documents**, not a single document.
+
+3. **Review Applied Filters**
+ If you are using filters, check that multiple records in your database satisfy those filter conditions.
+
+4. **Check Firestore Data**
+ Open your Firestore collection and verify that it contains **multiple records**.
+
+5. **Verify List Type Fields**
+ If querying a single field, confirm it's defined as a **List** in both Firebase and FlutterFlow.
+
+:::tip
+To test your setup, remove all filters temporarily and use a basic list query. This helps isolate whether the issue is with filtering or the query type.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/backend/resolving_firebase_configuration_issues.md b/docs/troubleshooting/backend/resolving_firebase_configuration_issues.md
new file mode 100644
index 00000000..d11aded1
--- /dev/null
+++ b/docs/troubleshooting/backend/resolving_firebase_configuration_issues.md
@@ -0,0 +1,71 @@
+---
+keywords: ['firebase', 'issues', 'configuration']
+slug: /troubleshooting/backend/resolving-firebase-configuration-issues
+title: Resolving Firebase Configuration Issues
+---
+# Resolving Firebase Configuration Issues
+
+If you're experiencing backend errors, failed schema validation, or data sync issues, this guide will help you verify and fix your Firebase setup in FlutterFlow.
+
+:::info[Prerequisites]
+- You must have already connected your Firebase project to FlutterFlow.
+- You should have access to your Firebase console with admin rights.
+:::
+
+Follow the steps below to fix firebase configuration:
+
+1. **Grant Required Permissions**
+
+ Assign the following permissions to `firebase@flutterflow.io` in your Firebase project:
+ - Editor
+ - Cloud Functions Admin
+ - Service Account User
+
+ Learn how to **[assign Firebase permissions](/integrations/firebase/connect-to-firebase/#allow-flutterflow-to-access-your-project)**.
+
+2. **Update Firestore Rules**
+
+ Update your Firestore security rules to allow access for FlutterFlow.
+
+ After making changes:
+ - Remove `firebase@flutterflow.io` from your authenticated users.
+ - Redeploy your Firestore rules.
+ - Validate your schema again.
+
+ 
+
+3. **Match Field Types and Names**
+
+ Check that data field types and names match between Firestore and FlutterFlow exactly. Mismatches will cause query errors.
+
+4. **Validate Firestore Schema in FlutterFlow**
+
+ Use the **Validate** button under **Firestore → Settings** in FlutterFlow to confirm that your collection schema matches your Firestore structure.
+
+ 
+
+5. **Reset Firebase Setup (If Needed)**
+
+ If issues persist after following the steps above:
+ - Revoke the current setup.
+ - Reconnect your Firebase project using the **[Firebase setup instructions](/integrations/firebase/connect-to-firebase/)**.
+
+6. **Add Authorized Domains**
+
+ In the Firebase console, go to **Authentication → Sign-in Method → Authorized Domains** and add: `app.flutterflow.io`
+
+7. **Refresh FlutterFlow**
+
+ Make sure you're using the latest version of the platform:
+
+ - Press `Ctrl`/`Cmd + Shift + R`
+ - Clear your browser cache
+ - Log out and back in to FlutterFlow
+
+8. **Upgrade to Blaze Plan (If Using Cloud Functions)**
+
+ Cloud Functions such as Push Notifications and Payments require a billing-enabled Firebase project. Make sure you’re on the **Blaze Plan**.
+
+:::tip
+After updating Firestore rules, always validate the schema using the **Validate** button before proceeding with other fixes.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/backend/update_document_action_fails_during_backend_call.md b/docs/troubleshooting/backend/update_document_action_fails_during_backend_call.md
new file mode 100644
index 00000000..fab2a779
--- /dev/null
+++ b/docs/troubleshooting/backend/update_document_action_fails_during_backend_call.md
@@ -0,0 +1,58 @@
+---
+keywords: ['call', 'document', 'backend']
+slug: /troubleshooting/backend/update-document-action-fails-during-backend-call
+title: Update Document Action Fails During Backend Call
+---
+# Update Document Action Fails During Backend Call
+
+When performing the **Update Document** action, you may encounter a situation where the loading indicator appears but then stops without completing the action. This indicates that the update was unsuccessful. If the update succeeds, the next steps in your action flow, such as displaying an alert dialog, should execute automatically.
+
+
+
+
+
+:::note
+After performing the update action, always verify that the data has been correctly updated in your database. If your document is not streamed in real-time within your app, the updated data may not immediately appear. Check the data in FlutterFlow CMS or directly in Firebase to confirm the update.
+:::
+
+**Causes of Document Update Failures:**
+
+When the update action fails, the action flow stops, preventing any subsequent actions from executing.
+
+There are two common reasons why the update action may fail:
+
+- **Permission Issue in Firestore**
+
+ The user may not have the necessary permission to write to the document.
+
+ 
+
+ **Cause:**
+ The Firestore security rules may not allow the current user to write (edit) documents.
+
+ **Solution:**
+ Review and configure your Firestore rules to grant write permission. For example, allowing write access to authenticated users is often sufficient if your app requires user authentication.
+
+- **Data Type Mismatch**
+
+ The values you are attempting to write may not match the expected field types.
+
+ For example, assigning a string value to a field that expects an integer will result in failure.
+
+ 
+
+ **Cause:**
+ Attempting to write a value of the wrong type, such as assigning text to a number field.
+
+ **Solution:**
+ Verify that the values being written match the expected data types for each field. If the data comes from an API call or form input, consider using custom actions to convert the value to the appropriate type before performing the update.
+
+ :::note
+ If you want to save a text field value as a number, ensure that the text field input type is set to **Number**.
+ :::
+
+:::info[Additional Troubleshooting]
+You can check for error details in your browser's developer console (F12). For example, permission errors will typically appear in the console logs, as shown below:
+
+
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/cloud-functions/_category_.json b/docs/troubleshooting/cloud-functions/_category_.json
new file mode 100644
index 00000000..b5afe6a0
--- /dev/null
+++ b/docs/troubleshooting/cloud-functions/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Cloud Functions"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/cloud-functions/fix_cloud_functions_deployment.md b/docs/troubleshooting/cloud-functions/fix_cloud_functions_deployment.md
new file mode 100644
index 00000000..12be8d77
--- /dev/null
+++ b/docs/troubleshooting/cloud-functions/fix_cloud_functions_deployment.md
@@ -0,0 +1,195 @@
+---
+keywords: ['cloud functions', 'firebase', 'deployment', 'error']
+slug: /troubleshooting/cloud-functions/fix-cloud-functions-deployment
+title: Fix Cloud Functions Deployment
+---
+
+# Fix Cloud Functions Deployment
+
+:::info[Prerequisites]
+- You must have a Firebase project connected to FlutterFlow.
+- Ensure your project is on the Blaze Plan.
+:::
+
+Cloud Functions allow you to execute backend code in response to events triggered by Firebase features or HTTPS requests. Various situations might cause Cloud Functions to malfunction, often stemming from setup problems or coding mistakes within the Cloud Function's script.
+
+This article guides you through common challenges with Cloud Functions in FlutterFlow and how to resolve them.
+
+**Errors Shown in FlutterFlow Builder**
+
+You may encounter the following errors in the FlutterFlow Builder:
+
+ - `Out of Date (Error)`
+ - `Not Deployed (Error)`
+
+ These errors can arise from various situations. Below are screenshots of these errors:
+
+ **Out of Date Error**
+
+ 
+
+ **Not Deployed Error**
+
+ 
+
+
+## Key Checks for Resolving Deployment Errors
+
+ 1. **Verify [firebase@flutterflow.io](mailto:firebase@flutterflow.io) Has Necessary Permissions**
+
+ To ensure FlutterFlow works smoothly with your project, ensure that `firebase@flutterflow.io` has the following permissions in your Firebase project:
+
+ - Cloud Functions Admin
+ - Editor
+ - Service Account User
+
+ Follow the steps below to add these permissions:
+
+ - Go to the Firebase Console and log into your account.
+ - Open your project and go to **Project Settings > Users and Permissions**.
+ - Under **Advanced Settings Permissions**, locate `firebase@flutterflow.io`, click **Edit**, and add the required roles.
+
+ 
+
+ 
+
+
+ 2. **Check for Function Name Mismatch**
+
+ Ensure the function name in your code exactly matches the function name defined in FlutterFlow.
+
+ For example, in this case, FlutterFlow expects `logoMaker`, but the code incorrectly uses `data`.
+
+ 
+
+
+ 3. **Validate Custom Code for Cloud Functions**
+
+ Small mistakes in your custom Cloud Functions code can prevent deployment.
+
+ - Double-check your code for errors.
+ - Test locally using an IDE or Firebase CLI.
+
+ 
+
+
+ 4. **Verify Firebase Billing Plan (Blaze Plan Required):**
+
+ - Ensure your Firebase project is on the **Blaze Plan**, not Spark Plan.
+ - Check billing status on GCP. Even if Firebase shows Blaze, GCP billing issues may still block deployments.
+
+
+ 5. **Check if Other Cloud Functions Are Deploying:**
+
+ - If some Cloud Functions (like Push Notification or Stripe) are deploying successfully, it indicates your Firebase setup is mostly correct.
+ - Focus on inspecting your specific function code and configuration.
+
+
+ 6. **Ensure Region Selection Matches Firebase Project:**
+
+ - The region set for your Cloud Function in FlutterFlow should match your Firebase project's region.
+ - Do not leave the region as `[default]`.
+
+ 
+
+ 
+
+ :::tip
+ If you previously deployed functions in the wrong region, delete them, set the correct region, and re-deploy.
+ :::
+
+ 7. **Protocol Conflicts: HTTP vs Callable Functions**
+
+ If you initially deployed a function as HTTP and later try to redeploy it as Callable (or vice versa), you'll get this error:
+
+ `[makeUserAdmin(us-central1)] Changing from an HTTPS function to a callable function is not allowed. Please delete your function and create a new one instead.`
+
+ Follow the steps below to fix this error:
+
+ - Delete the existing function in Firebase Console.
+ - Modify the protocol type in FlutterFlow.
+ - Redeploy the function.
+
+ 8. **Verify `package.json` Integrity**
+
+ - Use the generated `package.json` file as-is unless you need to add extra packages.
+ - Ensure it’s not blank and doesn’t contain invalid characters.
+
+ **Recommended structure:**
+
+ ```js
+ {
+ "name": "functions",
+ "description": "Firebase Custom Cloud Functions",
+ "engines": {
+ "node": "18"
+ },
+ "main": "index.js",
+ "dependencies": {
+ "firebase-admin": "^11.8.0",
+ "firebase-functions": "^4.3.1"
+ },
+ "private": true
+ }
+ ```
+
+
+ 9. **Ensure Packages Are Included in `package.json`**
+
+ If you are using third-party packages (e.g., `axios`), make sure they are properly added to the `dependencies` section in `package.json`:
+
+ 
+
+
+ 10. **Validate Third-Party Package Versions**
+
+ The versions specified in your `package.json` should match available versions listed on **[npmjs.com](https://www.npmjs.com/package/axios?activeTab=versions)**.
+
+ 
+
+
+ 11. **Check for Undeployed Firebase Rules and Indexes:**
+
+ - Incomplete Firestore rules or indexes can block function deployment.
+ - Make sure all rules and indexes have been deployed from FlutterFlow.
+
+
+**Additional Troubleshooting and Optimization:**
+
+- **Trigger Configuration Issues**
+
+ If your Cloud Functions are not being triggered:
+
+ **Review Event Triggers:**
+
+ - For Firestore triggers: verify document paths and collection names.
+ - For HTTP functions: ensure correct setup in FlutterFlow.
+
+ **Check Permissions and Rules:**
+
+ - Firebase security rules and project permissions must allow the Cloud Function operations.
+
+- **Execution Timeouts**
+
+ - Cloud Functions may fail if execution time exceeds limits.
+ - Set a custom timeout duration in FlutterFlow:
+
+ 
+
+ For longer processing tasks, increase the timeout duration in your Cloud Function configuration.
+
+ Configuring Cloud Function regions in FlutterFlow can also optimize performance:
+
+ 
+
+ :::note
+ Longer timeouts may increase Firebase costs.
+ :::
+
+- **Cold Start Delays**
+
+ Cloud Functions may respond slower after periods of inactivity:
+ - Use **Cloud Scheduler** to periodically invoke functions and keep them warm.
+ - Minimize dependencies to reduce cold start delays.
+
+Following this comprehensive troubleshooting guide should help you resolve most issues encountered when working with Cloud Functions.
diff --git a/docs/troubleshooting/custom-actions/_category_.json b/docs/troubleshooting/custom-actions/_category_.json
new file mode 100644
index 00000000..46ff22c9
--- /dev/null
+++ b/docs/troubleshooting/custom-actions/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Custom Actions"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/custom-actions/custom_actions_errors.md b/docs/troubleshooting/custom-actions/custom_actions_errors.md
new file mode 100644
index 00000000..d42db13c
--- /dev/null
+++ b/docs/troubleshooting/custom-actions/custom_actions_errors.md
@@ -0,0 +1,141 @@
+---
+keywords: ['troubleshooting', 'actions', 'custom']
+slug: /troubleshooting/custom-actions/custom-actions-errors
+title: Custom Actions Errors
+---
+# Custom Actions Errors
+
+:::info[Prerequisites]
+- A basic understanding of how custom actions work.
+- A FlutterFlow project with a custom action already created.
+:::
+
+
+Custom actions are powerful, but troubleshooting them can be tricky. This guide will help you systematically resolve common issues.
+
+
+- **Read the Error Message**
+
+ Always read the error message printed during test mode, compilation, or local build. The message often provides a clue about the potential issue.
+
+- **Common Troubleshooting Checklist**
+
+ - **Action Name Mismatch**
+
+ Ensure the name in the action matches the custom action in your code.
+
+ 
+
+ :::tip
+ Use the `Add BoilerPlate Code` option to generate code with the correct action name.
+ :::
+
+ - **Imports and Arguments**
+
+ - Check that all required imports are present.
+ - Ensure arguments are defined in both the action settings and your code.
+
+ 
+
+ Example:
+
+ - Argument 1: Missing definition in settings panel
+ - Argument 2: Correctly imported
+ - Argument 3: Nullable selected, but not specified as nullable in code
+
+ Follow the steps below to fix this issue:
+
+ 1. Manually update arguments in both the settings panel and your code.
+ 2. Use the `Add BoilerPlate Code` option (on web, copy only what you need; on desktop, it may replace all code).
+
+ 
+
+ - **Name Conflicts**
+
+ - Avoid using the same name for an action and its argument.
+
+ 
+
+ - **Reserved Keywords**
+
+ - Do not use Dart/Flutter reserved keywords as argument names. **Examples:** `abstract`, `else`, `import`, `show`, `as`, `enum`, `in`, `static`, `this`.
+ *FlutterFlow usually warns you, but double-check!*
+
+ - **Return Type Mismatch**
+
+ - Ensure the custom action returns the correct data type as defined in the settings.
+
+ 
+
+ *The function should return the type specified in the settings panel.*
+
+ - **Internal Library Imports**
+
+ - If importing internal libraries (example, `../../flutterflow`), set **Exclude from compilation** to `true` if needed.
+
+ - **Pubspec Dependencies**
+
+ - Ensure your dependencies are declared in your code and are compatible with FlutterFlow.
+
+ 
+
+ Check for:
+ - Version conflicts (check on **[pub.dev](https://pub.dev)**)
+ - Multiple versions of the same dependency
+ - Conflicts with FlutterFlow's auto-imported dependencies
+
+ 
+
+ 
+
+ - **Code Errors:**
+
+ - **Null values:**
+
+ Handle null values safely.
+
+ ```js
+ int example = passingIntWhichMayBeNullable ?? 0;
+ ```
+ - **Correct data types:**
+
+ Convert data types explicitly.
+
+ ```js
+ String str = "5";
+ int result = int.parse(str); // ✅
+ ```
+ Use `.toString()`, `.toInt()`, `.toDouble()` as needed.
+
+ - **Single elements** vs **arrays:**
+
+ Ensure you are not passing a single element where a list is expected, or vice versa.
+
+ - **Exclude from Compilation**
+
+ If this option is enabled, the code won’t be checked during build but can still run during test..
+
+ 
+
+ - **Duplicate Data Types/Structs**
+
+ Do not redefine data types or structs already defined in the data schema panel.
+
+ 
+
+ - **Callback Data Types**
+
+ Ensure callback actions return the correct data type.
+
+ 
+
+
+:::info[Additional Resources]
+- **Debugging with the Browser Console:** Use the browser debug console for logic errors.
+- **FlutterFlow University Video**: [Custom Actions Video](https://www.youtube.com/watch?v=rKaD9eKuZkY).
+- **Official Docs:** [Custom Actions | FlutterFlow Docs](/concepts/custom-code/custom-actions/)
+:::
+
+:::tip
+When in doubt, regenerate the boilerplate and compare with your code. Consistency between settings and code is key!
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/custom-actions/testing_custom_actions_using_debug_console.md b/docs/troubleshooting/custom-actions/testing_custom_actions_using_debug_console.md
new file mode 100644
index 00000000..80bf90c6
--- /dev/null
+++ b/docs/troubleshooting/custom-actions/testing_custom_actions_using_debug_console.md
@@ -0,0 +1,41 @@
+---
+keywords: ['testing', 'debug', 'console']
+slug: /troubleshooting/custom-actions/testing-custom-actions-using-debug-console
+title: Testing Custom Actions Using Debug Console
+---
+# Testing Custom Actions using Debug Console
+
+Sometimes, the compiler does not show any errors in the custom action, but the custom action still won't work as expected. This might be due to the code logic or the implementation. In order to test the implementation and the flow, you can use the debug console to test the custom action in different scenarios.
+
+:::info[Prerequisites]
+- You have created a custom action in FlutterFlow.
+- You are familiar with using Run Mode and viewing the browser console.
+:::
+
+The core function that you can use to test the custom actions on the console is the `debugPrint` function in Flutter. To use that in the custom actions, follow the steps below:
+
+1. **Add `debugPrint` Statements in the Code**
+
+ Use `debugPrint` to print some error on the debug console in case of a specific result. You can use if-else statements or try-catch statements in order to test the success of the scenario.
+
+ 
+
+ Example:
+
+ ```js
+ try {
+ final result = someFunction();
+ debugPrint('Function result: $result');
+ } catch (e) {
+ debugPrint('Error occurred: $e');
+ }
+
+2. **Run the App and Open Console**
+
+ After the correct implementation in the code, use the action inside the app. On the run mode, open the console. Now you should be able to see the errors in the console upon performing the action.
+
+ 
+
+:::info[Still having issues?]
+If you continue to experience issues after testing your logic with debugPrint, please contact support at support@flutterflow.io.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/_category_.json b/docs/troubleshooting/deployment/_category_.json
new file mode 100644
index 00000000..a068a3de
--- /dev/null
+++ b/docs/troubleshooting/deployment/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Deployment"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/codemagic_deployment_error_identification.md b/docs/troubleshooting/deployment/codemagic_deployment_error_identification.md
new file mode 100644
index 00000000..5a5f6c01
--- /dev/null
+++ b/docs/troubleshooting/deployment/codemagic_deployment_error_identification.md
@@ -0,0 +1,36 @@
+---
+keywords: ['deployment', 'error', 'identification']
+slug: /troubleshooting/deployment/codemagic-deployment-error-identification
+title: Codemagic Deployment Error Identification
+---
+# Codemagic Deployment Error Identification
+
+Follow the steps below to identify your codemagic error:
+
+- Press **Cmd/Ctrl + k**, type **"deployment"** and hit enter. It will take you to the deployment page.
+
+ 
+
+- Navigate to the Deployment section by clicking **Project Settings** > **Deployment** (under App Settings).
+
+ 
+
+
+- Click on the **Failed (VIEW LOGS)** text to see the logs.
+
+ 
+
+ In this step, you'll need to note the Failed Step that been displayed by CodeMagic error log.
+
+ 
+
+
+- Now, press **Cmd/Ctrl + F** to search for the term **"error"** in the logs to find the root cause of the issue. Keep pressing **"Enter"** till you find the error ( this is usually at the bottom of the logs ).
+
+ If you search for "error" and still don't find an error message that makes sense to you then you can also try with the following keyword: "message".
+
+ 
+
+- Now select and copy this error message and paste it in the Help Center search in the chat icon in the bottom-right corner to search the error. This will help you find the help article for this issue and then you can find the fix for it.
+
+ 
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/codemagic_deployment_tips.md b/docs/troubleshooting/deployment/codemagic_deployment_tips.md
new file mode 100644
index 00000000..3aa48b30
--- /dev/null
+++ b/docs/troubleshooting/deployment/codemagic_deployment_tips.md
@@ -0,0 +1,15 @@
+---
+keywords: ['deployment', 'tips', 'codemagic']
+slug: /troubleshooting/deployment/codemagic-deployment-tips
+title: CodeMagic Deployment Tips
+---
+# CodeMagic Deployment Tips
+
+Here are some tips to avoid Deployment issues:
+
+:::tip
+- Make sure you've followed all the steps for **[setting up deployment](/deployment/deploy-for-environments/#mobile-deployment)** in your project.
+- If you choose a deployment source from a GitHub Repository then please make sure that it's associated with FlutterFlow's GitHub integration.
+- If you are deploying to the Play Store from a GitHub repo, make sure to modify your build.gradle file to sign in release mode.
+- Setting a version number is optional but may be required for specific cases. If you are updating an existing app that has not been deployed using FlutterFlow yet, you will want to specify a version number.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/deployment_issues_with_stripe_integration.md b/docs/troubleshooting/deployment/deployment_issues_with_stripe_integration.md
new file mode 100644
index 00000000..35720156
--- /dev/null
+++ b/docs/troubleshooting/deployment/deployment_issues_with_stripe_integration.md
@@ -0,0 +1,54 @@
+---
+keywords: ['deployment', 'issues', 'integration']
+slug: /troubleshooting/deployment/deployment-issues-with-stripe-integration
+title: Deployment Issues with Stripe Integration
+---
+# Deployment Issues with Stripe Integration
+
+Integrating Stripe in your FlutterFlow project can help you accept payments efficiently. However, some common deployment issues may arise. This article outlines key steps and best practices to ensure a smooth Stripe integration and deployment experience.
+
+1. **Firebase Connection**
+
+ Stripe integration requires a connected Firebase project. Before running through this checklist, it's important to ensure your FlutterFlow project is linked to Firebase, a crucial step for successful payment processing. Detailed guidance can be found at **[FlutterFlow's Firebase Setup Guide](/integrations/firebase/connect-to-firebase/#step-1-set-up-your-project)**.
+
+2. **Upgrade to Firebase Blaze Plan**
+
+ Stripe functionality requires a Firebase Blaze Plan for operational capabilities. To avoid disruptions, you will need to upgrade from the Firebase Spark plan to the Blaze plan. Learn more about **[Google's process for upgrading](https://firebase.google.com/docs/projects/billing/firebase-pricing-plans)**.
+
+3. **Set the Google Cloud Platform (GCP) Location**
+
+ A defined Google Cloud Platform (GCP) location for your Firebase project ensures the correct regional operation of services. The absence of a set location can hinder the deployment process.
+
+ 
+
+4. **Firebase Project Permissions**
+
+ Ensure you have the necessary permissions enabled for your Firebase project. Two critical permissions involve access management and service configuration. You can also reference the **[setup guide](/integrations/firebase/connect-to-firebase/#step-1-set-up-your-project)** as well.
+
+ 
+
+5. **Correct Merchant Code**
+
+ Use the correct 3-letter merchant country code (e.g., "GBR" for the United Kingdom vs. "UK"). Incorrect codes can lead to failed transactions. For accurate codes, refer to **[IBAN Country Codes](https://www.iban.com/country-codes)**.
+
+ 
+
+ 
+
+6. **Test and Live Keys**
+
+ For deployment, both Test and Live Stripe keys must be configured in your project settings, regardless of the development stage. This ensures Stripe's API can properly interact with your application.
+
+ 
+
+7. **Consistent Region Settings**
+
+ Align your Firebase project's region with that of your FlutterFlow settings to prevent deployment failures. Inconsistencies can cause function deployment issues.
+
+ 
+
+ 
+
+If you find that this article hasn't fully addressed your concerns or if you have more questions, please don't hesitate to reach out to us at support@flutterflow.io
+
+
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/fixing_razorpay_deployment.md b/docs/troubleshooting/deployment/fixing_razorpay_deployment.md
new file mode 100644
index 00000000..7c4fc41c
--- /dev/null
+++ b/docs/troubleshooting/deployment/fixing_razorpay_deployment.md
@@ -0,0 +1,57 @@
+---
+keywords: ['deployment', 'firebase', 'razorpay']
+slug: /troubleshooting/deployment/fixing-razorpay-deployment
+title: Fixing Razorpay Deployment
+---
+# Fixing Razorpay Deployment
+
+Razorpay is a major payment processor in India. Integrating **[Razorpay](https://razorpay.com/)** can allow users to make payments using their app. This article outlines some common scenarios and troubleshooting instructions for Razorpay deployment issues.
+
+1. **Firebase Integration and Auth**
+
+ FlutterFlow uses Firebase integration and cloud functions to facilitate Razorpay payments. Ensure you have Firebase configured in your FlutterFlow project and that Firebase Auth is enabled.
+
+ 
+ 
+
+2. **Firebase Blaze Plan**
+
+ Razorpay uses cloud functions behind the scenes to facilitate payments. Cloud functions are a part of Firebase's "Blaze" plan. You must upgrade from the Firebase Spark plan to the Blaze plan to avoid disruptions. Learn how to upgrade here. On the bottom left side of your Firebase console, you will see which plan you are on
+
+ 
+
+3. **Set Google Cloud Location**
+
+ Ensuring your Firebase project is pinned to a specific Google Cloud Platform (GCP) location is key for optimal service functionality across regions. Skipping this step could result in errors.
+
+ 
+
+4. **Firebase Project Permissions**
+
+ Make sure your Firebase project has the required permissions activated. Access management and service configuration are two essential permissions to focus on. For guidance on setting these up, look at the instructions in the **[FlutterFlow Project Setup](/resources/projects/settings/project-setup/)**.
+
+5. **Razorpay Keys Check**
+
+ Make sure to copy and paste the correct Key ID and Key Secret from Razorpay for testing and production, respectively. For testing, make sure "Is Production" is turned off.
+
+ 
+
+ 
+
+ 
+
+6. **Razorpay Business Name**
+
+ Finally, ensure you have entered the proper "Business Name" in the Razorpay additional settings in FlutterFlow. Make sure this business name matches your business name in Razorpay records.
+
+ 
+
+:::info[Other Considerations]
+Razorpay currently works only on mobile (Android and iOS). This is due to a limitation from Razorpay's Flutter Package. If you are planning to collect payments on a web app - consider using Stripe.
+
+
+
+:::
+
+If you are still facing issue with deploying Razorpay on Flutterflow, please feel free to reach out to support@flutterflow.io
+
diff --git a/docs/troubleshooting/deployment/fixing_stripe_deployment_and_payment_errors.md b/docs/troubleshooting/deployment/fixing_stripe_deployment_and_payment_errors.md
new file mode 100644
index 00000000..90e7ecd5
--- /dev/null
+++ b/docs/troubleshooting/deployment/fixing_stripe_deployment_and_payment_errors.md
@@ -0,0 +1,106 @@
+---
+keywords: ['deployment', 'payment', 'issues']
+slug: /troubleshooting/deployment/fixing-stripe-deployment-and-payment-errors
+title: Fixing Stripe Deployment & Payment Errors
+---
+# Fixing Stripe Deployment & Payment Errors
+
+Integrating Stripe for payment processing in FlutterFlow can significantly simplify monetization. However, developers may encounter issues during deployment or while managing transactions. This guide outlines common deployment and payment issues—and how to fix them—to help ensure a seamless Stripe integration experience in FlutterFlow apps.
+
+## Deployment Checklist for Stripe Integration
+
+1. **Firebase Connection**
+
+ Stripe integration requires a connected Firebase project. Before running through this checklist, it's important to ensure your FlutterFlow project is linked to Firebase, a crucial step for successful payment processing. Detailed guidance can be found at **[FlutterFlow's Firebase Setup Guide](/integrations/firebase/connect-to-firebase/)**.
+
+2. **Upgrade to Firebase Blaze Plan**
+
+ Stripe functionality requires a Firebase Blaze Plan for operational capabilities. To avoid disruptions, you will need to upgrade from the Firebase Spark plan to the Blaze plan. Learn more about **[Google's process for upgrading](https://firebase.google.com/docs/projects/billing/firebase-pricing-plans)**.
+
+3. **Set the Google Cloud Platform (GCP) Location**
+
+ A defined Google Cloud Platform (GCP) location for your Firebase project ensures the correct regional operation of services. The absence of a set location can hinder the deployment process.
+
+ 
+
+4. **Firebase Project Permissions**
+
+ Ensure you have the necessary permissions enabled for your Firebase project. Two critical permissions involve access management and service configuration. You can also reference the **[setup guide](/integrations/firebase/connect-to-firebase/)**.
+
+ 
+
+5. **Correct Merchant Code**
+
+ Use the correct 3-letter merchant country code (example., "GBR" for the United Kingdom vs. "UK"). Incorrect codes can lead to failed transactions. For accurate codes, refer to **[IBAN Country Codes](https://www.iban.com/country-codes)**.
+
+ 
+
+ 
+
+6. **Test and Live Keys**
+
+ Both Test and Live Stripe keys must be configured in your project settings, regardless of the development stage. This ensures Stripe's API can properly interact with your application.
+
+ 
+
+7. **Consistent Region Settings**
+
+ Align your Firebase project's region with that of your FlutterFlow settings to prevent deployment failures. Inconsistencies can cause function deployment issues.
+
+ 
+
+ 
+
+## Addressing Payment Transaction Issues
+
+1. **Authentication Requirement**
+
+ Stripe payments **require an authenticated user session**. Before initiating payment processes, ensure your application logic includes user login or account creation.
+
+2. **Payment Modal Variations**
+
+ It's important to note that web and mobile platforms present different payment modal presentations. These UI differences are out-of-the-box for Stripe and cannot currently be customized within FlutterFlow.
+
+3. **Price Format**
+
+ Prices should be submitted to Stripe in **cents**, not **dollars**. Utilize a custom function to convert dollar values to cents for accurate transaction processing.To set a price in cents to Stripe, you can simply use a custom function that takes the price in dollars and returns it as cents.
+
+ Here is a custom code you can use to make this calculation in a custom function:
+
+ ```js
+ int dollarToCent(double amount) {
+ // Convert the amount to a string
+ String st = amount.toString();
+
+ // Remove any dots or commas
+ st = st.replaceAll('.', '');
+ st = st.replaceAll(',', '');
+
+ // Convert the cleaned string to an integer
+ return int.parse(st);
+ }
+ ```
+
+ // Input: 14.99
+
+ // Output: 1499 cents
+
+
+4. **CORS Error Resolution**
+
+ A CORS error during payment initiation often indicates a permissions issue with your Firebase function. Verify and adjust the `allUsers` permission for your Stripe function in the Firebase console to resolve this error.
+
+ 
+
+ 
+
+5. **Subscriptions**
+
+ Currently, Apple and Google restrict Stripe subscriptions on mobile platforms. To expand your subscription capabilities, you can use alternative solutions like RevenueCat for mobile apps and direct API calls for web applications.
+
+:::info[**For further information and troubleshooting:**]
+- [Stripe Documentation](https://stripe.com/docs)
+- [Stripe Payments](https://stripe.com/payments)
+- [FlutterFlow University](https://university.flutterflow.io/)
+- [Payments - Intro | FlutterFlow University](https://university.flutterflow.io/courses/flutterflow-payments)
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/resolve_errors_in_downloaded_code.md b/docs/troubleshooting/deployment/resolve_errors_in_downloaded_code.md
new file mode 100644
index 00000000..2ff4d251
--- /dev/null
+++ b/docs/troubleshooting/deployment/resolve_errors_in_downloaded_code.md
@@ -0,0 +1,35 @@
+---
+keywords: ['flutter', 'downloaded', 'code']
+slug: /troubleshooting/deployment/resolve-errors-in-downloaded-code
+title: Resolve Errors in Downloaded Code
+---
+# Resolve Errors in Downloaded Code
+
+When you download your project from FlutterFlow and run it locally in your IDE, you may encounter errors due to Flutter version mismatches. This guide outlines how to resolve these issues by ensuring your local Flutter version matches the version supported by FlutterFlow.
+
+1. **Check FlutterFlow’s supported Flutter version**
+
+ To find the Flutter version currently supported by FlutterFlow:
+ - Open the FlutterFlow dashboard.
+ - Navigate to your project settings or export screen.
+ - Locate the displayed Flutter version used for your project.
+
+ 
+
+2. **Verify the Flutter version on your machine**
+
+ To check the Flutter version installed locally, run the following command in your terminal:
+
+ ```js
+ flutter --version
+ ```
+ Here's an example of how you can do that:
+
+ 
+
+3. **Upgrading or Downgrading to the correct Flutter version**
+
+ If the current version on your machine is different than what is currently supported by FlutterFlow, you can downgrade or upgrade to the supported version. You can learn more about [**upgrading Flutter**](/testing/local-run/#4-running-app-on-device). By following these steps, you can fix the errors that you face after downloading the code and run locally.
+
+
+If you continue to experience issues, contact the FlutterFlow support team via live chat or email at support@flutterflow.io.
\ No newline at end of file
diff --git a/docs/troubleshooting/deployment/run_mode_build_failure.md b/docs/troubleshooting/deployment/run_mode_build_failure.md
new file mode 100644
index 00000000..cea172f5
--- /dev/null
+++ b/docs/troubleshooting/deployment/run_mode_build_failure.md
@@ -0,0 +1,103 @@
+---
+keywords: ['build', 'configuration', 'release']
+slug: /troubleshooting/deployment/run-mode-build-failure
+title: 'Run Mode: Build Failure'
+---
+# Run Mode: Build Failure
+
+Encountering a "Run mode: Build failed" error can be frustrating when you're eager to see your app in action. This error typically signifies a project issue that prevents a successful build. Addressing these errors promptly ensures your app's functionality and performance.
+
+This guide provides a structured approach to troubleshooting and resolving "Run mode: Build failed" errors, ensuring a smooth development process for your projects.
+
+- **Recognizing the Error**
+
+ Here's what the "Run mode: Build failed" error looks like inside of FlutterFlow:
+
+ 
+
+- **Understanding Test Mode vs. Run Mode**
+
+ Here's a little background on run mode vs. test mode in FlutterFlow. Test mode runs as a "test" to help you identify errors before deployment. These features include a debugger and display warnings. Alternatively, run mode attempts to run the app in **release mode** to better mimic what your users can expect in production. In release mode, **warnings are mostly suppressed**, meaning it's important to ensure you are acknowledging and addressing warnings in debug mode before you enter run mode.
+
+ The "Run mode: Build failed" error can occur under various circumstances, during:
+
+ - Run mode
+
+ - APK download
+
+ - Code download
+
+ - GitHub push
+
+ - And more
+
+## Common Scenarios and Solutions
+
+- **Custom Code Failures**
+
+ - **Issue**: Your project's custom code doesn't show errors within the editor, but errors appear when you try to run the app.
+
+ - **Example**: A custom widget lacks web support.
+
+ - **Solution**: Verify on pub.dev or equivalent platforms that the custom code supports the necessary platforms (example, web, iOS, Android).
+
+ - **Best practice**: Consider running the code locally on a sample Flutter project before implementing the custom code inside FlutterFlow to identify possible errors logged.
+
+- **Widget Failures**
+
+ - **Issue**: A widget within your app causes the build to fail due to errors.
+
+ - **Example**: Actions assigned to a widget are incomplete or improperly configured.
+
+ - **Solution**: Locate the error-causing widget (usually identified in the error message)
+
+ To correct the issue:
+
+ - Ensure the widget tree is correctly formatted
+
+ - Verify that widgets are named clearly for easy identification
+
+- **Build Fails Without Error Messages**
+
+ - **Issue**: The build process fails without displaying an error message, making it challenging to diagnose the problem.
+
+ - **Solution**: Download and run the project code locally with a debugger to identify and resolve the issue. If downloading the code is problematic, check your browser's console for errors that might indicate the cause.
+
+ 
+
+- **Grey Screen in Run Mode**
+
+ - **Issue**: Encountering a grey screen in run mode usually indicates an error suppressed by the release mode.
+
+ - **Solution**: Run the app in test mode to potentially reveal the error for troubleshooting. If test mode does not display errors, use the browser's developer console for clues.
+
+## Checklist for Troubleshooting
+
+- **Identify when and where the error occurs**:
+
+ Determine if the error is specific to run mode, test mode, or other instances like APK download or code download.
+
+- **Locate the source of the error**:
+
+ The error message often provides clues about where the problem lies, whether in custom code, a specific widget, or elsewhere.
+
+- **Check for platform support**:
+
+ For issues related to custom code, ensure compatibility with your target platforms.
+
+- **Examine widget configuration**:
+
+ Verify that all actions and configurations associated with widgets are complete and correct.
+
+- **Utilize local debugging**:
+
+ If the error is elusive, running the debugger locally on your downloaded code can help identify the issue.
+
+- **Leverage browser tools**:
+
+ The browser's console and developer tools can offer insights, especially when dealing with errors that don't manifest in traditional debug outputs.
+
+
+:::info[Additional Resources]
+[Basic Troubleshooting Guide – FlutterFlow Documentation](https://docs.flutterflow.io/troubleshooting/basic-troubleshooting-guide)
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/firebase/_category_.json b/docs/troubleshooting/firebase/_category_.json
new file mode 100644
index 00000000..4a0d3676
--- /dev/null
+++ b/docs/troubleshooting/firebase/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Firebase"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/firebase/client_access_to_firestore_expired.md b/docs/troubleshooting/firebase/client_access_to_firestore_expired.md
new file mode 100644
index 00000000..ad581c5e
--- /dev/null
+++ b/docs/troubleshooting/firebase/client_access_to_firestore_expired.md
@@ -0,0 +1,53 @@
+---
+keywords: ['database', 'firebase', 'client']
+slug: /troubleshooting/firebase/client-access-to-firestore-expired
+title: Client Access to Firestore Expired
+---
+# Client Access to Firestore Expired
+
+You may receive an email from Firebase with the subject:
+
+**"Client access to your Cloud Firestore database expired"**
+
+This message typically appears when your Firestore database is in **Test Mode** and the access duration has expired.
+
+You are seeing this error message because of the following:
+
+ When setting up Firestore for the first time, Firebase offers two rule options:
+
+ 1. **Test Mode** – Temporarily allows open access (expires after 30 days).
+ 2. **Production Mode** – Starts off restricted and requires secure rules.
+
+ 
+
+If you selected **Test Mode** during setup, Firestore access will automatically expire after the preset period. To continue using Firestore, you'll need to update the rules using one of the following options:
+
+- **Option 1: Manage Firestore Rules From FlutterFlow**
+
+ You can **[manage and deploy Firestore rules](/integrations/database/cloud-firestore/firestore-rules/)** directly from FlutterFlow.
+
+- **Option 2: Manually Update Firestore Rules in Firebase Console**
+
+ Follow these steps to manually update the rules:
+
+ 1. Go to the **[Firebase Console](https://console.firebase.google.com/)**.
+ 2. Open your project and navigate to **Firestore Database**.
+ 3. Select the **Rules** tab.
+
+ From here, you have two options:
+
+ - **Option A: Extend Test Mode**
+
+ Update the expiration timestamp to a future date if you're still in development.
+
+ 
+
+ - **Option B: Secure Your Rules for Production**
+
+ Update your rules to enforce proper authentication and access controls.
+
+
+ 
+
+
+If the issue persists, contact us at [support@flutterflow.io](mailto:support@flutterflow.io) for further assistance.
diff --git a/docs/troubleshooting/firebase/configuring_cors_for_firebase_storage.md b/docs/troubleshooting/firebase/configuring_cors_for_firebase_storage.md
new file mode 100644
index 00000000..c2462cce
--- /dev/null
+++ b/docs/troubleshooting/firebase/configuring_cors_for_firebase_storage.md
@@ -0,0 +1,84 @@
+---
+keywords: ['storage', 'firebase', 'cors']
+slug: /troubleshooting/firebase/configuring-cors-for-firebase-storage
+title: Configuring CORS for Firebase Storage
+---
+# Configuring CORS for Firebase Storage
+
+When you deploy your web app to a custom domain, the domain and the Firebase Storage bucket are hosted on different servers. This means that the browser will block requests to the Firebase Storage bucket from your web app, because the origins (the domains and ports) of the two servers are different.
+
+**What is CORS?**
+
+CORS stands for **Cross-Origin Resource Sharing**. It allows you to specify which origins are allowed to access your resources. By configuring CORS, you can tell the browser that your web app is allowed to make requests to the Firebase Storage bucket, even though the two servers are hosted on different domains.
+
+Follow these steps to configure CORS for your Firebase Storage bucket:
+
+1. Open **[Google Cloud Console](https://console.cloud.google.com)**.
+
+2. **Launch the Cloud Shell**:
+
+ Click the **Activate Cloud Shell** icon in the top-right corner.
+
+ 
+
+ Wait for the terminal to load.
+
+ 
+
+
+3. **Run the following Command:**
+
+ ```jsx
+ gcloud config set project your-firebase-project-id;
+ ```
+
+4. **Define and upload your cors.json file:**
+
+ The `cors.json` file contains a list of origins that are allowed to access your resources. Each origin is a string that identifies a domain or port. For example, the following origin allows access from the domain `www.example.com`:
+
+ ```jsx
+ "origins": ["https://www.example.com"]
+ ```
+
+ You can also specify a list of allowed headers. The following example allows access to the `Content-Type` and `Authorization` headers:
+
+ ```jsx
+ "origins": ["https://www.example.com"], "allowedHeaders": ["Content-Type", "Authorization"]
+ ```
+
+ To allow any origin to access your resource, you can use `*`. The `cors.json` file below allows any origin to access, but not modify your resources.
+
+ ```jsx
+ [
+ {
+ "origin": ["*"],
+ "method": ["GET"],
+ "maxAgeSeconds": 3600
+ }
+ ]
+ ```
+
+ Once you have defined your `cors.json` file, upload it to Google Cloud Console.
+
+ 
+
+ To confirm that you have uploaded it correctly, you can run `ls` in your console and you should see your `cors.json` file listed.
+
+
+5. **Run the `cors` Command to Configure CORS:**
+
+ ```jsx
+ gcloud storage buckets update gs://your-google-storage-bucket-name --cors-file=cors.json
+ ```
+
+6. **(Optional) Confirm success by viewing the CORS of your bucket**
+
+ Run the following command to confirm that the rules from your `cors.json` file were applied.
+ ```jsx
+ gcloud storage buckets describe gs://your-google-storage-bucket-name --format="default(cors_config)"
+ ```
+ You should see the same allowed origins and any other info defined in your `cors.json` file.
+
+For more information on configuring CORS in Firebase Storage, please see the **[official documentation](https://firebase.google.com/docs/storage/web/download-files#cors_configuration)**.
+
+
diff --git a/docs/troubleshooting/firebase/content_manager_firestore_error.md b/docs/troubleshooting/firebase/content_manager_firestore_error.md
new file mode 100644
index 00000000..a7fbdfb7
--- /dev/null
+++ b/docs/troubleshooting/firebase/content_manager_firestore_error.md
@@ -0,0 +1,90 @@
+---
+keywords: ['security', 'error', 'firebase', 'permissions']
+slug: /troubleshooting/firebase/content-manager-firestore-error
+title: Content Manager Firestore Error
+---
+
+# Content Manager Firestore Error
+
+You may see the following error message when accessing the **FlutterFlow Content Management System (CMS)**:
+
+
+
+This error typically occurs when Firebase permissions or authentication settings are not properly configured. Follow the steps below to resolve it.
+
+1. **Enable Email/Password Sign-In**
+
+ 1. Open the **[Firebase Console](https://console.firebase.google.com/)**.
+ 2. Select your project.
+ 3. From the left-hand menu, click **Authentication**.
+ 4. Click **Get started** (if not already started).
+ 5. Go to the **Sign-in method** tab.
+ 6. Ensure **Email/Password** is listed and marked as **Enabled** ✅.
+
+ 
+
+ :::note
+ If Email/Password is not enabled, turn it on by clicking the pencil icon and toggling the setting.
+ :::
+
+
+2. **Add Required Firebase Project Permissions**
+
+ FlutterFlow requires the following roles to be granted to `firebase@flutterflow.io` for proper functionality:
+
+ - Editor
+ - Cloud Functions Admin
+ - Service Account Admin
+
+ To add these permissions:
+
+ 1. In the **[Firebase Console](https://console.firebase.google.com/)**, open your project.
+ 2. Navigate to **Project Settings** > **Users & Permissions**.
+ 3. Check if `firebase@flutterflow.io` has the roles listed above.
+
+ 
+
+ :::info
+ If these roles are missing, the integration is incomplete. Make sure to add all three roles.
+ :::
+
+
+3. **Update Firestore Rules in FlutterFlow**
+
+ 1. In your FlutterFlow project, go to **Firestore** > **Settings**.
+ 2. Scroll down to the **Firestore Rules** section.
+ 3. Click **Deploy/Redeploy** to apply your latest rules.
+
+ 
+
+
+4. **Define Your Firebase Schema**
+
+ Make sure your Firebase schema is fully defined. The Content Manager only displays fields that are already defined in your Firebase schema.
+
+
+5. **Ensure You're Using the Latest FlutterFlow Version**
+
+ Press `Ctrl + R` (on Windows) or `Cmd + R` (on macOS) to refresh and ensure you’re on the latest version of FlutterFlow.
+
+
+6. **Clear Cache and Re-Login**
+
+ After completing the above steps:
+
+ - Clear your browser cache.
+ - Log out and log back into FlutterFlow.
+
+
+
+
+:::info[Still not working?]
+Try reconfiguring permissions from scratch.
+
+If none of the steps resolve the issue:
+1. Remove existing Firebase permissions.
+2. Re-add all necessary roles from scratch.
+3. Follow the full setup instructions in the **[official FlutterFlow Firebase integration guide](/integrations/firebase/connect-to-firebase/)**.
+:::
+
+By following the steps above, you should be able to resolve the error and continue using FlutterFlow CMS without interruptions.
\ No newline at end of file
diff --git a/docs/troubleshooting/firebase/firebase_android_config_file_missing.md b/docs/troubleshooting/firebase/firebase_android_config_file_missing.md
new file mode 100644
index 00000000..ab549439
--- /dev/null
+++ b/docs/troubleshooting/firebase/firebase_android_config_file_missing.md
@@ -0,0 +1,38 @@
+---
+keywords: ['firebase', 'android', 'configuration']
+slug: /troubleshooting/firebase/firebase-android-config-file-missing
+title: Firebase Android Config File Missing
+---
+
+# Firebase Android Config File Missing
+
+You may see the following warning in FlutterFlow, as shown in the image below:
+
+
+
+This typically means that the Firebase Android configuration file (`google-services.json`) has not been generated or uploaded to your FlutterFlow project.
+
+Follow the steps below to fix the issue:
+
+1. **Verify your Firebase Setup**
+
+ Make sure that Firebase has been fully configured for your project. Follow the **[Firebase setup guide](/integrations/firebase/connect-to-firebase/)** to ensure all required steps have been completed.
+
+2. **Open Project Settings in FlutterFlow**
+
+ - Navigate to your FlutterFlow project.
+ - From the left menu, select **Settings > Firebase**.
+
+ 
+
+3. **Regenerate your Firebase Configuration Files**
+
+ - In the Firebase Settings screen, click **Regenerate Firebase Files** to create new configuration files and upload them automatically.
+
+4. **Contact Support if Needed**
+
+ If you continue to experience issues, reach out to [FlutterFlow Support](mailto:support@flutterflow.io) for further assistance.
+
+:::note
+The configuration file is required for successful builds and deployment on Android. Make sure it remains up-to-date if you make changes in your Firebase project.
+:::
diff --git a/docs/troubleshooting/firebase/firebase_storage_limits_in_flutterflow.md b/docs/troubleshooting/firebase/firebase_storage_limits_in_flutterflow.md
new file mode 100644
index 00000000..93c3c318
--- /dev/null
+++ b/docs/troubleshooting/firebase/firebase_storage_limits_in_flutterflow.md
@@ -0,0 +1,53 @@
+---
+keywords: ['storage', 'firebase', 'flutterflow']
+slug: /troubleshooting/firebase/firebase-storage-limits-in-flutterflow
+title: Firebase Storage Limits in FlutterFlow
+---
+
+# Firebase Storage Limits in FlutterFlow
+
+Managing Firebase Storage properly is essential for controlling your app's file storage and associated costs in FlutterFlow. This article summarizes the current limits and best practices following Firebase’s September 2024 changes.
+
+## Firebase Storage Plans and Limits
+
+- **Blaze Plan (Pay-as-you-go)**
+
+ - Firebase Storage (Cloud Storage for Firebase) is only available on the Blaze plan for new Firebase projects.
+ - Storage charges are based on usage volume.
+ - The price per GB/TB decreases as your usage increases.
+ - Refer to the **[Firebase Pricing page](https://firebase.google.com/pricing)** for current rates.
+
+- **Spark Plan (Free Tier)**
+
+ - For projects created after September 2024, Cloud Storage for Firebase is **no longer available** on the Spark plan.
+ - To use file storage (uploads, images, videos, etc.) with Firebase Storage, you must upgrade to the Blaze plan.
+
+:::info
+If your Firebase project was created before the September 2024 policy change, you may still have limited access to Firebase Storage under legacy conditions. However, new projects must follow the updated Blaze-only policy.
+:::
+
+## Firebase Storage Operations Limits
+
+ - Firebase imposes limits on the number of operations (uploads, downloads, deletes) based on your plan.
+ - With Blaze, these limits are generally higher but still subject to quotas depending on your usage volume.
+ - Monitor your app’s usage patterns to avoid unexpected failures or costs.
+
+## Best Practices for Managing Firebase Storage
+
+ - Regularly delete unused or unnecessary files.
+ - Compress large files (especially images and videos) before uploading.
+ - Actively monitor storage usage in the Firebase Console.
+ - Set up automated cleanup processes for apps with large or growing data volumes.
+
+:::tip
+Proactive storage management helps control costs and maintain app performance.
+:::
+
+:::info[Additional Resources]
+- [Firebase Pricing](https://firebase.google.com/pricing)
+- [Firebase Storage FAQ (September 2024 Changes)](https://firebase.google.com/docs/storage/faqs-storage-changes-announced-sept-2024)
+- [Firebase Storage Documentation](https://firebase.google.com/docs/storage)
+- [FlutterFlow Docs: Storage](/integrations/firebase-storage/storage-rules/)
+:::
+
+Always review your Firebase plan details to ensure you're aligned with the most current pricing model and storage policies.
diff --git a/docs/troubleshooting/firebase/get_the_sum_of_firebase_document_or_api_values.md b/docs/troubleshooting/firebase/get_the_sum_of_firebase_document_or_api_values.md
new file mode 100644
index 00000000..ebe6a16d
--- /dev/null
+++ b/docs/troubleshooting/firebase/get_the_sum_of_firebase_document_or_api_values.md
@@ -0,0 +1,52 @@
+---
+keywords: ['firebase', 'api', 'document']
+slug: /troubleshooting/firebase/get-the-sum-of-firebase-document-or-api-values
+title: Get the Sum of Firebase Document or API Values
+---
+# Get the Sum of Firebase Document or API Values
+
+Sometimes you need to display a total, such as a subtotal or count based on data fetched from Firebase or an API. This guide walks you through the steps to calculate and display that sum in FlutterFlow.
+
+:::info[Prerequisites]
+- A working Firebase collection or API that returns numeric values.
+- A FlutterFlow UI component (example, **Text**) where the sum will be displayed.
+:::
+
+**Steps to Calculate the Sum of Firebase Document or API Values**
+
+1. **Identify where to Display the Total**
+
+ Decide where in your app the total will appear. For example, insert a **Text** widget that will show the computed sum.
+
+ 
+
+2. **Prepare your Data Type**
+
+ Next, you need to specify what kind of data you're adding up. For example, if you're working with numbers with decimal points, you'll classify your data as double. Make sure to indicate that you're dealing with a list of these values.
+
+ 
+
+
+3. **Retrieve and Map your Data**
+
+ When fetching data from Firebase or an API, extract the values you want to sum. Use the `map()` function to create a list of those values.
+
+ 
+
+4. **Calculate the Sum**
+
+ With your list of values ready, store them in a variable (let's call it `var1`). Then, decide on the format you want for your result. Use the `reduce` function to add up all the values in your list, `var1`, to get your total sum.
+
+ 
+
+5. **Checking Your Results**
+
+ After completing these steps, you should have the total sum displayed where you need it. If it looks right, you've successfully calculated the sum!
+
+ [](../assets/20250430121220338400.png)
+
+:::tip[Trobleshooting]
+- Use `.isNotEmpty` to prevent errors when the list is empty.
+- Format the output using `.toStringAsFixed(2)` to show 2 decimal places if needed.
+- Optional: Store the sum in a global variable for use across multiple pages.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/firebase/missing_firebase_storage_in_flutterflow_settings.md b/docs/troubleshooting/firebase/missing_firebase_storage_in_flutterflow_settings.md
new file mode 100644
index 00000000..928e20b5
--- /dev/null
+++ b/docs/troubleshooting/firebase/missing_firebase_storage_in_flutterflow_settings.md
@@ -0,0 +1,35 @@
+---
+keywords: ['storage', 'firebase', 'missing']
+slug: /troubleshooting/firebase/missing-firebase-storage-in-flutterflow-settings
+title: Missing Firebase Storage in FlutterFlow Settings
+---
+
+# Missing Firebase Storage in FlutterFlow Settings
+
+When setting up Firebase Storage in your FlutterFlow project, you may notice that the **Firebase Storage** option is missing from the **Firebase Settings** tab.
+
+ 
+
+This usually happens when Firebase Storage has not been enabled for your project in the Firebase Console. Until it’s enabled there, the option won’t appear in FlutterFlow.
+
+Follow these steps to enable Firebase Storage and make it available in your FlutterFlow settings:
+
+1. In your FlutterFlow project, click **Firebase** from the left menu, then click **Open Firebase Console**.
+
+ 
+
+2. In the Firebase Console, go to the **Build** menu and select **Storage**.
+
+ 
+
+3. Click **Get started** and complete the setup process.
+
+ 
+
+4. After successfully creating the storage bucket, return to FlutterFlow. You should now see the **Rules** option under **Firebase Settings**.
+
+ 
+
+:::note
+After setting up Firebase Storage, it may take up to one hour for the changes to appear in FlutterFlow.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/firebase/resolving_firestore_index_deployment_issues.md b/docs/troubleshooting/firebase/resolving_firestore_index_deployment_issues.md
new file mode 100644
index 00000000..558bb749
--- /dev/null
+++ b/docs/troubleshooting/firebase/resolving_firestore_index_deployment_issues.md
@@ -0,0 +1,51 @@
+---
+keywords: ['firebase', 'deployment', 'firestore']
+slug: /troubleshooting/firebase/resolving-firestore-index-deployment-issues
+title: Resolving Firestore Index Deployment Issues
+---
+# Resolving Firestore Index Deployment Issues
+
+If your Firestore indexes are not being deployed as expected, follow these troubleshooting steps to resolve the issue and ensure your app performs correctly.
+
+
+
+1. **Enable Email Sign-In**
+
+ - Open your Firebase project.
+ - Go to **Authentication** > **Sign-in method**.
+ - Enable **Email/Password** sign-in.
+
+2. **Grant Proper Permissions**
+
+ - In your Firebase project, open **Project Settings** > **Users and permissions**.
+ - Add firebase@flutterflow.io as a member.
+ - Assign the following roles:
+ - **Editor**
+ - **Cloud Functions Admin**
+ - **Service Account User**
+
+ 
+
+3. **Update Firestore Rules**
+
+ - Update your Firestore rules in both Firebase Console and FlutterFlow.
+ - Ensure they match your app’s data access requirements.
+ - Follow the detailed steps in the **[Firestore Rules documentation](/integrations/database/cloud-firestore/firestore-rules/)** to correctly configure your rules.
+
+ 
+
+4. **Verify Index Deployment**
+
+ - In the Firebase Console, go to **Firestore Database** > **Indexes**.
+ - Check that your indexes have been deployed.
+
+ :::note
+ Deployment may take a few minutes. Refresh the page if you don’t see updates immediately.
+ :::
+
+:::tip[Additional Tips]
+- Make sure you completed all the steps above before retrying deployment.
+- For advanced troubleshooting, check Firebase logs and permissions in Google Cloud Console.
+:::
+
+Following these steps should help resolve Firestore index deployment issues in FlutterFlow.
diff --git a/docs/troubleshooting/firebase/unable_to_validate_firestore_schema.md b/docs/troubleshooting/firebase/unable_to_validate_firestore_schema.md
new file mode 100644
index 00000000..d7fce64d
--- /dev/null
+++ b/docs/troubleshooting/firebase/unable_to_validate_firestore_schema.md
@@ -0,0 +1,96 @@
+---
+keywords: ['schema', 'database', 'firestore']
+slug: /troubleshooting/firebase/unable-to-validate-firestore-schema
+title: Unable to Validate Firestore Schema
+---
+
+# Unable to Validate Firestore Schema
+
+When trying to validate your Firestore Schema, you may encounter the error as seen in the image below:
+
+
+
+**Troubleshooting Steps:**
+
+1. **Verify that you have Created a Firestore database**
+
+ Ensure that you have already created a Firestore database in your Firebase project.
+
+ 
+
+2. **Check the Database Mode**
+
+ A database in Test Mode may not work properly for FlutterFlow integration.
+
+ :::note
+ After creating the database in Test Mode, there is no direct visual option to switch to Production Mode. You need to update the Firebase security rules manually. However, if you deploy the rules from FlutterFlow, this step is handled automatically.
+ :::
+
+ **Steps to Update your Database Rules**:
+
+ 1. Go to your Firebase project.
+ 2. Select **Cloud Firestore**.
+ 3. Navigate to **Rules**.
+
+ You will see something like this:
+
+ 
+
+ Update the rules as needed.
+
+ :::note
+ Ensure that you specify the correct `rules_version` and verify your configuration.
+ :::
+
+ 
+
+ 4. Click **Publish** to apply the changes.
+
+3. Assign the necessary permissions to `firebase@flutterflow.io`
+
+ You must grant the required cloud permissions to `firebase@flutterflow.io`:
+
+ - **Editor**
+ - **Cloud Functions Admin**
+ - **Service Account**
+
+ In the Firebase Console:
+
+ 1. Open your project.
+ 2. Go to **Project Settings** > **Users & Permissions**.
+ 3. Confirm that the required roles are assigned to `firebase@flutterflow.io`.
+
+ If you don't see these roles assigned, you need to complete this step:
+
+ 
+
+4. Ensure you have at least one collection created in FlutterFlow
+
+ In FlutterFlow, select the **Firestore** tab from the left menu. If no collections are listed, create at least one collection.
+
+ 
+
+5. **Confirm that your collections have documents**
+
+ Use FlutterFlow's CMS to verify that your collections contain at least one document:
+
+ - Select **Manage Content**.
+ - Check each collection to confirm that data exists.
+
+ If no documents exist, add at least one:
+
+ 
+
+ 
+
+6. **Deploy Firestore rules from FlutterFlow**
+
+ In your FlutterFlow project:
+
+ 1. Select **Firestore** > **Settings**.
+ 2. Scroll down to **Firestore Rules**.
+ 3. Select **Deploy** (or **Redeploy** if needed).
+
+ 
+
+
diff --git a/docs/troubleshooting/firebase/updating_firestore_security_rules.md b/docs/troubleshooting/firebase/updating_firestore_security_rules.md
new file mode 100644
index 00000000..a2965327
--- /dev/null
+++ b/docs/troubleshooting/firebase/updating_firestore_security_rules.md
@@ -0,0 +1,36 @@
+---
+keywords: ['rules', 'firestore', 'updating']
+slug: /troubleshooting/firebase/updating-firestore-security-rules
+title: Updating Firestore Security Rules
+---
+# Updating Firestore Security Rules
+
+Most backend issues are generated by the misconfiguration of the Firestore Security Rules. These backend issues may include Grey Screen errors, Infinite Loading screen, Firestore record creating error, Data mismatch errors, etc.
+
+To solve these issues, the Firestore rules have to be updated, for which you can follow the given series of steps:
+
+- **Update Your Firestore Rules**
+
+ From within your FlutterFlow project, select **Firestore** > **Settings** > Scroll down to **Firestore Rules** > select **Deploy**/**Redploy**.
+
+ 
+
+- **Update Firestore Indexes**
+
+ The next step is to see if the Firestore Rules and Indexes are **Out of Date** or **Not Deployed** (as shown in the image below). If yes, click on the blue **Deploy** button to push the latest rules.
+
+ 
+
+ After clicking on the **Deploy** button, a confirmation dialog would be shown, highlighting the changes in the rules that are being made from the deployment.
+
+ This compares the existing rules in Firestore and highlights what changes are being made in the Firestore rules. These changes are required when a new collection is created or is been edited or if the rules are Out of Date.
+
+ 
+
+ You can review the changes, and then you can click on the **Deploy Now** button. An orange loading indicator would be shown, which means that the rules are getting deployed (This step usually finishes within less than a minute, and the loading indicator is replaced with a Green Checkbox button).
+
+- **Validate the Firestore Schema**
+
+ After completing the steps above, validate the Firestore schema by clicking on the blue **Validate** button. This ensures that everything is configured correctly and the Firestore collection schema matches with the Collection schema configured in FlutterFlow.
+
+ 
\ No newline at end of file
diff --git a/docs/troubleshooting/google-play-store-deployment/_category_.json b/docs/troubleshooting/google-play-store-deployment/_category_.json
new file mode 100644
index 00000000..75449978
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Google Play Store Deployment"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/google-play-store-deployment/admob_ads_not_displaying_in_google_play_testing.md b/docs/troubleshooting/google-play-store-deployment/admob_ads_not_displaying_in_google_play_testing.md
new file mode 100644
index 00000000..4c387f69
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/admob_ads_not_displaying_in_google_play_testing.md
@@ -0,0 +1,70 @@
+---
+keywords: ['testing', 'configuration', 'display']
+slug: /troubleshooting/google-play-store-deployment/admob-ads-not-displaying-in-google-play-testing
+title: AdMob Ads Not Displaying in Google Play Testing
+---
+
+# AdMob Ads Not Displaying in Google Play Testing
+
+If your AdMob ads are not showing during **Open Testing** via the Google Play Store, the issue is often tied to AdMob configuration, app permissions, or settings in the Google Play Console. Follow the steps below to ensure ads display correctly.
+
+:::info[Prerequisites]
+- An active **AdMob** account is set up.
+- Your FlutterFlow project is linked to **AdMob**.
+- The app is uploaded to **Google Play Console** under an Open Testing track.
+:::
+
+- **Use Test Ads During Development**
+
+ Always use test ads during development to avoid policy violations or ad-serving issues:
+ - Refer to the **[Google AdMob Test Ads](https://developers.google.com/admob/android/test-ads)** guide for appropriate test ad unit IDs.
+ - Live ads should be used only after your app is published to production and approved.
+
+- **Verify AdMob Account Setup**
+
+ 1. Go to the **AdMob Console**.
+ 2. Confirm that your app is registered and linked to your Google Play listing.
+ 3. Ensure the app’s release status in AdMob matches its status in the **Google Play Console**.
+
+ :::note
+ If your app is listed as `not released` in AdMob, live ads may not load during testing.
+ :::
+
+- **Declare Use of Advertising ID**
+
+ Apps targeting **Android 13 (API 33)** or above must declare use of the **Advertising ID**:
+
+ 1. Open the **Google Play Console**.
+ 2. Go to **Policy > App Content**.
+ 3. Select **Advertising ID** and complete the required form.
+
+ :::warning
+ Failing to declare the Advertising ID may result in ads not showing during testing or after release.
+ :::
+
+- **Confirm Ad Unit Configuration in FlutterFlow**
+
+ 1. Open your project in **FlutterFlow**.
+ 2. Navigate to **Settings > AdMob Integration**.
+ 3. Confirm that the correct **Ad Unit IDs** are used.
+ 4. Ensure Ad widgets are connected to the appropriate ad units.
+
+- **Test in the Correct Environment**
+
+ - Use a physical device instead of an emulator when possible.
+ - Ensure the device has a strong internet connection.
+ - Avoid using VPNs or battery optimization tools that may interfere with ad delivery.
+
+- **Add app-ads.txt (Optional)**
+
+ Setting up an `app-ads.txt` file is optional but recommended for better ad quality:
+ - Follow the **[official guide](https://support.google.com/admob/answer/9363762?hl=en&ref_topic=9675856&sjid=8136071085841576181-EU)** to set it up.
+
+- **Wait for Ad Approval**
+
+ Even after the app is released:
+
+ - Live ads may take several days to appear due to the review process and inventory matching.
+ - This delay is expected.
+
+If ads still aren’t appearing, contact FlutterFlow Support at [support@flutterflow.io](mailto:support@flutterflow.io)
diff --git a/docs/troubleshooting/google-play-store-deployment/declare_advertising_id_android_13_play_console.md b/docs/troubleshooting/google-play-store-deployment/declare_advertising_id_android_13_play_console.md
new file mode 100644
index 00000000..bf7200b4
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/declare_advertising_id_android_13_play_console.md
@@ -0,0 +1,61 @@
+---
+keywords: ['api', 'android', 'error']
+slug: /troubleshooting/google-play-store-deployment/declare-advertising-id-android-13-play-console
+title: Declare Advertising ID for Android 13+ in Play Console
+---
+# Declare Advertising ID for Android 13+ in Play Console
+
+If your app targets Android 13 (API 33) or higher, Google Play requires that you declare whether your app uses the **Advertising ID**. Failing to do so will result in an upload error when submitting artifacts to the Play Console.
+
+:::info[Prerequisites]
+- Your app targets Android 13 (API 33) or above.
+- The app is being submitted via the **Google Play Console**.
+:::
+
+When uploading your app to Google Play, you may encounter this error:
+
+ ```js
+ {
+ "error": {
+ "code": 400,
+ "message": "Your app targets Android 13 (API 33) or above. You must declare the use of advertising ID in Play Console.",
+ "status": "INVALID_ARGUMENT"
+ }
+ }
+ ```
+ This error occurs when the required declaration for the Advertising ID is missing, incomplete, or inconsistent with your app configuration.
+
+ Google Play now requires developers targeting Android 13 (API 33) or above to explicitly declare if their app uses the **Advertising ID**.
+
+ You may see this error if:
+
+ - You didn't complete the advertising ID declaration in the Play Console.
+ - Your app configuration suggests ad usage but you have not declared it.
+ - Your declaration is incomplete or missing required details.
+
+Follow the steps below to fix this error:
+
+1. **Open App Content Section in Play Console:**
+
+ - Log into your **Google Play Console**.
+ - Navigate to your app's **App Content** section.
+
+ 
+
+2. **Declare Advertising ID Usage**
+
+ - If your app **does not contain ads**, select **No** under the "Advertising ID" section.
+
+ 
+
+ - If your app **contains ads**, select **Yes** and provide the necessary details about how ads are used.
+
+ This Declaration is important because Google Play uses this information to:
+
+ - Inform users about your app’s data collection practices.
+ - Ensure compliance with privacy policies.
+ - Prevent build upload failures.
+
+
+If the issue persists after following these steps, please contact FlutterFlow Support via Chat or email at [support@flutterflow.io](mailto:support@flutterflow.io).
+
diff --git a/docs/troubleshooting/google-play-store-deployment/error_running_pod_install.md b/docs/troubleshooting/google-play-store-deployment/error_running_pod_install.md
new file mode 100644
index 00000000..0a6d2749
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/error_running_pod_install.md
@@ -0,0 +1,45 @@
+---
+keywords: ['error', 'running', 'install']
+slug: /troubleshooting/google-play-store-deployment/error-running-pod-install
+title: Error Running Pod Install
+---
+
+# Error Running Pod Install
+
+This article addresses the common **Error Running Pod Install** issue, which typically occurs due to misconfiguration of Flutter or CocoaPods on macOS devices.
+
+:::info[Prerequisites]
+- Flutter is installed on your development machine.
+- You are working on a macOS device.
+- Basic familiarity with terminal commands.
+:::
+
+## Steps to Fix Error Running Pod Install:
+
+1. Verify Flutter is set up correctly by following the official guide: **[Flutter - Get Started: Install on macOS](https://docs.flutter.dev/get-started/install/macos)**.
+
+2. For troubleshooting specific to macOS, consult this guide: **[Troubleshooting Flutter on macOS](https://docs.flutter.dev/get-started/install/macos/mobile-ios#install-cocoapods)**.
+
+3. Run `flutter doctor` in the terminal to check for missing dependencies or configuration issues.
+
+4. Ensure CocoaPods is installed and up to date by running the following commands:
+
+ ```bash
+ sudo gem install cocoapods
+ pod repo update
+
+5. If the problem persists, try deleting the CocoaPods cache and reinstalling:
+
+ ```bash
+ flutter clean
+ ```
+ ```bash
+ flutter pub get
+ ```
+ ```bash
+ cd ios
+ ```
+ ```bash
+ pod install
+ ```
+ Deleting the `ios/Pods` directory and `ios/Podfile.lock` file before running `pod install` can help resolve lingering CocoaPods issues.
\ No newline at end of file
diff --git a/docs/troubleshooting/google-play-store-deployment/fix_launcher_icons_package_error.md b/docs/troubleshooting/google-play-store-deployment/fix_launcher_icons_package_error.md
new file mode 100644
index 00000000..d6fed1ff
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/fix_launcher_icons_package_error.md
@@ -0,0 +1,75 @@
+---
+keywords: ['error', 'package', 'icon']
+slug: /troubleshooting/google-play-store-deployment/fix-launcher-icons-package-error
+title: Fix Flutter Launcher Icons Package Error
+---
+
+# Fix Flutter Launcher Icons Package Error
+
+This article describes how to resolve the **[flutter_launcher_icons package](https://pub.dev/packages/flutter_launcher_icons)** error that may occur during app build or deployment.
+
+:::info[Prerequisites]
+- Access to your FlutterFlow project.
+- Ability to open and edit the `pubspec.yaml` file.
+- Familiarity with your build environment (FlutterFlow, GitHub, or IDE).
+:::
+
+**Understanding the Error:**
+
+During the build process, you might see the following error message:
+
+```text
+Codemagic Deploy Output Failed Step: Generate Launch Icon Could not find package "flutter_launcher_icons". Did you forget to add a dependency? pub finished with exit code 65. Build failed: Step 5 script 'Generate Launch Icon' exited with status code 65.
+```
+
+This error indicates that the **flutter_launcher_icons** package is missing or not configured correctly.
+
+Follow the steps below to fix the error:
+
+1. **Clear and Reset App Assets in FlutterFlow:**
+ - Navigate to **Settings and Integrations** > **App Assets** inside FlutterFlow.
+ - If the **Splash Screen** and **Launcher Icon** are set:
+ - Clear both assets.
+ - Re-upload the launcher icons.
+
+ 
+
+2. **`Add flutter_launcher_icons` Package in GitHub Deployment**
+ If you are deploying via GitHub and encounter this error, add the package to your `pubspec.yaml` file:
+
+ - Open your `pubspec.yaml` file.
+ - Add the following under `dev_dependencies`:
+
+ ```js
+ dev_dependencies:
+ flutter_launcher_icons: "^0.10.0"
+
+ flutter_icons:
+ android: true
+ ios: true
+ image_path_ios: "assets/images/launcher/ios.png"
+ image_path_android: "assets/images/launcher/android.png"
+ ```
+ - **flutter_launcher_icons*: "^0.10.0" specifies the package version.
+ - `image_path_ios` and `image_path_android` specify the paths to your launcher icon images.
+ - Ensure the image files exist at the specified paths.
+
+3. **Run the following commands in your terminal or IDE:**
+
+ ```bash
+ flutter pub get
+ ```
+ ```bash
+ flutter pub run flutter_launcher_icons:main
+ ```
+ ```bash
+ flutter run
+ ```
+ `flutter pub get` fetches packages.
+
+ `flutter pub run flutter_launcher_icons:main` generates launcher icons.
+
+ `flutter run` builds and runs the app.
+
+If the issue persists after following these steps, contact FlutterFlow Support at support@flutterflow.io.
+
diff --git a/docs/troubleshooting/google-play-store-deployment/google_play_draft_release_error.md b/docs/troubleshooting/google-play-store-deployment/google_play_draft_release_error.md
new file mode 100644
index 00000000..34385787
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/google_play_draft_release_error.md
@@ -0,0 +1,64 @@
+---
+keywords: ['deployment', 'error', 'releases']
+slug: /troubleshooting/google-play-store-deployment/google-play-draft-release-error
+title: Google Play Draft Release Error
+---
+
+# Google Play Draft Release Error
+
+When uploading an app to Google Play, you may encounter the following error:
+
+```js
+{
+ "error": {
+ "code": 400,
+ "message": "Only releases with status draft may be created on draft app.",
+ "status": "INVALID_ARGUMENT"
+ }
+}
+```
+
+This error occurs because Google Play only allows creating a Draft Release if your app is still marked as a draft in the Google Play Console. Typically, this means some required app information in the Play Console has not been completed, preventing full release submission.
+
+:::info[Prerequisites]
+- Your app is registered in the Google Play Console.
+- Basic app details such as store listing and setup information are ready to be filled.
+:::
+
+This error indicates that Google Play only allows you to create a **Draft Release** when your app is still marked as a draft in your Google Play Console. You likely have missing or incomplete app information in Google Play preventing full release submission.
+
+
+Follow these steps to fix the issue:
+
+1. Complete All Required Information in Google Play Console
+
+ - Log in to your **Google Play Console**.
+ - Complete all mandatory sections under:
+ - **App Content**
+ - **Store Listing**
+ - **Pricing & Distribution**
+ - **Target Audience & Content Rating**
+
+ Google Play requires all required information to be filled out before allowing full production releases.
+
+2. **Enable "Submit As Draft" in FlutterFlow**
+
+ After completing your app information, proceed as follows:
+
+ - **Open Settings and Integrations**: From your FlutterFlow project dashboard, navigate to **Settings > Integrations**.
+
+ 
+
+ - **Navigate to Mobile Deployment**: Select **Mobile Deployment**.
+
+ 
+
+ - **Enable Submit As Draft**: Under **Google Play Store Deployment**, toggle on **Submit as Draft**.
+
+ 
+
+ This allows you to submit your release as a draft until all Google Play requirements are fully satisfied.
+
+
+If you’ve followed all steps and still encounter the issue, contact **FlutterFlow Support** via Chat or email at [support@flutterflow.io](mailto:support@flutterflow.io) for additional assistance.
+
diff --git a/docs/troubleshooting/google-play-store-deployment/google_play_failed_to_upload_artefacts_package.md b/docs/troubleshooting/google-play-store-deployment/google_play_failed_to_upload_artefacts_package.md
new file mode 100644
index 00000000..2f885a40
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/google_play_failed_to_upload_artefacts_package.md
@@ -0,0 +1,61 @@
+---
+keywords: ['firebase', 'error', 'package']
+slug: /troubleshooting/google-play-store-deployment/google-play-failed-to-upload-artefacts-package
+title: Google Play Failed to Upload Artefacts
+---
+
+# Google Play Failed to Upload Artefacts
+
+:::info[Prerequisites]
+- Ensure your app’s `Package Name` in FlutterFlow matches the package name in Google Play Console.
+- Firebase is configured in your project settings.
+- Your Google Play Console account is active and accessible.
+:::
+
+When uploading your app to Google Play, you may encounter the following error:
+
+```js
+Google Play failed to upload artefacts. Package not found: com.flutterflow.appname.: {
+ "error": {
+ "code": 404,
+ "message": "Package not found: com.flutterflow.appname.",
+ "status": "NOT_FOUND"
+ }
+}
+```
+
+This error usually occurs in two scenarios:
+- Deploying the app to Google Play for the first time.
+- Changing the app’s `Package Name` in FlutterFlow without regenerating the Firebase configuration files.
+
+**First Time Deployment to Google Play**
+
+Follow these steps to upload your app for the first time:
+
+ 1. Generate your build in FlutterFlow and click the `AAB` button to download the build artifact.
+ 2. Log in to your **[Google Play Console](https://play.google.com/console)**.
+ 3. Navigate to your app project and upload the **AAB** file as a new release in the appropriate track (Internal, Closed, Open, or Production).
+ 4. After this initial upload, future deployments should proceed without this error.
+
+ 
+
+**Updating Package Name and Regenerating Config Files**
+
+If you have updated your app’s `Package Name` in FlutterFlow, follow these steps:
+ 1. Open your project in FlutterFlow.
+ 2. Navigate to **Settings** > **Firebase**.
+ 3. Click **Regenerate Config Files**.
+
+ 
+
+ 4. Enter the new `Package Name` and click Generate File to download the updated configuration files.
+
+ 
+
+ 5. Rebuild and redeploy your app to confirm the error is resolved.
+
+If the error persists after completing these steps:
+ - Verify the `Package Name` matches exactly between FlutterFlow and Google Play Console.
+ - Confirm that Firebase configuration files have been updated correctly.
+ - Contact FlutterFlow Support via Chat or email at support@flutterflow.io.
+
diff --git a/docs/troubleshooting/google-play-store-deployment/google_play_store_debug_signing_error.md b/docs/troubleshooting/google-play-store-deployment/google_play_store_debug_signing_error.md
new file mode 100644
index 00000000..17379f12
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/google_play_store_debug_signing_error.md
@@ -0,0 +1,36 @@
+---
+keywords: ['deployment', 'debug', 'android']
+slug: /troubleshooting/google-play-store-deployment/google-play-store-debug-signing-error
+title: Google Play Store Debug Signing Error
+---
+# Google Play Store Debug Signing Error
+
+When uploading your Android App Bundle (AAB) or APK to Google Play, you might encounter this error:
+
+```text
+You uploaded an APK or Android App Bundle that was signed in debug mode. You need to sign your APK or Android App Bundle in release mode
+```
+This error indicates the app must be signed with a release key before uploading.
+
+:::info[Prerequisites]
+- Access to the Android project files.
+- Familiarity with editing Gradle build files.
+:::
+
+**Steps to Fix Debug Signing Error:**
+ 1. Open the `android/app/build.gradle` file in your project folder.
+ 2. Locate the `buildTypes` section and find the configuration labeled `debug`.
+ 3. Replace the `debug` keyword with `release` in the relevant signing configuration.
+
+ 
+
+ 4. Save the file.
+
+ 
+
+ :::note
+ Make sure that you fill out all the information in the play store including the store listing information and the setup information.
+ :::
+
+
+
\ No newline at end of file
diff --git a/docs/troubleshooting/google-play-store-deployment/launcher_icon_missing_after_upload.md b/docs/troubleshooting/google-play-store-deployment/launcher_icon_missing_after_upload.md
new file mode 100644
index 00000000..1c3a8d1c
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/launcher_icon_missing_after_upload.md
@@ -0,0 +1,30 @@
+---
+keywords: ["icon", "added", "launcher"]
+slug: /troubleshooting/google-play-store-deployment/launcher-icon-missing-after-upload
+title: Launcher Icon Missing After Upload
+---
+
+# Launcher Icon Missing After Upload
+
+Custom app launcher icons may fail to appear after being added in the project settings due to missing icon generation steps.
+
+:::info[Prerequisites]
+- Flutter is installed on your development machine.
+- The project code has been downloaded or exported.
+- Basic familiarity with running terminal commands.
+:::
+
+**Steps to Resolve Missing Launcher Icon:**
+
+1. Run the launcher icon generation command in the terminal at your project root:
+
+ ```js
+ flutter pub run flutter_launcher_icons:main
+ ```
+ This generates the necessary launcher icon assets for your app.
+
+2. Ensure your Flutter environment is properly set up. If needed, follow the official **[Flutter installation guide](https://docs.flutter.dev/get-started/install)**.
+
+ - Verify your icon files are named correctly and placed in the appropriate directory.
+ - Check that your `pubspec.yaml` includes the correct `flutter_launcher_icons` configuration.
+ - Run `flutter clean` in your project directory before rerunning the icon generation command to clear caches.
\ No newline at end of file
diff --git a/docs/troubleshooting/google-play-store-deployment/migrate_to_play_integrity_api_from_safetynet_attestation.md b/docs/troubleshooting/google-play-store-deployment/migrate_to_play_integrity_api_from_safetynet_attestation.md
new file mode 100644
index 00000000..063003b6
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/migrate_to_play_integrity_api_from_safetynet_attestation.md
@@ -0,0 +1,36 @@
+---
+keywords: ['api', 'attestation', 'migration']
+slug: /troubleshooting/google-play-store-deployment/migrate-to-play-integrity-api-from-safetynet-attestation
+title: Migrate to Play Integrity API From SafetyNet Attestation
+---
+
+# Migrate to Play Integrity API From SafetyNet Attestation
+
+Google is deprecating the **SafetyNet Attestation API**, replacing it with the **Play Integrity API**. This article explains the migration steps needed to maintain app security and compliance with Google Play requirements.
+
+:::info[Prerequisites]
+- The **SafetyNet Attestation API** is currently used in your Android app.
+- Preparation for app deployment or maintenance on Google Play is underway.
+:::
+
+**Migration Steps:**
+
+1. **Begin the Migration Process**
+ Visit the official migration guide: **[SafetyNet Deprecation & Play Integrity Migration Guide](https://developer.android.com/google/play/integrity/migrate)**
+
+2. **Update Your Backend Implementation**
+ - Replace calls to the **SafetyNet Attestation API** with the **Play Integrity API** in your app code.
+ - Modify your backend to validate responses from the Play Integrity API.
+
+3. **Test Your Migration Thoroughly**
+ Verify that the Play Integrity API integration works correctly on multiple devices before publishing updates.
+
+:::tip
+Migrating is critical to:
+- Comply with the latest security standards.
+- Maintain access to Google's integrity services.
+- Benefit from improved error handling and security signals.
+Failure to migrate may cause degraded app functionality and user experience.
+:::
+
+If issues arise during migration, contact FlutterFlow Support at [support@flutterflow.io](mailto:support@flutterflow.io).
diff --git a/docs/troubleshooting/google-play-store-deployment/signed_in_debug_mode_error.md b/docs/troubleshooting/google-play-store-deployment/signed_in_debug_mode_error.md
new file mode 100644
index 00000000..ae16a7fd
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/signed_in_debug_mode_error.md
@@ -0,0 +1,30 @@
+---
+keywords: ['debug', 'android', 'release']
+slug: /troubleshooting/google-play-store-deployment/signed-in-debug-mode-error
+title: Signed in Debug Mode Error
+---
+
+# Signed in Debug Mode Error
+
+:::info[Prerequisites]
+- Generated an APK or Android App Bundle via **FlutterFlow → Build → Android**.
+- Access to the exported project folder.
+- Ability to edit the `android/app/build.gradle` file.
+:::
+
+When uploading an Android APK or App Bundle to the Play Store or a production environment, the following error may occur:
+
+```console
+You uploaded an APK or Android App Bundle that was signed in debug mode. You need to sign your APK or Android App Bundle in release mode
+```
+
+This error indicates that the build was signed with a debug configuration, which is only for internal testing and not valid for production release.
+
+To fix this, update the `build.gradle` file to use the release signing configuration.
+
+**Steps to Update Build Configuration:**
+1. Open the `android/app/build.gradle` file in your project folder.
+2. Locate the `debug` keyword under `buildTypes`.
+3. Replace the `debug` keyword with `release` and save the file.
+
+If the issue persists, contact FlutterFlow Support at support@flutterflow.io.
diff --git a/docs/troubleshooting/google-play-store-deployment/version_solving_failed_due_to_incompatible_package.md b/docs/troubleshooting/google-play-store-deployment/version_solving_failed_due_to_incompatible_package.md
new file mode 100644
index 00000000..e45cca85
--- /dev/null
+++ b/docs/troubleshooting/google-play-store-deployment/version_solving_failed_due_to_incompatible_package.md
@@ -0,0 +1,32 @@
+---
+keywords: ['error', 'version', 'failed']
+slug: /troubleshooting/google-play-store-deployment/version-solving-failed-due-to-incompatible-package
+title: Version Solving Failed Due to Incompatible Package
+---
+
+# Version Solving Failed Due to Incompatible Package
+
+A **version solving failed** error may occur when running `flutter pub get` if package versions in the project conflict with FlutterFlow's supported Flutter version.
+
+```js
+Running "flutter pub get" in flutter_tools... 3.4s
+Resolving dependencies...
+Because every version of flutter_test from sdk depends on collection 1.15.0
+and horse_care_new depends on collection 1.16.0,
+flutter_test from sdk is forbidden.
+So, because horse_care_new depends on flutter_test from sdk,
+version solving failed.
+pub finished with exit code 1
+```
+
+:::info[Prerequisites]
+- Custom actions or widgets are used in the project.
+- Access to the project's `pubspec.yaml` file.
+:::
+
+**Steps to Resolve the Error:**
+- Verify that all packages used in custom actions or widgets are compatible with FlutterFlow's Flutter version.
+
+- Before adding a new dependency in your custom widget or action, check if the package already exists in `pubspec.yaml`. If it does, only import the package in your code without adding it again as a dependency.
+
+- If no custom widgets or actions are used and the error persists, contact FlutterFlow Support at support@flutterflow.io for assistance.
\ No newline at end of file
diff --git a/docs/troubleshooting/index.md b/docs/troubleshooting/index.md
index 17b40ad9..53defd9c 100644
--- a/docs/troubleshooting/index.md
+++ b/docs/troubleshooting/index.md
@@ -1,17 +1,15 @@
---
slug: /troubleshooting
-title: Troubleshooting Guide
+title: Detecting Issues
description: A guide to troubleshoot or debug issues that occur within FlutterFlow project.
tags: [Troubleshooting]
sidebar_position: 0
keywords: [Troubleshooting, Debugging, Detect Issues, Runtime Errors]
---
-# Troubleshooting Guide
+# Detecting Issues
-This is a general troubleshooting guide for any issues that occur within FlutterFlow projects.
-
-## Detecting issues
+This is a general troubleshooting guide for detecting any issues that occur within FlutterFlow projects.
We've improved our issue detection capabilities and added features to provide clearer insights into what might be causing these problems. Here are some options you can use to troubleshoot the issue.
diff --git a/docs/troubleshooting/notifications/_category_.json b/docs/troubleshooting/notifications/_category_.json
new file mode 100644
index 00000000..650137e4
--- /dev/null
+++ b/docs/troubleshooting/notifications/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Notifications"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/notifications/fcm_token_generation-_roubleshooting.md b/docs/troubleshooting/notifications/fcm_token_generation-_roubleshooting.md
new file mode 100644
index 00000000..7811f58f
--- /dev/null
+++ b/docs/troubleshooting/notifications/fcm_token_generation-_roubleshooting.md
@@ -0,0 +1,99 @@
+---
+keywords: ['push notifications', 'fcm token', 'troubleshooting', 'cloud functions']
+slug: /troubleshooting/notifications/fcm-token-generation-troubleshooting
+title: FCM Token Generation Troubleshooting
+---
+
+# FCM Token Generation Troubleshooting
+
+When a user does not have an `fcm_token` sub-collection in their Firestore document, push notifications cannot be delivered to their device. This guide outlines the possible causes and solutions for resolving missing `fcm_token` sub-collections in FlutterFlow apps.
+
+**Understanding the Issue**
+
+Push notifications require a valid Firebase Cloud Messaging (FCM) token, which is generated when a user logs in or signs up on a physical device. This token is typically stored in the `fcm_token` sub-collection of the user document in Firestore. If this sub-collection is missing, the device cannot receive push notifications.
+
+Possible causes for missing tokens include:
+
+ - Failures during FCM token generation.
+ - Incomplete authentication flows.
+ - Permission issues preventing token creation.
+ - Invalid input data passed to Cloud Functions.
+
+
+Here are the steps to verify user eligibility for push notifications:
+
+ 1. Check Firestore for `fcm_token` Sub-Collection
+
+ 1. Open the **Firebase Console**.
+ 2. Navigate to **Firestore Database**.
+ 3. Locate the user document.
+ 4. Verify that the `fcm_token` sub-collection exists.
+
+ If present, the user is eligible to receive push notifications.
+
+ 
+
+
+### Troubleshooting Missing FCM Token Generation
+
+ 1. **Verify Cloud Function Execution**
+
+ The `addFcmToken` Cloud Function is responsible for generating and storing FCM tokens. If token generation fails, review its logs:
+
+ 1. Open the **Firebase Console**.
+ 2. Navigate to **Functions**.
+ 3. Locate the `addFcmToken` function.
+ 4. Open its **Logs** to review errors or warnings.
+
+ 
+
+ 2. **Resolve Permission Errors**
+
+ Proper permissions are required to allow the Cloud Function to write FCM tokens to Firestore.
+
+ **Verify Firebase Security Rules**
+
+ - Ensure your Firebase security rules permit writing to the `users` collection and its sub-collections.
+
+ **Verify FlutterFlow Service Account Permissions**
+
+ The `firebase@flutterflow.io` service account must have the following roles:
+
+ - `Editor`
+ - `Cloud Functions Admin`
+ - `Service Account User`
+
+ **How to Assign Roles**:
+
+ 1. Open the **Firebase Console**.
+ 2. Go to **Project Settings > Users & Permissions**.
+ 3. Locate the `firebase@flutterflow.io` service account.
+ 4. Assign any missing roles.
+
+ Refer to **[this guide](/integrations/firebase/connect-to-firebase#connect-an-existing-firebase-project-manually)** for full instructions.
+
+ 3. **Validate Input Data Passed to Cloud Function**
+
+ If a Cloud Function fails with status code `400`, it may be receiving invalid input data.
+
+ - Verify that your authentication flow correctly retrieves the user ID before calling the function.
+ - Ensure the user ID is not `null`, empty, or malformed.
+ - Implement conditional validation before invoking the function.
+ - Add logging to your authentication code and Cloud Functions to trace failures.
+
+ This is especially important if you are using custom authentication logic. If you are using FlutterFlow's built-in authentication, this issue is unlikely.
+
+ 4. **Check for FCM Server Errors**
+
+ Additional reasons FCM token generation may fail include:
+
+ - FCM server downtime or temporary outages.
+ - Incorrect or malformed requests sent from the Cloud Function to the FCM server.
+ - Insufficient API access permissions.
+ - Invalid or missing input data (e.g. device token).
+
+ If server issues persist, consider contacting Firebase support for assistance.
+
+By following this complete troubleshooting process, you can ensure your users successfully receive push notifications.
+
+---
diff --git a/docs/troubleshooting/notifications/firebase_push_notification_troubleshooting.md b/docs/troubleshooting/notifications/firebase_push_notification_troubleshooting.md
new file mode 100644
index 00000000..93bce0d1
--- /dev/null
+++ b/docs/troubleshooting/notifications/firebase_push_notification_troubleshooting.md
@@ -0,0 +1,114 @@
+---
+keywords: ['firebase', 'push notifications', 'troubleshooting', 'permissions']
+slug: /troubleshooting/notifications/firebase-push-notification-troubleshooting
+title: Firebase Push Notification Troubleshooting
+---
+
+# Firebase Push Notification Troubleshooting
+
+Push notifications are essential for keeping users informed through timely alerts and updates. However, several common configuration issues can prevent push notifications from working as expected in FlutterFlow projects. This guide outlines potential causes and solutions.
+
+:::info[Prerequisites]
+Before troubleshooting, ensure the following:
+
+- The FlutterFlow app is connected to Firebase.
+- The app is installed on a physical device (push notifications do not work on simulators).
+- The user is logged in to the app.
+- The app is not currently open when testing notifications.
+:::
+
+1. **Verify Firebase Blaze Plan Subscription**
+
+ - Navigate to **Firebase Console > Project Settings > Usage & Billing > Details & Settings**.
+ - Confirm that the subscription is on the **Blaze Plan**.
+ - If the current plan is **Spark**, upgrade by selecting **Modify Plan**.
+
+ 
+
+
+2. Verify Apple Push Notification (APN) Key Configuration
+
+ - **Create an APN Key:**
+
+ - Navigate to the Apple Developer Console.
+ - Go to **Certificates, Identifiers & Profiles > Keys**.
+ - Create a new key for push notifications if one does not exist.
+
+ 
+
+ Instructions for **[adding a push notification key](https://developer.apple.com/account/resources/authkeys/list)**
+
+ - **Upload the APN Key to Firebase**
+
+ - Navigate to **Firebase Console > Project Settings > Cloud Messaging > iOS section**.
+ - Upload the APNs Authentication Key.
+
+ 
+
+ Instructions for **[uploading APN key to Firebase](https://firebase.google.com/docs/cloud-messaging/ios/certs)**.
+
+
+3. **Create Push Notification Identifier for Apple**
+
+ - Go to the Apple Developer Console.
+ - Navigate to **Certificates, Identifiers & Profiles > Identifiers**.
+ - Create or verify an identifier for push notifications.
+
+ 
+
+ Instructions for **[creating a push notification identifier](https://developer.apple.com/account/resources/identifiers/list)**.
+
+
+4. **Verify Cloud Permissions for FlutterFlow Service Account**
+
+ - Go to **Firebase Console > Project Settings > Users & Permissions**.
+ - Locate the **firebase@flutterflow.io** service account.
+ - Ensure the following roles are assigned:
+
+ - Editor
+ - Cloud Functions Admin
+ - Service Account User
+
+ 
+
+ Instructions to **[add required cloud permissions](/integrations/firebase/connect-to-firebase/#allow-flutterflow-to-access-your-project)**.
+
+
+5. **Confirm Cloud Function Region Consistency**
+
+ - In **FlutterFlow > Settings > Firebase > Advanced Settings**, verify the Cloud Functions Region matches the region configured in **Firebase > Project Settings > Cloud Functions Location**.
+
+ 
+
+ 
+
+
+6. **Update FlutterFlow to Latest Version**
+
+ **Refresh FlutterFlow:**
+
+ - On Windows: Press `Ctrl + R`.
+ - On Mac: Press `Cmd + R`.
+
+ **Clear Browser Cache:** Clear the browser cache to ensure the latest version loads properly.
+
+
+7. **Resolve FlutterFlow Insufficient Permissions Error**
+
+ If an insufficient permissions error occurs:
+
+ 1. Open **Firebase Console > Project Settings > Users & Permissions**.
+ 2. Verify the **firebase@flutterflow.io** account exists.
+ 3. Assign the following permissions:
+
+ - Editor
+ - Cloud Functions Admin
+ - Service Account User
+
+ 
+
+ 4. Save changes and retry the operation in FlutterFlow.
+
+ 
+
+
diff --git a/docs/troubleshooting/notifications/firebase_push_notifications_on_web.md b/docs/troubleshooting/notifications/firebase_push_notifications_on_web.md
new file mode 100644
index 00000000..8deefb2c
--- /dev/null
+++ b/docs/troubleshooting/notifications/firebase_push_notifications_on_web.md
@@ -0,0 +1,37 @@
+---
+keywords: ['firebase', 'web push', 'notifications', 'custom actions']
+slug: /troubleshooting/notifications/firebase-push-notifications-on-web
+title: Firebase Push Notifications on Web
+---
+
+# Firebase Push Notifications on Web
+
+FlutterFlow currently does not support sending Firebase push notifications on web apps natively. However, Firebase itself supports this capability. This guide outlines alternative approaches to enable Firebase push notifications on web projects built with FlutterFlow.
+
+## Workarounds for Implementing Web Push Notifications
+
+There are two primary methods to implement Firebase web push notifications in FlutterFlow projects:
+
+- **Use Custom Actions:**
+
+ - Create custom actions in FlutterFlow that utilize Firebase Cloud Messaging (FCM) to send push notifications.
+ - This method requires writing custom code to handle notification logic and integrate it into FlutterFlow.
+ - Custom actions offer flexibility for handling different types of notifications based on the app’s needs.
+ - The Firebase Web SDK can be used alongside your FlutterFlow project to achieve this.
+
+ Refer to official Firebase documentation for detailed steps on **[setting up web push notifications](https://firebase.google.com/docs/cloud-messaging/js/client)**.
+
+
+- **Use Back-End Functions:**
+
+ - Implement server-side code using Firebase Functions or any other backend service.
+ - Backend functions handle sending notifications independently of the FlutterFlow frontend.
+ - This approach allows using the Firebase Admin SDK to programmatically send push notifications to targeted web clients.
+ - Backend solutions also offer better scalability, error handling, and control over notification delivery.
+
+:::note
+- Web push notification support requires properly configured Firebase Cloud Messaging, service workers, and valid VAPID keys.
+- FlutterFlow may add native support for web push notifications in future updates as the platform evolves.
+:::
+
+
diff --git a/docs/troubleshooting/notifications/fix-push_notifications_sent_to_zero_devices.md b/docs/troubleshooting/notifications/fix-push_notifications_sent_to_zero_devices.md
new file mode 100644
index 00000000..51237fd0
--- /dev/null
+++ b/docs/troubleshooting/notifications/fix-push_notifications_sent_to_zero_devices.md
@@ -0,0 +1,112 @@
+---
+keywords: ['push notifications', 'firebase', 'cloud functions', 'troubleshooting']
+slug: /troubleshooting/notifications/fix-push-notifications-sent-to-zero-devices
+title: Fix Push Notifications Sent to Zero Devices
+---
+
+# Fix Push Notifications Sent to Zero Devices
+
+Push notifications allow apps to send updates, alerts, and messages directly to users. In some cases, after triggering a push notification, FlutterFlow displays the following message:
+
+```js
+Push Notification sent to 0 devices
+```
+
+This means that the notification was attempted, but no eligible devices received it.
+
+Here are the causes:
+
+ - No registered devices have generated FCM tokens.
+ - Target devices were offline at the time of sending.
+ - Misconfiguration in Firebase or FlutterFlow settings.
+ - Missing permissions or API configuration.
+ - Recipient devices have blocked push notifications.
+
+The following steps below outline how to troubleshoot and resolve this issue:
+
+ 1. **Verify Firebase Functions Are Enabled**
+
+ - Ensure that Firebase Functions are enabled in the Firebase Console.
+ - Confirm that your project is on the Blaze Plan.
+
+ 
+
+
+ 2. **Delete and Redeploy Firebase Cloud Functions**
+
+ - Manually delete the Cloud Functions related to push notifications from Firebase.
+
+ 
+
+ - After deletion, redeploy Push Notifications from FlutterFlow:
+
+ 
+
+ 3. **Verify Server Region Configuration**
+
+ - Ensure that the Firebase server region matches the configuration in FlutterFlow.
+ - For example, if the server region is `us-central1`, it must match in both Firebase and FlutterFlow.
+
+ In FlutterFlow:
+ Navigate to **Settings > Firebase > Advanced Settings** and set the correct region.
+
+ 
+
+ In Firebase:
+ Verify that Cloud Functions are deployed to the same region.
+
+ 
+
+ 4. **Check FCM API Settings in Google Cloud Console**
+
+ - Open the **[Google Cloud Console](https://console.cloud.google.com/)**.
+ - Search for `FCM API` and ensure it is enabled.
+
+ 
+
+ - Make sure that a valid server key is available in Firebase Console. If missing, create one through Google Cloud Console.
+
+ 5. **Verify Cloud Permissions for flutterflow.io Service Account**
+
+ To ensure proper communication between FlutterFlow and Firebase:
+
+ - Step 1: Open Firebase Console
+
+ - Go to [Firebase Console](https://console.firebase.google.com/).
+ - Select your project.
+
+ - Step 2: Navigate to Users & Permissions
+
+ - Open **Project Settings** via the gear icon (⚙️).
+ - Select **Users & Permissions**.
+
+ 
+
+ - Step 3: Verify Existing Permissions
+
+ - Locate the `firebase@flutterflow.io` service account.
+ - Verify the following roles are assigned:
+ - `Editor`
+ - `Cloud Functions Admin`
+ - `Service Account User`
+
+ 
+
+ - Step 4: Add Missing Permissions
+
+ - If any roles are missing:
+ - Click **Add Member**.
+ - Enter `firebase@flutterflow.io`.
+ - Select missing roles from the dropdown:
+ - `Editor`
+ - `Cloud Functions Admin`
+ - `Service Account User`
+
+ 
+
+ - Step 5: Verify All Permissions Are Applied
+
+ - Confirm that all required roles now appear next to the service account.
+
+Following these steps should resolve most push notification delivery issues.
+
diff --git a/docs/troubleshooting/notifications/fix_insufficient_permissions_push-notifications.md b/docs/troubleshooting/notifications/fix_insufficient_permissions_push-notifications.md
new file mode 100644
index 00000000..bf66df8b
--- /dev/null
+++ b/docs/troubleshooting/notifications/fix_insufficient_permissions_push-notifications.md
@@ -0,0 +1,74 @@
+---
+keywords: ['permissions', 'firebase', 'push']
+slug: /troubleshooting/notifications/fix-insufficient-permissions-push-notifications
+title: Fix Insufficient Permissions for Push Notifications
+---
+
+# Fix Insufficient Permissions for Push Notifications
+
+If you encounter an **"Insufficient Permissions"** error when deploying push notifications from FlutterFlow to Firebase, it usually means the `firebase@flutterflow.io` service account does not have the necessary permissions in your Firebase project. This guide will walk you through how to resolve this issue.
+
+:::info[Prerequisites]
+Before proceeding, ensure you have:
+- Connected your Firebase project to FlutterFlow.
+- Completed the steps in **[Connect to Firebase](/integrations/firebase/connect-to-firebase/#allow-flutterflow-to-access-your-project)**.
+:::
+
+**Steps to Resolve the Insufficient Permissions Error:**
+
+ 1. **Open Firebase Console**
+
+ - Go to the **[Firebase Console](https://console.firebase.google.com/)**.
+ - Click on your project tile to open your FlutterFlow project.
+
+ 2. **Navigate to Users & Permissions:**
+
+ - In the Firebase project dashboard, click on the gear icon (⚙️) to open **Project Settings**.
+ - From the left sidebar, select **Users & Permissions**.
+
+ 
+
+ 3. **Locate the `firebase@flutterflow.io` Account**
+
+ - In the **Users** tab, search for `firebase@flutterflow.io`.
+ - If this account is missing, click **Add User**, enter `firebase@flutterflow.io` as the email address, and continue.
+
+
+ 4. **Assign the Required Permissions**
+
+ - Click on `firebase@flutterflow.io` to open the user details.
+ - Ensure the following roles are assigned:
+
+ - **Editor**
+ - **Cloud Functions Admin**
+ - **Service Account User**
+
+ 
+
+ - If any permissions are missing, click **Add Permissions** and select the missing roles.
+
+
+5. **Save Changes:**
+
+ - After assigning all necessary roles, click **Save** to apply changes.
+ - Verify that all permissions have been successfully added and saved.
+
+6. **Retry the Operation in FlutterFlow:**
+
+ - Return to your FlutterFlow project.
+ - Retry the action that previously failed due to insufficient permissions.
+
+ The error should now be resolved. If you continue to experience issues, please contact the FlutterFlow Support team.
+
+:::note
+Granting the correct permissions to `firebase@flutterflow.io` is essential for FlutterFlow to deploy push notifications and access Firebase resources correctly.
+
+
+:::
+
+
+:::info[Additional Resources]
+- [Connect FlutterFlow to Firebase](/integrations/firebase/connect-to-firebase/#allow-flutterflow-to-access-your-project)
+- [Firebase Roles and Permissions](https://firebase.google.com/docs/projects/iam/roles)
+:::
+
diff --git a/docs/troubleshooting/test-mode/_category_.json b/docs/troubleshooting/test-mode/_category_.json
new file mode 100644
index 00000000..04bd6c53
--- /dev/null
+++ b/docs/troubleshooting/test-mode/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Testing"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/test-mode/black_screen_during_run_mode.md b/docs/troubleshooting/test-mode/black_screen_during_run_mode.md
new file mode 100644
index 00000000..9f0d80fc
--- /dev/null
+++ b/docs/troubleshooting/test-mode/black_screen_during_run_mode.md
@@ -0,0 +1,42 @@
+---
+keywords: ['run-mode', 'black-screen', 'preview']
+slug: /troubleshooting/test-mode/black-screen-during-run-mode
+title: Black Screen During Run Mode
+---
+
+# Black Screen During Preview
+
+If your app screen appears blank during Run Mode, follow these steps to resolve the issue:
+
+:::info[Prerequisites]
+- You have already built and deployed at least one screen in your project.
+- You are running the app in **Run Mode** within the editor.
+:::
+
+1. **Reload the Frame**
+
+ Right-click on the preview screen and select **Reload Frame**.
+
+2. **Change the Device**
+
+ Use the device selector on the left panel to switch to a different preview device.
+
+3. **Refresh the Page**
+
+ Press `Ctrl + R` (Windows) or `Cmd + R` (Mac) to refresh the browser.
+
+4. **Update FlutterFlow and Clear Cache**
+
+ - Ensure you are using the latest version.
+ - Clear your browser cache.
+ - Log out and back in to your FlutterFlow account.
+
+5. **Submit a Bug Report**
+
+ If none of the steps work, submit a bug report using the **Send Feedback** button in FlutterFlow.
+
+ 
+
+:::tip
+Blank screens are often temporary. Try switching devices or reloading before making major changes to your project.
+:::
diff --git a/docs/troubleshooting/test-mode/firestore_permission_error-run_mode.md b/docs/troubleshooting/test-mode/firestore_permission_error-run_mode.md
new file mode 100644
index 00000000..12a000c3
--- /dev/null
+++ b/docs/troubleshooting/test-mode/firestore_permission_error-run_mode.md
@@ -0,0 +1,69 @@
+---
+keywords: ['notification', 'security', 'permissions']
+slug: /troubleshooting/test-mode/firestore-permission-error-run-mode
+title: Firestore Permission Error in Run Mode
+---
+
+# Firestore Permission Error in Run Mode
+
+When previewing your app in Run Mode, you may encounter the following error message:
+
+**Firestore Security Rules: Missing or insufficient permissions**
+
+This occurs when your Firestore rules conflict with the permissions required for a query in your app.
+
+:::info[Prerequisites]
+- You are using Firebase Firestore in your FlutterFlow project.
+- Your project has one or more Firestore queries configured.
+:::
+
+
+This error is typically triggered when:
+
+ - Firestore rules prevent any user from reading the database.
+ - A page attempts to run a query before a user is authenticated (e.g., querying user-specific data on the login page).
+
+ Example:
+
+ - If Firestore rules are configured as:
+
+ ```js
+ rules_version = '2';
+ service cloud.firestore {
+ match /databases/{database}/documents {
+ match /{document=**} {
+ allow read, write: if false;
+ }
+ }
+ }
+ ```
+
+ Any Firestore query will fail because no read or write access is allowed.
+
+ - If rules allow only authenticated access:
+
+ ```js
+ allow read, write: if request.auth != null;
+ ```
+ And a query is placed on a page before the user signs in (e.g., on the login screen), it will trigger this error.
+
+ Descriptive widget names can help you quickly identify which query or widget is triggering the permission issue. In the example above, the error message references a widget named Container. Renaming it to something like UserQueryContainer can make debugging easier.
+
+Take the steps below to fix this error:
+
+ - **Review Firestore Rules**
+
+ Go to Firestore → Settings → Rules and verify that your access rules align with how and when your app queries the database.
+
+ - **Adjust Query Placement**
+
+ Ensure that queries requiring authentication are not used on screens accessible to unauthenticated users.
+
+ - **Use Conditional Visibility**
+
+ If a query must exist on a pre-login screen, wrap it in conditional logic to only execute when the user is signed in.
+
+:::tip
+Test queries using the Run Mode Console and check the browser logs for more specific errors.
+Use Firestore Schema Validation in FlutterFlow to ensure your rules are properly deployed.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/test-mode/gray_screen_run_mode.md b/docs/troubleshooting/test-mode/gray_screen_run_mode.md
new file mode 100644
index 00000000..515ba254
--- /dev/null
+++ b/docs/troubleshooting/test-mode/gray_screen_run_mode.md
@@ -0,0 +1,103 @@
+---
+keywords: ['firebase', 'configuration', 'gray-screen']
+slug: /troubleshooting/test-mode/gray-screen-run-mode
+title: Gray Screen in Run Mode
+---
+
+# Gray Screen in Run Mode
+
+Seeing a gray screen in Run Mode usually points to a configuration issue in your Firebase or project settings. Follow these steps to diagnose and resolve the issue.
+
+:::info[Prerequisites]
+- You have integrated Firebase with your FlutterFlow project.
+- You have access to your Firebase Console.
+:::
+
+1. **Check Firebase Permissions**
+
+ Ensure that firebase@flutterflow.io has the following roles:
+
+ - **Editor**
+ - **Cloud Functions Admin**
+ - **Service Account User**
+
+ To verify:
+
+ 1. Go to the **Firebase Console**.
+ 2. Select your project → **Project Overview**.
+ 3. Navigate to **Users and permissions** → **Advanced permissions**.
+ 4. Locate firebase@flutterflow.io and ensure it has the roles listed above.
+
+ 
+
+ If missing, click the pencil icon and assign the roles.
+
+2. **Regenerate Firebase Configuration Files**
+
+ 1. In FlutterFlow, go to **Settings & Integrations** → **Firebase**.
+ 2. Click **Regenerate Config Files**.
+ 3. In the popup, click **Generate Files**.
+
+ 
+
+ :::tip
+ You must regenerate config files if you change your project name in FlutterFlow or Firebase.
+ :::
+
+3. **Update Firebase Rules**
+
+ 1. In FlutterFlow, go to **Firestore** → **Settings**.
+ 2. Scroll to **Firestore Rules** and click **Deploy**.
+ 3. Confirm by selecting **Deploy Now** in the popup.
+
+ 
+
+ A green checkmark indicates success.
+
+4. **Validate Firebase Schema**
+
+ 1. In **Firestore** → **Settings**, scroll to **Firebase Schema Validation**.
+ 2. Click **Validate**.
+
+ 
+
+ If the schema is valid, you’ll see a success message. If not, review the identified issues.
+
+ 
+
+5. **Ensure Collections Have Data**
+
+ An empty Firestore collection can result in a gray screen. Visit the Firebase Console → **Firestore Database** to confirm your collections contain documents.
+
+ 
+
+6. **Verify Custom Widget Compatibility**
+
+ If your app uses a custom widget, make sure its package supports web. On **[pub.dev](https://pub.dev)**, check that **WEB** is listed under platforms.
+
+ 
+
+ If not, choose an alternative package.
+
+7. **Refresh FlutterFlow Environment**
+
+ - Press Ctrl + R (Windows) or Cmd + R (Mac) to refresh FlutterFlow.
+ - Clear your browser cache.
+ - Log out and back in.
+
+ :::tip
+ Refreshing your session can fix slow or buggy behavior in the UI Builder.
+ :::
+
+8. **Retest the Project**
+
+ After completing the above steps, create a new Run Mode session to test if the gray screen issue is resolved.
+
+9. **Test Locally**
+
+ If the issue persists, download your FlutterFlow code and run the project locally to diagnose further.
+
+:::info[Additional Resources]
+- **[Run Flutter App Locally](/testing/local-run)**
+- **[FlutterFlow Firebase Integration Guide](/integrations/firebase/connect-to-firebase/#step-1-set-up-your-project)**
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/test-mode/loading_spinner_run_mode.md b/docs/troubleshooting/test-mode/loading_spinner_run_mode.md
new file mode 100644
index 00000000..9caa3a8d
--- /dev/null
+++ b/docs/troubleshooting/test-mode/loading_spinner_run_mode.md
@@ -0,0 +1,41 @@
+---
+keywords: ['database', 'firestore', 'loading']
+slug: /troubleshooting/test-mode/loading-spinner-run-mode
+title: Loading Spinner in Run Mode
+---
+
+# Loading Spinner in Run Mode
+
+A persistent loading spinner in FlutterFlow's Run Mode usually indicates an issue with your Firestore rules configuration. Updating your rules can resolve this issue.
+
+:::info[Prerequisites]
+- You have already connected your FlutterFlow project to Firebase.
+- You have access to your Firebase Console.
+:::
+
+Here are the steps to fix this error:
+
+1. **Copy Firestore Rules from FlutterFlow**
+
+ 1. Open your project.
+ 2. Navigate to **Firestore** → **Settings**.
+ 3. Click the **Copy** icon to copy the default Firestore rules.
+
+ 
+
+2. **Paste the Rules in Firebase Console**
+
+ 1. Open the **[Firebase Console](https://console.firebase.google.com/)**.
+ 2. Select your project and go to **Firestore Database**.
+ 3. Open the **Rules** tab.
+ 4. Paste the copied rules into the editor and click **Publish**.
+
+ 
+
+3. **Retest Your Project in FlutterFlow**
+
+ Return to FlutterFlow and run your project again in **Run Mode**. The loading spinner should no longer appear if the Firestore rules were configured correctly.
+
+:::tip
+Always keep your Firestore rules up to date after making structural changes to your database in FlutterFlow.
+:::
diff --git a/docs/troubleshooting/test-mode/local_build_providerinstaller_error.md b/docs/troubleshooting/test-mode/local_build_providerinstaller_error.md
new file mode 100644
index 00000000..4320d469
--- /dev/null
+++ b/docs/troubleshooting/test-mode/local_build_providerinstaller_error.md
@@ -0,0 +1,71 @@
+---
+keywords: ['build', 'android', 'emulator']
+slug: /troubleshooting/test-mode/local-build-providerinstaller-error
+title: Local Build ProviderInstaller Error
+---
+
+# Local Build ProviderInstaller Error
+
+This error commonly occurs when building Flutter apps on Android emulators. It is related to the `ProviderInstaller` service and can typically be resolved through basic cleanup and Flutter version upgrades.
+
+:::info[Prerequisites]
+- You are testing or running your Flutter project on an Android emulator.
+- You have Flutter and Android Studio installed and configured.
+:::
+
+1. **Uninstall the App from the Emulator**
+
+ Before rebuilding your app, ensure the old installation is removed:
+
+ 1. Open the Android Emulator.
+ 2. Locate your app icon and uninstall it.
+ 3. Alternatively, run the following command from your terminal:
+
+ ```bash
+ adb uninstall com.yourcompany.yourapp
+ ```
+
+ Replace com.yourcompany.yourapp with your actual app ID.
+
+2. **Rebuild the App**
+
+ After uninstalling:
+
+ Run the following command in your project directory:
+
+ ```bash
+ flutter clean
+ ```
+
+ ```bash
+ flutter pub get
+ ```
+
+ ```bash
+ flutter run
+ ```
+
+
+ This will remove cached data and reinstall the app on the emulator.
+
+3. **Upgrade Flutter (If Problem Persists)**
+
+ If the issue continues, upgrading Flutter may help. Run the command below to upgrade:
+ ```bash
+ flutter upgrade
+ ```
+
+ Ensure your Flutter SDK is up to date. You can verify the version with:
+
+ ```bash
+ flutter --version
+ ```
+
+ :::note
+ This error is often related to Google Play Services not being properly initialized on the emulator. If you're still encountering issues, consider creating a new emulator using a system image that includes the Play Store.
+ :::
+
+:::info[Additional Resources]
+- Read the official **[Flutter Build Documentation](https://docs.flutter.dev/testing/build-modes)**.
+- Check **[Android Emulator System Images](https://developer.android.com/studio/run/managing-avds#system-images)**.
+:::
\ No newline at end of file
diff --git a/docs/troubleshooting/test-mode/slow_test_mode_load.md b/docs/troubleshooting/test-mode/slow_test_mode_load.md
new file mode 100644
index 00000000..cb42991a
--- /dev/null
+++ b/docs/troubleshooting/test-mode/slow_test_mode_load.md
@@ -0,0 +1,50 @@
+---
+keywords: ['test mode', 'slow load', 'run mode']
+slug: /troubleshooting/test-mode/slow-test-mode-load
+title: Slow Loading in Test Mode
+---
+
+# Slow Loading in Test Mode
+
+If Test Mode takes several minutes to load or fails entirely, the issue may stem from your browser, network, or project configuration. This guide walks you through the most common causes and how to resolve them.
+
+:::info[Prerequisites]
+- You are using FlutterFlow's Test Mode feature.
+- You have already deployed or previewed a version of your app.
+:::
+
+**Steps to Resolve Slow Loading:**
+
+- **Check Your Internet Connection**
+
+ A weak or unstable connection may delay the loading of compiled apps. Make sure you have a stable network before launching Test Mode.
+
+- **Sync Your System Clock**
+
+ Ensure your device’s time and date settings are accurate. An incorrect clock can cause authentication issues and impact performance.
+
+- **Clear Browser Cache**
+
+ Browsers store temporary files that may interfere with page loading. Clearing your cache can resolve stale resource conflicts and improve speed.
+
+- **Try a Different Browser**
+
+ Some browsers may conflict with specific web assets or settings. If one browser is slow, switch to another (e.g., from Chrome to Firefox).
+
+- **Disable Browser Extensions**
+
+ Extensions like ad blockers or privacy tools can interfere with FlutterFlow’s platform. Temporarily disable them to check for improvement.
+
+:::tip[Optimize Your Project]
+Projects with many pages, assets, or custom code may take longer to compile. Follow these steps to optimize your project:
+- Remove unused images, fonts, or icons.
+- Consolidate or simplify custom code.
+- Limit the number of pages in a single testing session.
+:::
+
+:::info[Additional Resources]
+If the issue persists after following the steps above, check the
+**[official support](https://intercom.help/flutterflow/en/articles/7052737-test-mode-is-not-loading-or-is-very-slow-it-takes-a-long-time-to-load-the-app)** article.
+:::
+
+Following these steps should resolve most Test Mode performance issues and reduce load times for future previews.
\ No newline at end of file
diff --git a/docs/troubleshooting/test-mode/test_api_calls.md b/docs/troubleshooting/test-mode/test_api_calls.md
new file mode 100644
index 00000000..ac57df9c
--- /dev/null
+++ b/docs/troubleshooting/test-mode/test_api_calls.md
@@ -0,0 +1,54 @@
+---
+keywords: ['apis', 'test-api', 'api-call']
+slug: /troubleshooting/test-mode/test-api-calls
+title: Test API Calls
+---
+
+# Test API Calls
+
+Verifying an API response before integrating it into your app helps prevent runtime issues and ensures your data is structured correctly. This guide walks you through testing an API directly within FlutterFlow.
+
+:::info[Prerequisites]
+- A project is open in FlutterFlow.
+- An API key or endpoint is available if required by the API.
+:::
+
+**Steps to Test API Calls:**
+
+1. **Open the `API Calls` Panel**
+
+ From the left sidebar, go to the `API Calls` section.
+
+ 
+
+2. **Select or Create an API Call**
+
+ Choose an existing `API Call` or click `+ Add API Call` to create a new one.
+
+ 
+
+3. **Enter the API Endpoint**
+
+ Add the endpoint and necessary parameters, headers, or authentication.
+
+ 
+
+4. **Click the `Response & Test` Tab**
+
+ Navigate to the `Response & Test` tab to preview the response structure.
+
+ 
+
+5. **Run the API Test**
+
+ Click the `Test API Call` button to trigger the request. If successful, the API response displays in JSON format.
+
+ 
+
+ A valid API response displays a structured output like the example below::
+
+ 
+
+:::tip
+Use **[JSONPath](https://jsonpath.com/)** to validate and extract values from the returned JSON structure during testing.
+:::
diff --git a/docs/troubleshooting/translations/_category_.json b/docs/troubleshooting/translations/_category_.json
new file mode 100644
index 00000000..304dfd11
--- /dev/null
+++ b/docs/troubleshooting/translations/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Translations"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/translations/fix_google_translate_errors.md b/docs/troubleshooting/translations/fix_google_translate_errors.md
new file mode 100644
index 00000000..1f8105ba
--- /dev/null
+++ b/docs/troubleshooting/translations/fix_google_translate_errors.md
@@ -0,0 +1,59 @@
+---
+keywords: ['translation', 'localization', 'google']
+slug: /troubleshooting/translations/fix-google-translate-errors
+title: Fix Google Translate Errors
+---
+
+# Fix Google Translate Errors
+
+FlutterFlow integrates with Google Translate to help localize your app automatically. This guide outlines how to identify and resolve common issues with the translation integration.
+
+:::info[Prerequisites]
+- Google Translate integration must be enabled for the project.
+- At least one supported language must be added in **App Settings > Localization**.
+- Review the [Google Translate Integration](/concepts/localization/#add-multi-language-support) guide for setup instructions.
+:::
+
+## Common Translation Issues and Fixes
+
+- **Long Text Forms**
+ **Problem:** Attempting to translate long blocks of text in forms or widgets can lead to API timeouts or failures.
+ **Solution:** Remove long text elements and translate them outside of FlutterFlow using external tools like Google Translate. Once translated, manually paste the content back into your project. Ensure the input field is empty before retrying automatic translation.
+
+- **Special Characters**
+ **Problem:** Some special characters—such as emojis, accented symbols, or non-Latin characters—may not be supported by the Google Translate API and can cause translation to fail.
+ **Solution:** Review the text and replace or remove any unsupported special characters. Then attempt the translation again.
+
+- **Exceeding Language Limit**
+ **Problem:** Adding more than 10 language options in your project may result in translation failure.
+ **Solution:** Limit your project to a maximum of 10 supported languages for translation to work reliably with Google Translate.
+
+## Steps to Troubleshoot Translation Failures
+
+1. **Locate the Problem Area**
+ Identify the specific widget, page, or field where translation fails. Focusing on the problematic component will make resolution faster.
+
+2. **Use the Translate All Button**
+ In **App Settings > Localization**, click the **Translate All** button. The process will stop at the first failure, indicating the field or element causing the issue.
+
+3. **Check Chrome Developer Console**
+ Open the Chrome DevTools console and monitor for any error logs related to translation requests. This can help identify issues such as invalid characters, request failures, or unsupported content.
+
+4. **Remove and Isolate Problematic Text**
+ Temporarily delete the suspected text and retry the translation. If the translation proceeds successfully, that text is likely causing the failure. Manually translate and reinsert it.
+
+ :::note
+ Using shorter, plain-text strings without special characters improves success rates with the Google Translate API.
+ :::
+
+:::info[Additional Help]
+If the issue persists after troubleshooting, reach out to [support@flutterflow.io](mailto:support@flutterflow.io) with the following:
+
+ - Screenshot or screen recording of the failure
+ - Console error logs (if available)
+ - A description of where the failure occurs (page/widget/text field)
+
+ This will help the support team resolve the issue faster.
+:::
+
+
diff --git a/docs/troubleshooting/widget/_category_.json b/docs/troubleshooting/widget/_category_.json
new file mode 100644
index 00000000..cd298df5
--- /dev/null
+++ b/docs/troubleshooting/widget/_category_.json
@@ -0,0 +1,3 @@
+{
+ "label": "Widget"
+}
\ No newline at end of file
diff --git a/docs/troubleshooting/widget/custom_widget_errors.md b/docs/troubleshooting/widget/custom_widget_errors.md
new file mode 100644
index 00000000..7f67f8a4
--- /dev/null
+++ b/docs/troubleshooting/widget/custom_widget_errors.md
@@ -0,0 +1,90 @@
+---
+keywords: ['custom widget', 'widget errors', 'widget troubleshooting', 'flutterflow']
+slug: /troubleshooting/widget/custom-widget-errors
+title: Custom Widget Errors
+---
+
+# Custom Widget Errors
+
+This article demonstrates common errors and issues that may occur when creating a `Custom Widget` in FlutterFlow, along with steps to resolve them. In this example, an `Animated Text Widget` is used.
+
+
+
+**Project URL:** [Animated Kit Widget Project](https://app.flutterflow.io/project/animated-kit-widget-fyqw6j)
+
+**Run Mode URL:** [Animated Kit Widget Run Mode](https://app.flutterflow.io/run/QP62FwanUTRs7O3HJzdo)
+
+:::info[Prerequisites]
+- A custom widget has been added to your project.
+- Necessary packages have been added to **Custom Code > Packages**.
+:::
+
+:::tip[Best Practices Before Creating a Custom Widget]
+- Set a unique name for the custom widget in the left panel `Side Widget` field.
+- Start with the boilerplate code template provided by FlutterFlow. Copy it and modify your code from there.
+
+
+:::
+
+
+**Common Errors and Solutions:**
+
+ - **Widget Name Conflicts with Package Name**
+
+ A common issue is using a widget name that conflicts with the name of an imported package.
+
+ Avoid generic or conflicting names like `main` or `widget`. Use unique widget names that do not overlap with package names.
+
+ 
+
+ 
+
+ Avoid using generic or conflicting names like `main` or `widget`. Always use unique widget names that do not overlap with any package names.
+
+ - **Missing Package Imports in Code**
+
+ After adding an external package as a dependency, you must import it at the top of your custom widget code. Failure to do so results in errors such as:
+
+ ```js
+ The method 'AnimatedText' isn't defined...
+ ```
+
+ 
+
+ Here is how to fix this issue:
+
+ - Visit the package page on **[pub.dev](https://pub.dev/)** and locate the import line in the package details section.
+ - Copy and paste the correct import statement into your custom widget code.
+
+ 
+ 
+
+
+ - **Missing Indirect Dependencies**
+
+ Some packages may rely on additional external packages. Ensure that all required dependencies are also imported in your code.
+
+ 
+
+ In this example, the package depends on another package named `silver_tools`, which must also be imported. Always review the dependency chain for any external packages you add.
+
+ 
+
+
+ - **Widget Name Mismatch Between UI and Code**
+
+ A mismatch between the widget name in FlutterFlow and the class name in your code will cause compilation errors.
+
+ Incorrect example:
+
+ 
+
+ Corrected version with matching names:
+
+ 
+
+ Ensure that the widget name matches exactly in both places.
+
+
+By following these best practices and carefully reviewing package imports, dependencies, and widget names, most common issues with `Custom Widgets` in FlutterFlow can be avoided.
+
diff --git a/docs/troubleshooting/widget/emoji-size-on-ios-devices.md b/docs/troubleshooting/widget/emoji-size-on-ios-devices.md
new file mode 100644
index 00000000..8e047421
--- /dev/null
+++ b/docs/troubleshooting/widget/emoji-size-on-ios-devices.md
@@ -0,0 +1,38 @@
+---
+keywords: ['ios', 'emoji', 'text', 'size']
+slug: /troubleshooting/widget/emoji-size-on-ios-devices
+title: Emoji Size on iOS Devices
+---
+
+# Emoji Size on iOS Devices
+
+On iOS devices, emojis can appear oversized when rendered inside text widgets, disrupting the intended design and layout. This guide explains how to maintain consistent emoji sizing across all devices using container constraints and auto-sizing configuration.
+
+:::info[Prerequisites]
+- You are using a `Text` widget that includes emojis.
+- You are targeting iOS devices as part of your app deployment.
+:::
+
+## Steps to Maintain Consistent Emoji Size
+
+1. **Wrap the Text Widget in a Container**
+ Create a `Container` with fixed width and height (example `32x32 pixels`) to restrict the emoji size.
+
+2. **Place the Emoji Inside a Text Widget**
+ Add a `Text` widget containing the emoji and place it inside the container.
+
+3. **Set a Font Size**
+ Apply a specific font size to the `Text` widget (example, `16`, `24`, etc.).
+
+4. **Enable Auto-Size**
+ Turn on **Auto-Size** in the `Text` widget to allow responsive resizing within the fixed container.
+
+ 
+
+ This ensures that the emoji will resize according to the container's constraints and not exceed the intended bounds.
+
+ :::tip
+ Auto-Size works best when combined with fixed container dimensions. This approach prevents oversized emojis and supports responsive layouts.
+ :::
+
+
diff --git a/docs/troubleshooting/widget/infinite_scroll_pagination_in_listview.md b/docs/troubleshooting/widget/infinite_scroll_pagination_in_listview.md
new file mode 100644
index 00000000..5818fae7
--- /dev/null
+++ b/docs/troubleshooting/widget/infinite_scroll_pagination_in_listview.md
@@ -0,0 +1,51 @@
+---
+keywords: ['listview', 'infinite scroll', 'pagination']
+slug: /troubleshooting/widget/infinite-scroll-pagination-in-listview
+title: Infinite Scroll Pagination in ListView
+---
+
+# Infinite Scroll Pagination in ListView
+
+If a `ListView` with **Infinite Scroll** enabled loads all items at once instead of paginating, the issue is typically related to layout configuration. This guide outlines how to correctly structure the widget for proper pagination behavior.
+
+:::info[Prerequisites]
+- Infinite Scroll is enabled in the `ListView`.
+- The widget is placed inside a layout that allows height constraints to be respected.
+:::
+
+Follow the steps below to configure ListView for pagination:
+
+1. **Ensure ListView Has a Defined Height**
+ A `ListView` must have a height constraint to determine the viewport size and paginate correctly. Without a defined height, it will attempt to load all items.
+
+2. **Let ListView Handle Its Own Scrolling**
+ - Disable scrolling in any parent `Column` or scrollable container.
+ - Enable the **Primary** option, and wrap `ListView` in an `Expanded` widget.
+ - This allows `ListView` to control scroll behavior and calculate items to load per page.
+
+ 
+
+3. **Wrap ListView Inside a Fixed-Height Container (if nested)**
+ If `ListView` is inside a scrollable parent (like `Column` or `ListView`), wrap it in a `Container` with a defined height (e.g., `500px`). This ensures it doesn't expand indefinitely.
+
+ 
+
+4. **Avoid Missing Height Constraints**
+ Without constraints, `ListView` will not know the visible size and will load all data at once, bypassing pagination.
+
+ :::warning
+ Placing `ListView` directly inside a scrollable parent without a defined height will break Infinite Scroll behavior.
+ :::
+
+5. **Use Layout Structure That Supports Scroll Isolation**
+ Allow `ListView` to scroll independently before the parent scroll takes over. Combine this with defined height and `Expanded` usage for best results.
+
+ 
+
+:::tip
+To optimize pagination, define consistent item heights and test using varying screen sizes.
+:::
+
+:::info[Additional Resources]
+- **[ListView Scroll Example Project](https://app.flutterflow.io/project/list-view-scroll-example-wdv076)** – View a working configuration example.
+:::
diff --git a/docs/troubleshooting/widget/rive_animation_loading_errors.md b/docs/troubleshooting/widget/rive_animation_loading_errors.md
new file mode 100644
index 00000000..f04a9255
--- /dev/null
+++ b/docs/troubleshooting/widget/rive_animation_loading_errors.md
@@ -0,0 +1,33 @@
+---
+keywords: ['rive', 'animation', 'loading', 'error']
+slug: /troubleshooting/widget/rive-animation-loading-errors
+title: Rive Animation Loading Errors
+---
+
+# Rive Animation Loading Errors
+
+Rive animations may fail to render when the source file is incorrectly linked. This guide outlines how to provide a valid `.riv` file URL for successful animation loading.
+
+:::info[Prerequisites]
+- A valid Rive animation is hosted online with a `.riv` extension.
+- The animation is added to a FlutterFlow widget that supports Rive.
+:::
+
+## Steps to Fix Rive Animation Not Loading
+
+1. **Verify the Rive File URL**
+ Ensure the file URL ends with `.riv` and points directly to a hosted Rive file.
+
+ ```text
+ https://public.rive.app/community/runtime-files/1199-2317-jack-olantern.riv
+ ```
+
+ If the URL points to a webpage or lacks the `.riv` extension, the animation will not load in FlutterFlow.
+
+2. **Copy the Correct Link from Rive Community:**
+
+ - Go to the animation page on the **[Rive Community](https://rive.app/community/)**.
+ - Right-click the **Download** button.
+ - Select Copy Link Address.
+
+ The copied link must end with `.riv`. Any URL that redirects to a webpage or file viewer will fail to render.
diff --git a/docs/troubleshooting/widget/scroll_to_action_on_page_load.md b/docs/troubleshooting/widget/scroll_to_action_on_page_load.md
new file mode 100644
index 00000000..44205257
--- /dev/null
+++ b/docs/troubleshooting/widget/scroll_to_action_on_page_load.md
@@ -0,0 +1,33 @@
+---
+keywords: ['scroll to action', 'page load', 'delay', 'animation']
+slug: /troubleshooting/widget/scroll-to-action-on-page-load
+title: Scroll To Action on Page Load
+---
+
+# Scroll To Action on Page Load
+
+When a `Scroll To Action` fails to trigger during a page load, it is often because the scrollable widget has not fully rendered at the time the action executes. This guide outlines how to ensure the scroll action works reliably during page load.
+
+:::info[Prerequisites]
+- The `Scroll To Action` is configured inside an `On Page Load` action flow.
+- The target widget is inside a scrollable view such as `ListView` or `Column`.
+:::
+
+## Steps to Ensure Reliable Scroll Behavior:
+
+1. **Add a Delay Before the Scroll Action**
+ Insert a `Delay Action` before the `Scroll To Action` to allow the widget tree to complete rendering. Recommended delay duration is 500 to 700 ms.
+
+ 
+
+2. **Use Load Animations for Scrollable Widgets**
+ Applying an animation ensures the widget is fully visible before scrolling.
+ - Add a load animation (e.g., `Fade`) to the scrollable widget.
+ - Set the animation duration to approximately `1200 ms`.
+ - Add a `Delay Action` before the scroll action (e.g., `700 ms`).
+
+ 
+
+ :::tip
+ Combining a delay with animation prevents the scroll action from executing before the widget appears, creating a smoother transition.
+ :::
\ No newline at end of file
diff --git a/docs/troubleshooting/widget/store_custom_widget_output_using_app_state.md b/docs/troubleshooting/widget/store_custom_widget_output_using_app_state.md
new file mode 100644
index 00000000..f79c60e2
--- /dev/null
+++ b/docs/troubleshooting/widget/store_custom_widget_output_using_app_state.md
@@ -0,0 +1,34 @@
+---
+keywords: ['custom', 'widgets', 'app state', 'output']
+slug: /troubleshooting/widget/store-custom-widget-output-using-app-state
+title: Store Custom Widget Output Using App State
+---
+
+# Store Custom Widget Output Using App State
+
+To use the output from a custom widget elsewhere in your project, you can store its value in an app state variable. FlutterFlow does not directly support retrieving data from custom widgets, so this method provides an effective workaround.
+
+:::info[Prerequisites]
+- You have created a custom widget in your project.
+- You are familiar with the **[App State management](../../resources/data-representation/app-state)** system in FlutterFlow.
+:::
+
+## Steps to Store Output from a Custom Widget
+
+1. **Create an App State Variable**
+ Go to **App State**, then create a new app state variable that will hold the value returned by your custom widget.
+
+ 
+
+2. **Update the App State Variable from the Custom Widget**
+ In your custom widget code, use `FFAppState()` to set the value of the app state variable.
+
+ 
+
+ ```js
+ FFAppState().update(() {
+ FFAppState().localvalue = 'setvalue';
+ });
+ ```
+
+ App state variables can be accessed anywhere in your FlutterFlow project, making them useful for sharing data between custom widgets and other parts of the app.
\ No newline at end of file
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index 524c8f8a..0cf93486 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -11,6 +11,11 @@ const config: Config = {
onBrokenMarkdownLinks: 'throw',
onBrokenAnchors: 'throw',
favicon: 'logos/favicon.png',
+
+ clientModules: [
+ require.resolve('./src/js/table-helpers.js'),
+ require.resolve('./src/js/chatbot.js'),
+ ],
i18n: {
defaultLocale: 'en',
locales: ['en'],
@@ -20,13 +25,15 @@ const config: Config = {
'classic',
{
docs: {
- breadcrumbs: false,
+ breadcrumbs: true,
routeBasePath: '/',
sidebarPath: './sidebars.ts',
editUrl: 'https://github.com/FlutterFlow/flutterflow-documentation/edit/main/',
showLastUpdateAuthor: true,
showLastUpdateTime: true,
exclude: ['docs/index.md'],
+ sidebarCollapsible: true, /* Keep sidebar expanded by default */
+ sidebarCollapsed: true, /* Start with sidebar expanded */
// lastVersion: 'current',
// versions: {
// current: {
diff --git a/firebase.json b/firebase.json
index 0264603d..edfa7d38 100644
--- a/firebase.json
+++ b/firebase.json
@@ -1975,7 +1975,7 @@
},
{
"source": "/marketplace/creators-hub/submitting-an-item-for-review",
- "destination": "/marketplace/creators-hub/submit-item-for-reivew",
+ "destination": "/marketplace/creators-hub/submit-item-for-review",
"type": 301
},
{
@@ -2307,6 +2307,136 @@
"source": "/concepts/multiple-languages/language-selector",
"destination": "/concepts/localization",
"type": 301
+ },
+ {
+ "source": "/misc/enterprise-support-policy",
+ "destination": "/misc/enterprise#enterprise-support-policy",
+ "type": 301
+ },
+ {
+ "source": "/misc/flutterflow-experts",
+ "destination": "/misc/hire-flutterflow-developer",
+ "type": 301
+ },
+ {
+ "source": "/firebase-content-manager",
+ "destination": "/integrations/database/cloud-firestore/firestore-content-manager/",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/audio-player",
+ "destination": "/concepts/file-handling/displaying-media#audioplayer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/audio-recording",
+ "destination": "/concepts/file-handling/displaying-media#audio-recording",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/play-stop-sound",
+ "destination": "/concepts/file-handling/displaying-media#play-or-stop-sound",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/video-player",
+ "destination": "/concepts/file-handling/displaying-media#videoplayer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/youtube-player",
+ "destination": "/concepts/file-handling/displaying-media#youtubeplayer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/pdf-viewer",
+ "destination": "/concepts/file-handling/displaying-media#pdfviewer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/upload-data",
+ "destination": "/concepts/file-handling/uploading-files",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/upload-save-file",
+ "destination": "/concepts/file-handling/uploading-files#upload-or-save-file-action",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/upload-save-media",
+ "destination": "/concepts/file-handling/uploading-files#upload-or-save-media-action",
+ "type": 301
+ },
+ {
+ "source": "/concepts/alerts-notification/alert-dialog",
+ "destination": "/concepts/alerts/alert-dialog",
+ "type": 301
+ },
+ {
+ "source": "/concepts/alerts-notification/dismiss-custom-dialog",
+ "destination": "/concepts/alerts/dismiss-custom-dialog",
+ "type": 301
+ },
+ {
+ "source": "/concepts/alerts-notification/haptic-feedback",
+ "destination": "/concepts/alerts/haptic-feedback",
+ "type": 301
+ },
+ {
+ "source": "/concepts/alerts-notification/push-notifications",
+ "destination": "/concepts/notifications/push-notifications",
+ "type": 301
+ },
+ {
+ "source": "/concepts/alerts-notification/one-signal",
+ "destination": "/concepts/notifications/one-signal",
+ "type": 301
+ },
+ {
+ "source": "/concepts/state-management/generated-code",
+ "destination": "/generated-code/state-management",
+ "type": 301
+ },
+ {
+ "source": "/concepts/custom-code/custom-files",
+ "destination": "/concepts/custom-code/configuration-files",
+ "type": 301
+ },
+ {
+ "source": "/marketplace/creators-hub/submit-item-for-reivew",
+ "destination": "/marketplace/creators-hub/submit-item-for-review",
+ "type": 301
+ },
+ {
+ "source": "/resources/functions/utility/#code-expressions",
+ "destination": "/resources/functions/utility/#inline-function",
+ "type": 301
+ },
+ {
+ "source": "/configuring-cors-for-firebase-storage",
+ "destination": "/troubleshooting/firebase/configuring-cors-for-firebase-storage",
+ "type": 301
+ },
+ {
+ "source": "/accounts-billing/refunds",
+ "destination": "/accounts-billing/subscriptions/refunds",
+ "type": 301
+ },
+ {
+ "source": "/accounts-billing/subscriptions/subscriptions/flutterflow-teams",
+ "destination": "/accounts-billing/subscriptions/subscriptions",
+ "type": 301
+ },
+ {
+ "source": "/accounts-billing/subscriptions/more-subscription-faqs",
+ "destination": "/accounts-billing/subscriptions",
+ "type": 301
+ },
+ {
+ "source": "/resources/projects/settings/mcp-server",
+ "destination": "/",
+ "type": 301
}
]
}
diff --git a/sidebars.ts b/sidebars.ts
index 2a0d47de..25f953dc 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -16,7 +16,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Before You Begin',
- collapsed: true,
+ collapsed: false,
items: [
{
type: 'autogenerated',
@@ -27,7 +27,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'FlutterFlow Platform',
- collapsed: true,
+ collapsed: false,
items: [
{
type: 'autogenerated',
@@ -38,7 +38,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Resources',
- collapsed: true,
+ collapsed: false,
link: {
type: 'generated-index',
title: 'FlutterFlow Resources',
@@ -56,7 +56,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Building Concepts',
- collapsed: true,
+ collapsed: false,
link: {
type: 'generated-index',
title: 'Key Concepts',
@@ -74,7 +74,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Testing & Publishing',
- collapsed: true,
+ collapsed: false,
items: [
{
type: 'autogenerated',
@@ -85,7 +85,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Integrations',
- collapsed: true,
+ collapsed: false,
link: {
type: 'generated-index',
title: 'Third Party Integrations',
@@ -103,7 +103,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Generated Code',
- collapsed: true,
+ collapsed: false,
items: [
{
type: 'autogenerated',
@@ -114,7 +114,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Accounts & Billing',
- collapsed: true,
+ collapsed: false,
items: [
{
type: 'autogenerated',
@@ -125,7 +125,7 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: 'Miscellaneous',
- collapsed: true,
+ collapsed: false,
items: [
{
type: 'autogenerated',
diff --git a/src/components/Feedback/index.js b/src/components/Feedback/index.js
index 1b6fdee7..b22d8ba4 100644
--- a/src/components/Feedback/index.js
+++ b/src/components/Feedback/index.js
@@ -52,9 +52,9 @@ const Feedback = () => {
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
- color: feedback === 'thumbs_up' ? 'var(--ifm-color-primary)' : 'gray',
- backgroundColor: '#f0f0f0',
- border: '1px #f0f0f0',
+ color: feedback === 'thumbs_up' ? 'var(--ifm-color-primary)' : 'var(--ifm-text-color)',
+ backgroundColor: 'var(--ifm-background-color)',
+ border: '1px solid var(--ifm-border-color)',
borderRadius: '8px',
padding: '10px 20px',
fontSize: '16px',
@@ -71,9 +71,9 @@ const Feedback = () => {
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
- color: feedback === 'thumbs_down' ? 'var(--ifm-color-primary)' : 'gray',
- backgroundColor: '#f0f0f0',
- border: '1px #f0f0f0',
+ color: feedback === 'thumbs_down' ? 'var(--ifm-color-primary)' : 'var(--ifm-text-color)',
+ backgroundColor: 'var(--ifm-background-color)',
+ border: '1px solid var(--ifm-border-color)',
borderRadius: '8px',
padding: '10px 20px',
fontSize: '16px',
@@ -94,7 +94,9 @@ const Feedback = () => {
width: '100%',
height: '100px',
padding: '10px',
- borderColor: 'lightgray',
+ borderColor: 'var(--ifm-border-color)',
+ backgroundColor: 'var(--ifm-background-color)',
+ color: 'var(--ifm-text-color)',
borderRadius: '8px',
fontFamily: 'var(--ifm-font-family-base)',
}}
diff --git a/src/components/InfoCard/index.module.css b/src/components/InfoCard/index.module.css
index 8c870802..38c34ec4 100644
--- a/src/components/InfoCard/index.module.css
+++ b/src/components/InfoCard/index.module.css
@@ -1,57 +1,94 @@
.infoCard {
- border: var(--border);
- border-radius: 4px;
- padding: 30px;
- transition: background-color 0.3s, box-shadow 0.3s;
- box-sizing: border-box; /* Ensures padding is included in width/height */
- box-shadow: none; /* Initial shadow */
+ border: 1px solid var(--ifm-color-emphasis-100);
+ border-radius: 8px;
+ padding: 24px;
+ transition: all 0.3s ease;
+ box-sizing: border-box;
+ background: var(--custom-background-light);
+ cursor: pointer;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.largeCard {
+ grid-column: span 2; /* Makes the card span 2 columns */
}
-@media (max-width: 768px) { /* For landscape phones and smaller tablets */
+@media (max-width: 768px) {
.infoCard {
- padding: 20px; /* Smaller padding on smaller screens */
+ padding: 20px;
+ }
+
+ .largeCard {
+ grid-column: span 1; /* Reset on mobile */
}
}
.infoCard:hover {
- border: var(--selected-border); /* Keep the initial border */
- box-shadow: 0 4px 8px rgba(255, 255, 255, 0.8); /* Elevation effect for light mode */
+ border-color: var(--ifm-color-primary);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ transform: translateY(-2px);
}
@media (prefers-color-scheme: dark) {
+ .infoCard {
+ border-color: var(--card-border-light 100%);
+ }
+
.infoCard:hover {
- box-shadow: 0 4px 8px rgba(255, 255, 255, 0.2); /* Elevation effect for dark mode */
+ border-color: var(--ifm-color-primary);
+ box-shadow: 0 4px 12px rgba(255, 255, 255, 0.1);
}
}
+/* Dark mode background */
+[data-theme='dark'] .infoCard {
+ background: var(--custom-background-dark);
+}
+
.infoCardIcon {
font-size: 24px;
- margin-bottom: 10px;
+ margin-right: 12px;
+ color: var(--ifm-color-primary);
+ display: flex;
+ align-items: center;
}
.infoCardTitle {
- font-weight: bold;
- font-size: 20px;
+ font-weight: 600;
+ font-size: 18px;
+ color: var(--ifm-color-primary);
+ margin: 0;
}
.titleContainer {
display: flex;
align-items: center;
- padding-bottom: 20px;
+ margin-bottom: 16px;
}
.logo {
- height: 1.5em; /* 1em typically equals the font-size of the parent, which is the h2 in this case */
+ height: 1.5em;
padding-right: 10px;
- width: auto; /* Maintain the aspect ratio of the image */
+ width: auto;
+}
+
+.infoCardDescription {
+ color: var(--ifm-color-content);
+ font-size: 14px;
+ line-height: 1.5;
+ margin: 0;
+ flex-grow: 1;
}
.infoCardLink {
- display: flex;
- color: var(--primary-texr);
+ display: block;
+ color: inherit;
+ text-decoration: none;
}
.infoCardLink:hover {
- color: var(--primary-texr);
+ color: inherit;
text-decoration: none;
}
\ No newline at end of file
diff --git a/src/components/InfoCard/index.tsx b/src/components/InfoCard/index.tsx
index 6f286fa0..4ecbbf43 100644
--- a/src/components/InfoCard/index.tsx
+++ b/src/components/InfoCard/index.tsx
@@ -1,16 +1,24 @@
import React from 'react';
import styles from './index.module.css';
+interface InfoCardProps {
+ icon?: string;
+ title: string;
+ description: string;
+ pagePath: string;
+ isLarge?: boolean;
+}
-const InfoCard = ({ icon, title, description, pagePath })=> {
+const InfoCard = ({ icon, title, description, pagePath, isLarge = false }: InfoCardProps) => {
+ console.log('InfoCard:', title, 'isLarge =', isLarge);
+
return (
- {/* Link the card */}
-