One Codebase, Two Minds: Flutter vs React Native Prompts That Make an LLM Write Navigation, State, and Tests Without Hardcoding

Cross-platform mobile development with an LLM usually breaks at the same three places: navigation trees that drift from the spec, state management that quietly turns into a pile of globals, and tests the model writes after the fact to make the diff look tidy. The stack you pick changes the failure mode — not the ambition.

This roundup gives ready-to-paste prompts for both Flutter (Dart, widgets, Riverpod/Bloc) and React Native (TypeScript, hooks, Redux/Zustand). The rule of thumb: if your team already lives in JS/TS and needs fast integration with a web codebase, start with the React Native prompts. If you need one rendering model, predictable UI, and steady performance on weak devices, start with Flutter.

What to check first Before any prompt, paste your folder tree, package versions, and one existing screen into the chat. A model that sees your conventions stops inventing its own.

Navigation: spec first, code second

1. Flutter — route map from a user-flow table

For: converting a flow diagram into GoRouter routes with typed arguments.

You are a Flutter engineer. Here is my user flow as a table
(screen, action, next screen, required params).
Build a GoRouter config: every route has a name constant,
typed args via a class, and a redirect guard for auth.
Do not hardcode paths in widgets — only named constants.
Output: router file + a usage snippet per navigation call.

Example: a profile/:id route becomes ProfileArgs { final String id; }, and the widget reads it through state.pathParameters, never through a string concatenation inside onPressed.

2. React Native — typed navigation contract

For: React Navigation with TypeScript, where params are checked at compile time.

Using React Navigation (native stack + bottom tabs), generate
a RootStackParamList and TabParamList. Every screen component
must type its props with NativeStackScreenProps.
Add a linking config for deep links. No `navigation.navigate('X')`
with untyped strings — show me the typed call for each screen.

The payoff is concrete: rename a screen in the param list and TypeScript flags every broken call before the app runs. In Flutter, the equivalent safety comes from named constants plus typed args — a different mechanism, same goal.

Key distinction Flutter navigation is configuration-centric (one route tree); React Native navigation is component-centric (screens register themselves). Ask the model for the artifact that matches your stack, or it will blend the two and produce nonsense.

State management that survives a refactor

3. Flutter — Riverpod notifier from a state description

For: turning a screen's states into a sealed class and a Notifier.

Screen: order list. States: loading, empty, error(message),
data(items, isRefreshing). Use Riverpod NotifierProvider.
Rules: no BuildContext inside the notifier, side effects only
in methods, copyWith for refresh. Give me the state class,
the notifier, and the widget's switch expression.

A common failure: the model puts ScaffoldMessenger calls inside the notifier. State classes must stay UI-free — catch this in review.

4. React Native — Zustand store with selectors

For: a store that does not re-render the whole tree on every keystroke.

Create a Zustand store for cart state: items, add, remove,
total (derived). Components must subscribe via selectors,
not the whole store. Show a component that re-renders only
when its own item changes. Explain why the selector matters.

The explanation matters: it is the model's chance to state that returning a new object from a selector defeats shallow comparison — a bug that looks like a performance mystery later.

5. Flutter — Bloc event/state matrix

For: teams on Bloc who want the event surface enumerated before code.

List every user action on the checkout screen as events,
map each to states, and mark which transitions are illegal.
Then generate the Bloc with on<Event> handlers.
Illegal transitions must be ignored, not thrown.

6. React Native — Redux Toolkit slice with typed hooks

For: migrating ad-hoc useState logic into a slice without breaking consumers.

Convert this component's local state into a Redux Toolkit slice.
Keep the public props identical. Provide typed useAppDispatch
and useAppSelector hooks. Show a before/after diff of one call site.

API, errors, and the boring parts

7. Flutter — repository with typed failures

Wrap this REST endpoint in a repository returning
Either<Failure, T>. Failures: network, timeout, unauthorized,
server(code). Use Dio. No exceptions escaping to the UI layer.
Show the widget handling each Failure branch.

8. React Native — fetch layer with AbortController

Write a typed API client using fetch + AbortController.
Cancellation on unmount, timeout after N ms, error normalized
to {kind, message}. Show a hook useOrders() using it.

Both prompts share a principle worth stating to the model explicitly: errors are data, not control flow. It is the single instruction that most improves generated mobile code.

Animations and weak devices

9. Flutter — implicit vs explicit animation choice

I need a card that expands on tap. Compare AnimatedContainer
and an AnimationController for this case, pick one, justify
by rebuild cost, and write the code. Target: 60 fps on a
low-end Android device.

10. React Native — Reanimated worklet, not JS thread

Implement a swipe-to-delete row with react-native-reanimated.
The gesture must run on the UI thread. Show the worklet,
the useAnimatedStyle, and the cleanup. Explain what would
break if this ran on the JS thread.
Where people go wrong Asking for "a smooth animation" gets you a pretty demo. Asking for the thread it runs on gets you code that survives a mid-range phone.

Tests the model will not fake

11. Flutter — widget test from acceptance criteria

Here are 4 acceptance criteria for the login screen.
Write widget tests, one per criterion, using pumpWidget
and find.byKey. Mock the repository with mocktail.
No golden tests. Each test name must quote its criterion.

12. React Native — Testing Library with mocked network

Write tests with @testing-library/react-native for the
order list: loading, empty, error, data. Mock the API client,
not fetch. Assert on visible text, not test IDs, except for
list items. Use waitFor for async states.

13. Both — a test plan before any code

Before writing code, produce a test plan table:
case, input, expected state, expected UI. Flag cases that
need a fake clock or a fake network. Wait for my approval.

This is the highest-leverage prompt in the list. A model that plans tests first stops producing untestable widgets.

Choosing your stack by prompt fit

Signal Flutter prompts React Native prompts
Team background Dart or none Strong JS/TS
Web code reuse Low High
UI predictability Single render model Depends on native views
Weak-device performance Steady, compiled Needs care with the JS thread
Navigation style Central route tree Screens self-register
Non-obvious insight The model mirrors your prompt's vocabulary. Say "widget" and it writes Flutter; say "component" and it writes React. Mix the words and you get a hybrid that compiles on neither platform.

For adjacent workflows, see Twelve Prompts That Turn an LLM Into a Web Dev Lead and The LLM Detective: DevTools Prompts.

What to do next

Pick three prompts from the stack your team actually uses — one navigation, one state, one test plan — and run them on a real screen this week. Compare the diff against what a colleague would have written. The gap you find is your personal prompt backlog.

Keep a shared file of prompts that worked, with the failure modes they prevented. That file becomes more valuable than any framework comparison, because it encodes your team's conventions — the one thing a model cannot guess.

← All posts

Ask AI about this article

Ask a question about this article — ASI Biont will answer based on its text.