> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/flutter/document-detector/ui-customizations.md).

# UI Customizations

Customize Document Detector for Flutter. Learn how to configure document selection, guidance screens, previews, uploads, retry states, and in-flow messages.

{% hint style="warning" %}
This guide covers **caf\_sdk 2.4.0** and above (Certta DevX). For the previous `CafSdk` sequential flow, see the [legacy documentation](https://docs.caf.io/caf-sdk/flutter/getting-started-with-the-sdk).
{% endhint %}

## Overview

Document Detector can customize interface copy, illustrations, and in-flow messages. Customization is optional; only set the fields you want to change.

There are two setups, depending on the module you enable in `caf-modules-config.json`: `documentDetector` or `documentDetectorUI`.

{% content-ref url="/pages/8imRjz3wgDSO5c2vhnO5" %}
[Installation Guide](/caf-sdk/flutter/installation-guide.md)
{% endcontent-ref %}

## Selecting documents to capture

Configure the documents users are allowed to process with `flow`. Physical documents can be captured via the camera or uploaded (if enabled). Virtual documents must be uploaded.

{% hint style="info" %}
With the UI module, users see a list of allowed documents derived from `flow`.
{% endhint %}

```dart
// Headless
final config = CerttaDocumentDetectorConfiguration(
  flow: [
    CafDocumentDetectorFlow(document: CafDocument.rgFront),
    CafDocumentDetectorFlow(document: CafDocument.rgBack),
  ],
  showPopup: true,
);

// UI module — documents still come from flow
final uiConfig = CerttaDocumentDetectorUiConfiguration(
  flow: [
    CafDocumentDetectorFlow(document: CafDocument.rgFront),
    CafDocumentDetectorFlow(document: CafDocument.rgBack),
  ],
  showPopup: true,
  documentSelectionScreen:
      const CafDocumentDetectorUIDocumentSelectionScreenConfiguration(
    title: 'Choose a document',
    description: 'Select the document you want to use',
  ),
);
```

### Guidance popup customization

A guidance popup is shown before the camera or file gallery opens. Customize it per step on `CafDocumentDetectorFlow`.

{% hint style="warning" %}
Popup customization applies to the headless `documentDetector` module. It is not available in `documentDetectorUI`.
{% endhint %}

```dart
final config = CerttaDocumentDetectorConfiguration(
  flow: [
    CafDocumentDetectorFlow(
      document: CafDocument.rgFront,
      stepLabel: 'ID Card Front',
      illustration: 'https://picsum.photos/400',
      message: 'Place the document on a table',
      okButtonTitle: 'Ok',
    ),
  ],
  showPopup: true,
);
```

{% hint style="info" %}
If `showPopup` is `true`, these details appear in a guidance popup. If uploads are enabled or `showPopup` is `false`, the popup is skipped and the details apply to the upload popup instead.
{% endhint %}

### Document selection screen

With the UI module, customize the picker title and description. The document list itself is built from `flow`.

```dart
final config = CerttaDocumentDetectorUiConfiguration(
  flow: [
    CafDocumentDetectorFlow(
      document: CafDocument.rgFront,
      stepLabel: 'ID Card Front',
      illustration: 'https://picsum.photos/400',
      message: 'Place the document on a table',
      okButtonTitle: 'Confirm',
    ),
  ],
  documentSelectionScreen:
      const CafDocumentDetectorUIDocumentSelectionScreenConfiguration(
    title: 'Choose a document',
    description: 'Select the document you want to use',
  ),
);
```

## Instructions screen customization

The UI module can show an instructions screen before the camera or file gallery. Customize capture and upload copy independently.

```dart
final config = CerttaDocumentDetectorUiConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  instructionScreen: const CafDocumentDetectorUIInstructionScreenConfiguration(
    enable: true,
    captureImage: 'https://yourdomain.com/images/capture-guide.png',
    captureTitle: 'Get Ready to Scan',
    captureSteps: [
      'Find good lighting',
      'Place document within the frame',
      'Avoid glare',
    ],
    uploadImage: 'https://yourdomain.com/images/upload-guide.png',
    uploadTitle: 'Upload Your Document',
    uploadSteps: [
      'Ensure the file is clear',
      'Must be JPG or PNG',
      'Max size 5MB',
    ],
    buttonText: "I'm Ready",
  ),
);
```

All properties are optional. If omitted, the SDK uses defaults.

| Property       | Description                                              |
| -------------- | -------------------------------------------------------- |
| `enable`       | Shows or hides the instruction screen. Default `true`.   |
| `captureImage` | URL or local asset for the camera instruction screen.    |
| `captureTitle` | Heading shown before the camera opens.                   |
| `captureSteps` | Tips for taking a good photo.                            |
| `uploadImage`  | URL or local asset for the upload instruction screen.    |
| `uploadTitle`  | Heading shown before the user picks a file.              |
| `uploadSteps`  | Tips for choosing a valid file.                          |
| `buttonText`   | Label on the button that continues to camera or gallery. |

## Photo preview

Set `showPreview: true` to let users confirm or retake the photo.

```dart
final config = CerttaDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  showPreview: true,
  previewCustomization: const CafDocumentDetectorPreviewCustomization(
    title: 'Confirm Photo Quality',
    message: 'Ensure all details are clear and there are no reflections.',
    okButton: 'Confirm',
    tryAgainButton: 'Recapture',
  ),
);
```

| Property         | Description                       |
| ---------------- | --------------------------------- |
| `title`          | Title text on the preview screen. |
| `message`        | Subtitle on the preview screen.   |
| `okButton`       | Confirmation button label.        |
| `tryAgainButton` | Retry button label.               |

## Document upload

Enable upload with `CafDocumentDetectorUploadSettings`.

{% hint style="info" %}
Unlike the UI module, using headless `documentDetector` with uploads enabled hides the camera capture option.
{% endhint %}

{% hint style="warning" %}
Upload settings apply to physical documents. Virtual documents always allow upload.
{% endhint %}

```dart
final config = CerttaDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  uploadSettings: const CafDocumentDetectorUploadSettings(
    enable: true,
    compress: true,
    fileFormats: [CafFileFormat.png, CafFileFormat.jpg],
    maxFileSize: 5,
  ),
  uploadCustomization: const CafDocumentDetectorUploadCustomization(
    image: 'https://picsum.photos/400',
    message: 'Please choose the document file you want to upload.',
    uploadButton: 'Upload file',
    cancelButton: 'Cancel',
  ),
);
```

| Property       | Description                           |
| -------------- | ------------------------------------- |
| `image`        | Image at the top of the upload popup. |
| `message`      | Message inside the upload popup.      |
| `uploadButton` | Upload button label.                  |
| `cancelButton` | Cancel button label.                  |

## Retry attempts

`maxRetryAttempts` defaults to `3`. Use `-1` for unlimited retries.

```dart
final config = CerttaDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  maxRetryAttempts: 3,
  retryCustomization: const CafDocumentDetectorRetryCustomization(
    title: 'An error happened',
    description: 'Check your internet connection and try again',
    textButton: 'Try Again',
  ),
);
```

| Property      | Description                   |
| ------------- | ----------------------------- |
| `title`       | Title on the retry screen.    |
| `description` | Subtitle on the retry screen. |
| `textButton`  | Retry button label.           |

## Feedback messages

```dart
final config = CerttaDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  messageCustomization: const CafDocumentDetectorMessageCustomization(
    waitMessage: 'Please wait...',
    fitTheDocumentMessage: 'Align your document within the frame.',
    holdItMessage: 'Hold steady...',
    verifyingQualityMessage: 'Verifying document quality...',
    lowQualityDocumentMessage: 'Document quality is too low. Please try again.',
    uploadingImageMessage: 'Uploading document...',
    positiveButtonMessage: 'Continue',
  ),
);
```

| Property                        | Description                                  |
| ------------------------------- | -------------------------------------------- |
| `waitMessage`                   | Shown when starting the camera.              |
| `fitTheDocumentMessage`         | Prompt to fit the document in the frame.     |
| `holdItMessage`                 | Shown during capture.                        |
| `verifyingQualityMessage`       | Shown during quality verification.           |
| `lowQualityDocumentMessage`     | Shown when quality is too low.               |
| `uploadingImageMessage`         | Shown while saving the image.                |
| `openDocumentWrongMessage`      | Shown if an open document is detected.       |
| `unsupportedDocumentMessage`    | Shown for unsupported documents.             |
| `documentNotFoundMessage`       | Shown when no document is detected.          |
| `sensorLuminosityMessage`       | Shown when brightness is too low.            |
| `sensorOrientationMessage`      | Shown when orientation is incorrect.         |
| `sensorStabilityMessage`        | Shown when the device is not stable.         |
| `popupDocumentSubtitleMessage`  | Subtitle in the document illustration popup. |
| `positiveButtonMessage`         | Confirmation button label.                   |
| `wrongDocumentMessage`          | Shown when the document type is incorrect.   |
| `predictorScanDocumentMessage`  | Prompt to scan a document.                   |
| `predictorGetCloserMessage`     | Prompt to get closer.                        |
| `predictorCentralizeMessage`    | Prompt to center the document.               |
| `predictorMoveAwayMessage`      | Prompt to move away.                         |
| `predictorAlignDocumentMessage` | Prompt to align the document.                |
| `predictorTurnDocumentMessage`  | Prompt to rotate the document.               |
| `predictorCapturedMessage`      | Confirmation that the document was captured. |

## Upload progress messages

```dart
final config = CerttaDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  uploadSettings: const CafDocumentDetectorUploadSettings(enable: true),
  uploadMessagesCustomization:
      const CafDocumentDetectorUploadMessagesCustomization(
    sending: 'Sending your document...',
    verifyingIntegrity: 'Checking image quality...',
    processingData: 'Extracting data...',
    almostDone: 'Wrapping things up...',
  ),
);
```

| Property             | Description                                |
| -------------------- | ------------------------------------------ |
| `sending`            | Shown when upload starts.                  |
| `verifyingIntegrity` | Shown while checking quality and validity. |
| `processingData`     | Shown while the backend extracts data.     |
| `almostDone`         | Shown in the final stage of verification.  |

## Full customization example

{% hint style="info" %}
All customization fields are optional.
{% endhint %}

```dart
final certta = CerttaSdk();

await certta.documentDetector.open(
  CerttaDocumentDetectorConfiguration(
    flow: [
      CafDocumentDetectorFlow(
        document: CafDocument.rgFront,
        stepLabel: 'ID Card Front',
        illustration: 'https://picsum.photos/400',
        message: 'Place the document on a table',
        okButtonTitle: 'Ok',
      ),
    ],
    showPopup: true,
    showPreview: true,
    maxRetryAttempts: 3,
    requestTimeout: 60,
    uploadSettings: const CafDocumentDetectorUploadSettings(enable: true),
    previewCustomization: const CafDocumentDetectorPreviewCustomization(
      title: 'Confirm Photo Quality',
      message: 'Ensure all details are clear and there are no reflections.',
      okButton: 'Confirm',
      tryAgainButton: 'Recapture',
    ),
    uploadCustomization: const CafDocumentDetectorUploadCustomization(
      image: 'https://picsum.photos/400',
      message: 'Please choose the document file you want to upload.',
      uploadButton: 'Upload file',
      cancelButton: 'Cancel',
    ),
    retryCustomization: const CafDocumentDetectorRetryCustomization(
      title: 'An error happened',
      description: 'Check your internet connection and try again',
      textButton: 'Try Again',
    ),
    messageCustomization: const CafDocumentDetectorMessageCustomization(
      waitMessage: 'Please wait...',
      fitTheDocumentMessage: 'Align your document within the frame.',
    ),
    uploadMessagesCustomization:
        const CafDocumentDetectorUploadMessagesCustomization(
      sending: 'Sending your document...',
      verifyingIntegrity: 'Checking image quality...',
      processingData: 'Extracting data...',
      almostDone: 'Wrapping things up...',
    ),
  ),
);
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.caf.io/caf-sdk/flutter/document-detector/ui-customizations.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
