morph — Flutter SDK
Intelligent UI SDK for Flutter
Your app has one interface. Your users are not one person.
Website · Documentation · Dashboard · Pricing
What is Morph?
Morph is an intelligent UI SDK that makes your Flutter app personal for every user — automatically.
No darkTheme to write. No AppColors to duplicate. No accessibility backlog. One widget. That's it.
MorphProvider(
licenseKey: 'morph-free-demo',
child: MyApp(),
)
Works without a license key — native detection is always free. Add a key for AI-powered adaptation. Get your key →
Also available for React. See React SDK →
Three layers of intelligence
V1 — Context Intelligence
Morph reads the room the moment your app loads.
- 🌙 Dark at night. Light in the morning.
- ♿ High contrast when the system asks.
- 🎨 Color-blind safe palette when needed.
- ⚡ Reduced motion. Bold text. Language. All detected.
Reads directly from the device OS — platformBrightness, highContrast, textScaleFactor, boldText, disableAnimations. No config needed.
System preference always wins. Time-based logic is a smart fallback — never an override.
V1 — Design Intelligence
IA reads your actual design — not just your colors.
Not a color inverter. Morph reads your ThemeData or your AppColors file — whatever you already have — and generates the opposite theme from your exact palette.
The result: a complete ColorScheme with 4 surface depth levels, WCAG AA verified on every element. It looks hand-crafted. Because the reasoning behind it was.
V2 — Behavioral Intelligence (Pro)
Your interface learns this person.
Morph observes taps, navigation patterns, session context, zoom events. All local. All private. All in Hive. Nothing leaves the device.
- After 20 interactions → zones this person always uses rise
- After 3 sessions → layout density adapts
- After 5 sessions → the interface morphs around this user's behavior
Always with their permission. Always reversible. Always with an Undo button.
Install
# pubspec.yaml
dependencies:
morphui: ^0.1.0
flutter pub add morphui
Quick start
void main() {
runApp(
MorphProvider(
licenseKey: 'morph-free-demo',
child: MyApp(),
),
);
}
Pass your existing colors
Morph works with whatever color structure you already have. No restructuring. No renaming. No extra files.
With AppColors file
MorphProvider(
licenseKey: 'morph-free-demo',
colors: MorphColors(
background: AppColors.background,
surface: AppColors.surface,
primary: AppColors.primary,
text: AppColors.text,
textSecondary: AppColors.textSecondary,
border: AppColors.border,
error: AppColors.error,
success: AppColors.success,
warning: AppColors.warning,
),
child: MyApp(),
)
With ThemeData
MorphProvider(
licenseKey: 'morph-free-demo',
baseTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF4F46E5),
),
),
child: MyApp(),
)
With both — CAS 3 (mixed)
MorphProvider(
licenseKey: 'morph-free-demo',
baseTheme: AppTheme.lightTheme,
colors: MorphColors(
success: AppColors.success,
warning: AppColors.warning,
),
child: MyApp(),
)
How adaptation works
| App theme | Time of day | System preference | Action |
|---|---|---|---|
| Light | Day | None | ✅ Stay light |
| Light | Night | None | 🌙 Generate dark |
| Dark | Day | None | ☀️ Generate light |
| Dark | Night | None | ✅ Stay dark |
| Any | Any | Dark (system) | 🌙 Always dark |
| Any | Any | Light (system) | ☀️ Always light |
Morph detects your app brightness automatically from your colors. You never declare whether your app is light or dark — Morph figures it out.
Read the state anywhere
// From any widget in the tree
final theme = context.morphTheme // ThemeMode
final plan = context.morphPlan // MorphPlan
final settings = context.morphSettings // MorphSystemSettings
// System settings
final brightness = settings.brightness // Brightness
final highContrast = settings.highContrast // bool
final textScale = settings.textScaleFactor // double
final boldText = settings.boldText // bool
final reducedMotion = settings.disableAnimations // bool
You always stay in control
safeMode — detect without touching anything
MorphProvider(
safeMode: true,
child: MyApp(),
)
Morph detects everything, applies nothing.
All values still readable via context.morphSettings.
V2 — Behavioral Intelligence (Pro)
MorphZone
ChameleonReorderableColumn(
zones: [
MorphZone(
id: 'search',
priority: 1,
child: SearchSection(),
),
MorphZone(
id: 'feed',
priority: 2,
child: FeedSection(),
),
MorphZone(
id: 'trending',
priority: 3,
child: TrendingSection(),
),
],
)
After enough sessions, Morph reorders zones based on what this user actually uses. Always with their permission. Always with an Undo button.
Navigation tracking
MaterialApp(
navigatorObservers: [
context.morphNavObserver,
],
home: const HomePage(),
)
Morph tracks navigation patterns cross-pages and suggests shortcuts automatically.
V2 — Mobile-specific features (Pro)
Interruption Recovery
User gets a call mid-session. They come back. Morph remembers.
MorphProvider(
licenseKey: 'morph-pro-xxx',
features: MorphFeatures(
interruptionRecovery: true,
),
onResumePosition: (page, depth) {
// Scroll to saved position
_scrollController.animateTo(
_scrollController.position.maxScrollExtent
* depth / 100,
duration: const Duration(milliseconds: 600),
curve: Curves.easeOutCubic,
);
},
child: MyApp(),
)
Declare the context so Morph builds the right recovery message:
// In your page
context.morphSetContext(
page: '/checkout',
context: 'checkout',
metadata: { 'total': cart.total },
)
Grip Detection
Detects left or right hand from the accelerometer. Primary actions reposition toward the thumb automatically. No permission required.
MorphProvider(
features: MorphFeatures(gripDetection: true),
child: MyApp(),
)
// In your page — primary action follows the thumb
GripAdaptiveLayout(
child: ProductContent(),
primaryAction: AddToCartButton(),
)
Battery-Aware UI
Low battery? Morph reduces animations, simplifies the interface, and on OLED screens goes darker. Your app lasts longer. Your user stays.
MorphProvider(
features: MorphFeatures(batteryAwareUI: true),
child: MyApp(),
)
// Adapt your UI per battery level
BatteryAwareWidget(
normal: FullDashboard(),
medium: SimplifiedDashboard(),
low: EssentialDashboard(),
critical: CriticalDashboard(),
)
Circadian Rhythm UI
The interface evolves with the time of day — not just dark/light.
MorphProvider(
features: MorphFeatures(circadianRhythm: true),
child: MyApp(),
)
V2 — Agency features
Fatigue Detection
Tap accuracy drops. Typing slows. Morph detects fatigue and simplifies the interface to what matters right now.
MorphProvider(
features: MorphFeatures(
fatigueCognitiveDetection: true,
),
child: MyApp(),
)
// Form adapts automatically
FatigueAdaptiveForm(
normalFields: allFormFields,
simplifiedFields: essentialFieldsOnly,
submitButton: SubmitButton(),
)
GPS Context UI
Walking → bigger text. In a vehicle → essential only. Stationary → full interface. Uses your existing GPS feed. Zero extra permissions.
MorphProvider(
features: MorphFeatures(gpsContext: true),
child: MyApp(),
)
// In your location service — pass speed to Morph
context.morphGpsAdapter.onLocationUpdate(
speedKmh: position.speed * 3.6,
accuracy: position.accuracy,
)
Enable features by plan
MorphProvider(
licenseKey: 'morph-pro-xxx',
// React preset — ecommerce
features: MorphFeatures.ecommerce(),
// React preset — fintech / field apps
features: MorphFeatures.fintech(),
// Or configure manually
features: MorphFeatures(
interruptionRecovery: true, // Pro
gripDetection: true, // Pro
batteryAwareUI: true, // Pro
circadianRhythm: true, // Pro
fatigueCognitiveDetection: false, // Agency
gpsContext: false, // Agency
),
child: MyApp(),
)
Suggestions system
Morph observes behavior locally and surfaces suggestions to the user at the right moment — never during a scroll, never during typing.
Each suggestion has two buttons:
[Not now] [Action]
- Not now → never ask again for 7 days
- Action → execute immediately with an Undo notice
- Refused 3 times → never shown again
Suggestions are generated locally — no network call needed.
Examples:
- "You always go to Search after Home. Want a shortcut?"
- "You read content carefully. Enable reading mode?"
- "Your battery is low. Switch to essential view?"
- "You often use the app at night. Enable dark mode automatically?"
Analytics — send anonymized data (Agency, opt-in)
All behavioral data stays on device by default. Enable anonymous reporting only with explicit user consent.
MorphProvider(
licenseKey: 'morph-agency-xxx',
analytics: MorphAnalyticsConfig(
enabled: true,
userConsent: _userHasConsented,
onConsentRequired: () => showConsentDialog(),
retentionDays: 30, // max 30 — enforced
),
child: MyApp(),
)
What is sent — anonymized aggregates only:
- Zone scores (0.0 to 1.0) — not individual clicks
- Confirmed navigation sequences
- Scroll behavior summary
- App hash (non-reversible)
- Month only — not exact date
Never sent: clicks, timestamps, user identity, device fingerprint, app content, location data.
Platform support
| Platform | Status |
|---|---|
| iOS 12+ | ✅ |
| Android 6+ | ✅ |
| ThemeData | ✅ |
| AppColors files | ✅ |
| Material 3 | ✅ |
| Cupertino style | ✅ |
| Provider | ✅ |
| Riverpod | ✅ |
| Bloc / Cubit | ✅ |
| GetX | ✅ |
| Flutter Web | 🔜 |
Pricing
| Free | Pro | Agency | |
|---|---|---|---|
| Price | $0 | $19/mo | $49/mo |
| API calls/day | 50 | 2,000 | Unlimited |
| License keys | 1 | 5 | Unlimited |
| Dark mode + Accessibility | ✅ | ✅ | ✅ |
| AI theme generation | ✅ | ✅ | ✅ |
| Interruption recovery (basic) | ✅ | ✅ | ✅ |
| Behavioral intelligence V2 | — | ✅ | ✅ |
| Grip detection | — | ✅ | ✅ |
| Battery-aware UI | — | ✅ | ✅ |
| Circadian rhythm | — | ✅ | ✅ |
| Fatigue detection | — | — | ✅ |
| GPS context UI | — | — | ✅ |
| Analytics dashboard | — | — | ✅ |
| AI recommendations | — | — | ✅ |
One license key works on both React and Flutter. No extra cost.
Troubleshooting
Dark theme not matching brand
Pass your AppColors via MorphColors(). Morph reads your exact palette
and generates the opposite theme from it — never a generic dark.
Theme not updating when system changes
Make sure your MaterialApp is inside MorphProvider — not the other way around.
Grip detection not working
Check that sensors_plus is in your pubspec.yaml and that
MorphFeatures(gripDetection: true) is set.
Analytics not sending
Both enabled: true AND userConsent: true are required.
One alone is not enough.
Roadmap
✅ Live now
- Automatic dark / light theme from ThemeData or AppColors
- WCAG AA — guaranteed, not hoped for
- System preferences — all of them
- AI-powered theme generation
- iOS and Android
✅ V2 — Behavioral Intelligence
- Zone tracking and reordering
- Navigation pattern detection
- Interruption Recovery
- Grip Detection
- Battery-aware UI
- Circadian Rhythm UI
- Suggestions system with permission
- Fatigue Detection (Agency)
- GPS Context UI (Agency)
- Analytics dashboard (Agency)
- AI-powered recommendations (Agency, opt-in)
🔜 V3
- Flutter Web support
- Cross-platform insights with React SDK
morphui.dev · Docs · Dashboard · pub.dev · React SDK
Every user deserves an interface made for them.
Apache License 2.0
Libraries
- morphui
- Morph for Flutter — automatic UI adaptation.