Skip to main content
Presentum - Declarative presentation engine for Flutter

Build dynamic UI at scale

Presentum is a declarative Flutter engine that helps you manage campaigns, app updates, special offers, tips, and notifications with clean, testable, type-safe code. Show the right message to the right user at the right time, with impression limits, cooldowns, A/B testing, and analytics - all handled automatically.

Declarative by design

Describe presentations as data. No imperative show/hide logic.

Type-safe

Generics ensure compile-time correctness. No runtime surprises.

Clean architecture

Business logic in guards, UI in outlets, tracking in storage.

Production ready

Eligibility rules, A/B tests, cooldowns, impression tracking built-in.

Quick example

// 1. Define surfaces
enum AppSurface with PresentumSurface {
  homeTopBanner,
  popup;
}

// 2. Create payload
class CampaignPayload extends PresentumPayload<AppSurface, CampaignVariant> {
  final String id;
  final int priority;
  final Map<String, Object?> metadata;
  final List<PresentumOption> options;
}

// 3. Initialize
final presentum = Presentum(
  storage: MyStorage(),
  guards: [CampaignGuard()],
);

// 4. Render
PresentumOutlet(
  surface: AppSurface.homeTopBanner,
  builder: (context, item) => BannerWidget(item),
)
That’s it! Presentum handles eligibility, impressions, cooldowns, and state automatically.

Get started

What you can build

Force update dialogs, optional upgrade prompts, changelog announcements using Shorebird or CodePush.

Production example

Real-world implementation from a live app:
final presentum = Presentum(
  storage: CampaignStorage(),
  eventHandlers: [
    PresentumStorageEventHandler(storage: storage),
  ],
  guards: [
    AppOpenedCountGuard(
      appOpenedCount: userRepository.fetchAppOpenedCount,
    ),
    AppLifecycleChangedGuard(
      refresh: AppLifecycleChangedRefresh(),
    ),
    SyncStateWithCandidatesGuard(),
    CampaignSchedulingGuard(eligibility),
    RemoveIneligibleCampaignsGuard(eligibility),
  ],
);
See complete implementation ->

Guides

Recipes

Powerful features

Build complex targeting rules with conditions and extractors:
AllOfEligibility(conditions: [
  TimeRangeEligibility(start: start, end: end),
  AnySegmentEligibility(requiredSegments: {"premium"}),
  NumericComparisonEligibility(
    contextKey: 'app_version',
    comparison: NumericComparison.greaterThanOrEqual,
    threshold: 2.0,
  ),
])
Learn more ->

Community

Ready to start?

Start with the quickstart guide

Build your first Presentum presentation in 5 minutes