Skip to content

polarismorph-code/morph_flutter

Repository files navigation

Morph

morph — Flutter SDK

Intelligent UI SDK for Flutter

Your app has one interface. Your users are not one person.

pub.dev license Flutter iOS Android

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.

Full V2 documentation →


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.

Charging-aware by default. When the device is plugged in, Morph keeps the UI in normal mode regardless of battery level — a phone charging at 12% behaves like one at 95%. No surprise downgrades while the user is at their desk.

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.

Robust to bad fixes. Updates with accuracy > 50m are dropped — indoor / urban-canyon noise won't flip the UI to "stationary" while the user is actually mid-trip.

Tunnel-tolerant. When the signal degrades for up to 30 seconds the adapter holds the last known context — going through a tunnel or under a bridge no longer drops the user back to "unknown".

Hysteresis on transitions. Mode changes use asymmetric thresholds (e.g. walking→cycling at 7 km/h but cycling→walking only at 5 km/h), so a steady speed at the boundary doesn't oscillate the UI.

Accelerometer-aware. When GPS reports stationary but the accelerometer shows sustained train-like vibration, the adapter upgrades to vehicle — useful in metros and trains where the GPS loses lock for minutes at a time.

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.

Get your license key →


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

About

Intelligent UI SDK for Flutter. Automatic dark mode, accessibility and behavioral adaptation. One line of code. Zero config.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages