Using AI Prompts to Design a Screen¶
This chapter explains how to use an AI assistant to design and implement Flutter screens managed by SimpleAppState, while preserving its mental model and structural guarantees.
Rather than relying on implicit conventions, we provide the AI with a precise operational prompt that defines how state may be read, written, and updated.
This approach is especially useful when:
Prototyping complex screens
Refactoring existing widgets
Why a Dedicated AI Prompt Is Necessary¶
Generic AI instructions such as “write a Flutter screen” often lead to incorrect patterns, including:
Storing state inside widgets
Calling setState unnecessarily
Mutating values returned from
slot.get()Updating state during
build()
SimpleAppState intentionally differs from many common Flutter state-management approaches. To avoid subtle but critical mistakes, the AI must be given explicit rules describing the state semantics.
The following prompt serves as a contract between you and the AI.
Canonical AI Prompt¶
Use the following prompt verbatim when asking an AI to implement a screen using SimpleAppState.
You are an AI assistant helping to implement a Flutter screen
whose state is managed using the SimpleAppState package.
I will describe the widget structure (UI mock) in the next message.
Your task is to implement the screen logic and state interaction
correctly according to the rules below.
--------------------------------
State Access Rules
--------------------------------
- Widgets may read or write external state only through
StateSlots declared in `slots`.
- Slot values are retrieved using `slot.get()`.
- If a slot belongs to SimpleAppState,
`slot.get()` returns a deep copy of the value.
- If a slot belongs to RefAppState,
`slot.get()` returns a reference.
- Whether a slot belongs to SimpleAppState or RefAppState
is determined solely by how it was defined
(`SimpleAppState.slot(...)` or `RefAppState.slot(...)`).
You must not change or reinterpret this.
--------------------------------
State Update Rules
--------------------------------
- Slot values must be updated using `slot.set(value)`
or `slot.update((value) => newValue)`.
- For SimpleAppState:
the value passed into `update` is already a deep copy.
You must mutate this value directly and return it.
Do NOT create another copy.
- For RefAppState:
the value passed into `update` is a reference.
RefAppState is explicitly designed for in-place mutation.
Do NOT create copies here either.
- When a slot is updated, widgets subscribing to that slot
are rebuilt automatically.
Do NOT call `setState()`.
--------------------------------
Batch Updates
--------------------------------
- When updating multiple slots together,
you may use `SimpleAppState.batch(() { ... })`.
- A batch groups multiple slot updates into a single UI rebuild.
- Slot updates inside a batch are applied in declaration order.
This means that calling `get()` after `set()` inside the same
batch returns the updated value.
- Always call `batch()` on the correct appState instance
that owns the slots being updated.
--------------------------------
Custom Classes in Slots
--------------------------------
- Any custom class stored in a slot MUST extend `CloneableFile`
from the `file_state_manager` package.
- You must implement:
- `clone()` returning a deep copy of all properties
- `toDict()` returning a Map composed only of primitive values
- a `fromDict` factory constructor restoring all properties
- Overriding `==` and `hashCode` is strongly recommended.
- Classes extending CloneableFile are automatically
deep-copied recursively, even when nested inside Lists or Maps.
--------------------------------
Forbidden Actions
--------------------------------
- You must NOT call `slot.set()` or `slot.update()` during `build()`.
Doing so causes infinite rebuild loops.
- All state updates must occur in event handlers,
such as button callbacks, Futures, or other
non-build-phase logic.
How to Use This Prompt¶
Copy the prompt above.
Paste it into your AI tool.
In the next message, describe:
The widget tree (mock UI)
Which slots already exist
Which interactions should update state
Review the generated code, focusing on:
Slot usage
Absence of setState
No updates during build()
This two-step interaction produces significantly more reliable and maintainable results.
In the next message, for example, we give the AI two files:
/// Slot definition file. app_state.dart
import 'package:simple_app_state/simple_app_state.dart';
// state and slots
final appState = SimpleAppState();
final countSlot = appState.slot<int>('count', initial: 0);
final logsSlot = appState.slot<List<String>>('logs', initial: [], caster: (raw) => (raw as List).cast<String>());
/// counter_page.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:simple_app_state/simple_app_state.dart';
class CounterPage extends SlotStatefulWidget {
@override
List<StateSlot> get slots => [countSlot, logsSlot];
@override
SlotState<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends SlotState<CounterPage> {
@override
Widget build(BuildContext context) {
final count = countSlot.get();
final logs = logsSlot.get();
return CreatedNewWidget();
}
}
Then tell it to replace CreatedNewWidget() with the actual widget.
You can also ask the AI to add slots or design a data class that extends the Cloneable file. Please consider this as needed.