> ## Documentation Index
> Fetch the complete documentation index at: https://docs.craveup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Flutter quickstart

> Connect a Flutter application to the Crave Storefront API with typed, capability-safe ordering.

This quickstart configures the official Dart SDK, checks whether takeout ordering is available, and
loads a published menu without a browser API key or BFF.

## 1. Install

```yaml pubspec.yaml theme={null}
dependencies:
  flutter:
    sdk: flutter
  crave_storefront_sdk: 0.2.0
```

Run `flutter pub get`.

## 2. Configure deployment values

Pass deployment-specific values with `--dart-define`:

```bash theme={null}
flutter run \
  --dart-define=CRAVEUP_API_URL=https://api.craveup.com \
  --dart-define=CRAVEUP_MERCHANT_SLUG=downtown-pizza \
  --dart-define=CRAVEUP_LOCATION_ID=loc_123
```

For sandbox testing, replace the origin and identifiers with the exact sandbox deployment values
provided for your account. Sandbox and production have separate environment variables and data;
never reuse a `StorefrontSessionStore` record or customer token across those origins.

## 3. Create the client

```dart theme={null}
import 'package:crave_storefront_sdk/crave_storefront_sdk.dart';

const apiUrl = String.fromEnvironment('CRAVEUP_API_URL');
const merchantSlug = String.fromEnvironment('CRAVEUP_MERCHANT_SLUG');
final sessionStore = InMemoryStorefrontSessionStore();

final client = CraveStorefrontClient(
  baseUri: Uri.parse(apiUrl),
  merchantSlug: merchantSlug,
  sessionStore: sessionStore,
);
```

This anonymous guest quickstart needs no customer-token provider. The in-memory store makes the
sample runnable, but it loses the cart when the process exits. Before shipping, replace it with a
`StorefrontSessionStore` backed by encrypted platform storage.

## 4. Check availability and load the menu

```dart theme={null}
const locationId = String.fromEnvironment('CRAVEUP_LOCATION_ID');

Future<MenuBundle> loadTakeoutMenu() async {
  final readiness = await client.locations.getOrderingReadiness(
    locationId,
    fulfillmentMethod: FulfillmentMethod.takeout,
  );
  if (readiness case OrderingUnavailable(:final reason)) {
    throw StateError(reason);
  }
  return client.menus.getForLocation(locationId, menuOnly: true);
}
```

`getOrderingReadiness` is anonymous and side-effect free. Starting an ordering session is the point
where the SDK receives and stores the guest cart capability and revision.

## 5. Start an order

```dart theme={null}
final result = await client.orderingSessions.start(
  locationId,
  StartOrderingSessionRequest.fresh(
    fulfillmentMethod: FulfillmentMethod.takeout.wireValue,
    channel: OrderChannel.app,
  ),
);

final cart = result.cart;
```

Keep one client per application session so its serialized cart lifecycle protects monotonic
revisions. Dispose it with `client.close()` when the application-level owner is torn down.

## 6. Surface safe failures

```dart theme={null}
try {
  await loadTakeoutMenu();
} on StorefrontApiException catch (error) {
  showApiMessage(error.code, error.requestId);
} on StorefrontTimeoutException {
  showRetryMessage();
}
```

See the [Dart and Flutter Storefront SDK guide](/getting-started/flutter-storefront-sdk) for session
storage, cancellation, conflict recovery, and security guidance.
