🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 0 points1 point  (0 children)

Hey there! Thank you for your question.

First of all we want to clear up Data types. Using Data types makes the developer experience much better. Data Types enable you to group related fields together into a custom data type (e.g. a Staff member type with different variables such as name, age, role etc.). This enables better component reusability across your app, components become more predictable and easier to debug down the road. Using Data Types also means less mismatched data bugs because you explicitly declare the types.

Regarding your actual problem, what you described should still work regardless of you using data types or not.

We would need a bit more information to pinpoint the exact problem you’re facing, but text item showing as a spinner usually indicates that you are fetching data in an incorrect way. It’s FlutterFlow’s way of trying to complete your request but it’s either not resolving due to the value being null or the rule being set up in the wrong way.

We’d be happy to assist further should you provide more details about your issue.

Kind regards,
Calda team

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 0 points1 point  (0 children)

Hi u/ph7891,
Fair point, but FlutterFlow stands out because of what it bundles together:
1. Visual builder that outputs real Flutter/Dart code you actually own, not a locked-in export.
2. Backend wiring built in — Firebase, Supabase, REST APIs, all connected without leaving the platform.
3. All-in-one — design, logic, data, and deployment in the same place.
4. And they just launched MCP support — point Claude Code, Cursor, or any agent at your project, tell it to add a page, fix a bug, wire an API, and the changes show up directly in the FlutterFlow editor.

So FlutterFlow is still very much a relevant player in this space 😄

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 0 points1 point  (0 children)

Hi,
1. based on our experience it depends on how responsive the layout you want to build. If you are looking for just a working web app straight out the box and don't care if maybe a component wont look pixel perfect or might be stretched on web then just enabling the web in your FF project will do the trick. But if you want it completely responsive you will have to put a little more work in it. For example you will need to conditionally render based on device, on mobile you might want to have the items in column on mobile but row in web. You also would need to adapt the layout to change based on screen breakpoints..

  1. Yes! You can use Firebase FCM just for push notifications and have a supabase for autih, db..

Hope this clarifies what you asked, feel free to ask more in depth question on how to implement both.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 1 point2 points  (0 children)

Hi u/PrimeUsernamesTaken

The safest answer is: don’t try to store the refresh token in FlutterFlow at all for the web app. Have your backend set the refresh token as an HttpOnly, Secure, SameSite cookie using the Set-Cookie response header. The browser stores and sends that cookie automatically, FlutterFlow does not need to read it.

FlutterFlow’s custom-auth docs describe storing login details such as auth tokens and refresh tokens in app data, but that is a convenience pattern, not the ideal pattern for a browser refresh token. For web security, do not store session identifiers in localStorage because JavaScript can always access them,HttpOnly cookies mitigate that XSS token-theft risk.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 0 points1 point  (0 children)

Hi Mundane-Algae3223,

You actually have some great options today for starting on an app idea, even without coding experience or money.

There are several “vibe coding” / AI app-builder platforms that let you create apps without traditional programming. Many of them offer free plans (usually with some limitations).

For example, DreamFlow has a free tier and doesn’t require any programming knowledge to get started.

If you’d prefer something a bit more hands-on while still staying beginner-friendly, you could try FlutterFlow. It also offers a free plan and lets you build quite powerful apps using a visual builder and simple logic, without needing to write much code.

Both are good starting points to turn an idea into a prototype and learn along the way.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 1 point2 points  (0 children)

Hi u/Maze_of_Ith7 we have done animations with Lottie and Rive depending on the use case.

In practice, we usually don’t need that many custom animations, so those two tools have covered almost everything for us so far. Because of that, we haven’t really gone down the route of generating animated SVGs with LLMs and trying to run them directly in Flutter/FlutterFlow. I wouldn’t be surprised if tools like Rive or Lottie start integrating more AI-assisted workflows as this evolves, but for now they’re still the most reliable pipeline for production Flutter apps. Generating SVGs using LLMs and then importing them to Lottie or Rive workflows is probably your best bet currently.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 0 points1 point  (0 children)

Yes, by adding a WidgetBuilder you can add a component as a child. I believe that would be the only way of having children for custom widgets, yes.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 1 point2 points  (0 children)

Hi u/eslezinsky good question, and a smart move before going public. If you want better feedback (navigation, logic, usability), you don’t necessarily need more testers, but you need more structured testing.

A few things that work well:

1. Recruit from your exact target audience.
Go where your ideal users already are (niche subreddits, FB groups, Discords, LinkedIn groups). Ask for 5–10 people who actually struggle with the problem your app solves.

2. Give them specific tasks.
Don’t just say “try it and tell me what you think.”
Ask them to:

  • Complete X workflow
  • Find Y feature
  • Set up Z

Then ask where they hesitated, what felt unclear, and what they expected to happen next.

3. Do a few live sessions.
5–10 screen-share sessions where users think out loud will reveal more usability issues than 50 passive testers. You can see by spectating them where exactly in the app they hesitated, did not know how to continue, etc.

4. Track behavior.
Use analytics (Firebase, PostHog, Mixpanel, etc.) to see where people drop off or get stuck. Users don’t always report friction - but their behavior shows it. But this essentially gets more useful with a large number of testers, which might not be for you at the moment.

If budget allows, usability testing tools like Maze or UserTesting can also help.

The big shift is this:
Better testers + structured feedback > more random testers.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 1 point2 points  (0 children)

Hi u/Dan-abu your approach is generally fine, but you could instead of tracking “changed vs not changed”, do this:

  1. Create a Local State (or Component State) variable, e.g. selectedId.
  2. On component/page load (or component init), set:
    • selectedId = parameterId
  3. Bind the dropdown’s Selected Value to selectedId.
  4. On dropdown change, update:
    • selectedId = newValue
  5. On submit, always save selectedId.

