---
title: Getting started
description: From installation to the first nudge shown at the right moment.
---
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.page/AngeloAvv/nudge/llms.txt
> Use this file to discover all available pages before exploring further.

This guide builds a rating prompt that appears after the user completed three orders, at most once
every two weeks.

<Steps>
  <Step title="Add the dependency">
    ```yaml title="pubspec.yaml"
    dependencies:
      nudge: ^0.1.0
    ```

    Then run `flutter pub get`.
  </Step>

  <Step title="Initialize at startup">
    Initialize the package once, before `runApp`. Concurrent or repeated calls return the same
    instance.

    ```dart title="lib/main.dart"
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();

      final nudge = await Nudge.initialize();
      registerNudges(nudge);

      runApp(const MyApp());
    }
    ```

    `initialize` also starts the first session and schedules the retention policy, see
    [Storage and retention](/storage).
  </Step>

  <Step title="Log what the user does">
    Events have a name and optional metadata. Logging is synchronous and never throws.

    ```dart
    Nudge.instance.logEvent('order_completed', {
      'total': 42.5,
      'payment': 'card',
    });
    ```
  </Step>

  <Step title="Declare the nudge">
    A nudge is a condition on the history plus the policies that decide when it may fire again.

    ```dart title="lib/nudges.dart"
    void registerNudges(Nudge nudge) {
      nudge
          .define('rating_prompt')
          .when(
            nudge.when().event('order_completed').count().greaterThanOrEqual(3),
          )
          .cooldown(const Duration(days: 14))
          .maxFires(3, per: const Duration(days: 365))
          .register();
    }
    ```
  </Step>

  <Step title="Ask at a natural pause">
    Call `checkpoint()` where an interruption is acceptable — here, right after an order went
    through. It fires the eligible nudge with the highest priority, records the fire and returns
    it, or returns `null`.

    ```dart
    Future<void> onOrderCompleted(BuildContext context) async {
      final nudge = Nudge.instance;
      nudge.logEvent('order_completed', {'total': 42.5});

      final fire = nudge.checkpoint();
      if (fire?.nudgeId == 'rating_prompt') {
        await InAppReview.instance.requestReview();
        fire!.complete(NudgeOutcome.unknown);
      }
    }
    ```

    The fire is recorded as soon as `checkpoint()` returns, so the cooldown applies even if the app
    is closed while the dialog is open.
  </Step>

  <Step title="Understand what happens">
    When a nudge does not fire, ask why:

    ```dart
    print(Nudge.instance.explainNudge('rating_prompt'));
    ```

    ```text
    ✗ nudge rating_prompt
      ✓ condition
        ✓ count(order_completed) = 4 >= 3
      ✗ cooldown 14d
        ✗ NOT
          ✓ fires(nudge rating_prompt, last 14d) = 1 > 0
      ✓ max 3 fires per 365d
        ✓ fires(nudge rating_prompt, last 365d) = 1 < 3
    ```
  </Step>
</Steps>

## Next steps

- Read [Core concepts](/concepts) to understand how the pieces fit
- Browse the [Recipes](/recipes) for production-ready nudges
- See [Testing and debugging](/testing) to cover your nudges with tests