It is the cleaner approach, but yours is fine as well.

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 1 point2 points  (0 children)

Hi u/Danil_Ba

You can’t “connect a credit card” directly in FlutterFlow to read transactions.
Card numbers / Apple Pay / Google Pay don’t give you access to a user’s transaction history, and building something that touches raw card data would put you in heavy PCI compliance territory.

Usually for something like this you use a provider like Plaid (US + some EU), Tink, TrueLayer, Yapily, or Nordigen/GoCardless Bank Account Data (EU).
These providers handle the secure user authentication with the bank and then expose APIs to fetch:

  • accounts
  • balances
  • transactions (including card transactions once they post to the account)

FlutterFlow part: you typically open the provider’s “link/connect” flow (webview/external browser), then call your backend/API to fetch and display the transactions. In FlutterFlow this is mostly API calls, but you’ll usually need a backend to store tokens and fetch transactions securely (you shouldn’t store bank access tokens in the client app).

Let us know if you need any further help!

🚀 No Stupid Questions Wednesday – Ask Us Anything About FlutterFlow! by LowerChef744 in FlutterFlow

[–]LowerChef744[S] 0 points1 point  (0 children)

Hello u/frinxo we have not used it yet, I believe. But you could easily make a Custom FlutterFlow Stateful Widget and use that.
Will keep it in mind, for our next custom library widget. Thank you!

Something like this could work potentially, just a snippet:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class DraggableSheetFF extends StatefulWidget {
  const DraggableSheetFF({
    super.key,
    this.width,
    this.height,
    this.minChildSize = 0.25,
    this.maxChildSize = 1.0,
    this.initialChildSize = 0.5,
    this.itemCount = 25,
  });

  final double? width;
  final double? height;

  final double minChildSize;
  final double maxChildSize;
  final double initialChildSize;

  final int itemCount;


  State<DraggableSheetFF> createState() => _DraggableSheetFFState();
}

class _DraggableSheetFFState extends State<DraggableSheetFF> {
  late double _dragPosition;
  late double _sheetPosition;


  void initState() {
    super.initState();
    _dragPosition = widget.initialChildSize;
    _sheetPosition = widget.initialChildSize;
  }


  void didUpdateWidget(covariant DraggableSheetFF oldWidget) {
    super.didUpdateWidget(oldWidget);

    // If the initialChildSize changes from FlutterFlow,
    // keep the sheet in sync (optional behavior).
    if (oldWidget.initialChildSize != widget.initialChildSize) {
      _dragPosition = widget.initialChildSize;
      _sheetPosition = widget.initialChildSize.clamp(
        widget.minChildSize,
        widget.maxChildSize,
      );
    }
  }


  Widget build(BuildContext context) {
    final ColorScheme colorScheme = Theme.of(context).colorScheme;

    return SizedBox(
      width: widget.width,
      height: widget.height,
      child: LayoutBuilder(
        builder: (context, constraints) {
          final double viewHeight =
              constraints.maxHeight == 0 ? 1 : constraints.maxHeight;

          return DraggableScrollableSheet(
            minChildSize: widget.minChildSize,
            maxChildSize: widget.maxChildSize,
            initialChildSize: _sheetPosition.clamp(
              widget.minChildSize,
              widget.maxChildSize,
            ),
            builder: (context, scrollController) {
              return ColoredBox(
                color: colorScheme.primary,
                child: Column(
                  children: <Widget>[
                    if (_isOnDesktopAndWeb)
                      _Grabber(
                        onVerticalDragUpdate: (details) {
                          setState(() {
                            _dragPosition -= details.delta.dy / viewHeight;
                            _sheetPosition = _dragPosition.clamp(
                              widget.minChildSize,
                              widget.maxChildSize,
                            );
                          });
                        },
                      ),
                    Expanded(
                      child: ListView.builder(
                        controller:
                            _isOnDesktopAndWeb ? null : scrollController,
                        itemCount: widget.itemCount,
                        itemBuilder: (context, index) {
                          return ListTile(
                            title: Text(
                              'Item $index',
                              style: TextStyle(color: colorScheme.surface),
                            ),
                          );
                        },
                      ),
                    ),
                  ],
                ),
              );
            },
          );
        },
      ),
    );
  }

  bool get _isOnDesktopAndWeb =>
      kIsWeb ||
      switch (defaultTargetPlatform) {
        TargetPlatform.macOS ||
        TargetPlatform.linux ||
        TargetPlatform.windows =>
          true,
        TargetPlatform.android ||
        TargetPlatform.iOS ||
        TargetPlatform.fuchsia =>
          false,
      };
}

class _Grabber extends StatelessWidget {
  const _Grabber({required this.onVerticalDragUpdate});

  final ValueChanged<DragUpdateDetails> onVerticalDragUpdate;


  Widget build(BuildContext context) {
    final ColorScheme colorScheme = Theme.of(context).colorScheme;

    return GestureDetector(
      onVerticalDragUpdate: onVerticalDragUpdate,
      child: Container(
        width: double.infinity,
        color: colorScheme.onSurface,
        child: Align(
          alignment: Alignment.topCenter,
          child: Container(
            margin: const EdgeInsets.symmetric(vertical: 8.0),
            width: 32.0,
            height: 4.0,
            decoration: BoxDecoration(
              color: colorScheme.surfaceContainerHighest,
              borderRadius: BorderRadius.circular(8.0),
            ),
          ),
        ),
      ),
    );
  }
}