> For the complete documentation index, see [llms.txt](https://docs.accurascan.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.accurascan.com/language/web-plugin/id-plugin/vue.md).

# Vue

## Accura IDScan Plugin — Vue 3 Integration Guide

This guide walks you through integrating the **Accura IDScan Plugin** into a Vue 3 project built with Vite.

### Step 1: Initialize Project

If you do not have an existing Vue 3 project, scaffold one using Vite:

```bash
npm create vite@latest my-id-app -- --template vue
cd my-id-app
npm install
```

***

### Step 2: Install Plugin

Install the Accura IDScan Plugin package from the npm registry:

```bash
npm install accuraidscanplugin
```

***

### Step 3: Implementation

Create a dedicated scanner component at `components/IDScanner.vue`. The following snippet shows only the **plugin import and initialization** logic:

```vue
<script setup>
import { onMounted, onUnmounted } from 'vue';

let plugin = null; // Holds the active plugin instance for lifecycle management

onMounted(async () => {
  // Dynamically import the plugin inside onMounted to guarantee browser-only execution.
  // Vue's onMounted lifecycle hook runs exclusively on the client side,
  // making it safe to access browser APIs such as the camera.
  const { default: IDCardPlugin } = await import('accuraidscanplugin');

  // Instantiate the plugin with:
  //   1. The capture callback invoked when the scan is complete
  //   2. A configuration object specifying card target and UI appearance
  plugin = new IDCardPlugin(
    handleCapture,   // Fired automatically upon successful ID card scan
    {
      countryCode: "UGA",    // Country code of the ID card
      cardCode: "UGNIDF",    // Card code ID front Card
      topTextSize: "",       // Top overlay text size (default if empty)
      topTextColor: "",      // Top overlay text color (default if empty)
      topTextWeight: "",     // Top overlay font weight (default if empty)
      bottomTextSize: "",    // Bottom overlay text size (default if empty)
      bottomTextColor: "",   // Bottom overlay text color (default if empty)
      bottomTextWeight: "",  // Bottom overlay font weight (default if empty)
    }
  );

  // Activate the camera and begin the ID card detection session.
  await plugin.start();
});

// Release camera resources and destroy the plugin when the component unmounts.
onUnmounted(() => {
  if (plugin) {
    plugin.destroy();
  }
});
</script>
```

***

### Step 4: Response Handling

When the plugin completes an ID card scan, it invokes the **`handleCapture`** callback with a payload object that may contain one or both of the following properties:

| Property | Type     | Description                                                     |
| -------- | -------- | --------------------------------------------------------------- |
| `front`  | `string` | Base64 Data URL of the front side of the ID card                |
| `back`   | `string` | Base64 Data URL of the back side of the ID card (if applicable) |

**What is Base64?** Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. Each scanned card image is delivered as a Data URL string (e.g., `data:image/jpeg;base64,/9j/...`), combining a MIME type prefix with the encoded image payload. Before transmitting to a server, this string must be decoded back into binary form (a `Blob`) to construct a valid multipart HTTP request.

The following demonstrates the **base64-to-Blob conversion** and API submission:

```js
// Utility: converts a base64 Data URL string into a binary Blob.
// Multipart form uploads require raw binary data rather than text-encoded base64.
const base64ToBlob = (base64DataURL) => {
    // Separate the MIME type header from the encoded payload at the comma boundary.
    const [meta, content] = base64DataURL.split(",");

    // Extract the MIME type (e.g., "image/jpeg") from the header segment.
    const mimeMatch = meta.match(/:(.*?);/);
    const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";

    // Decode the base64-encoded payload back into raw binary characters.
    const binary = atob(content);

    // Reconstruct the binary bytes as a typed Uint8Array.
    const array = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        array[i] = binary.charCodeAt(i); // Map each character to its byte code
    }

    // Return a Blob with the appropriate MIME type for correct server handling.
    return new Blob([array], { type: mime });
};

// Submits a card image Blob to the server-side verification endpoint.
const sendToAPI = async (blob, isface, card_code, filename) => {
    const formData = new FormData();
    formData.append("scan_image", blob, filename);  // Binary image file
    formData.append("isface", isface);              // "front" or "back"
    formData.append("country_code", "UGA");         // ISO country code
    formData.append("card_code", card_code);        // Card template identifier
    formData.append("passport", "false");           // "true" for passport documents
    formData.append("webcam", "false");             // "true" if captured via webcam

    try {
        const response = await fetch("http://ip:port/doc_liveness.php", {
            method: "POST",
            body: formData,
        });
        const data = await response.json();
        console.log(`API Response (${isface}):`, data);

        if (data && data.score !== undefined) {
            console.log(`Score (${isface}): ${data.score}`);
        }
    } catch (error) {
        console.error(`Error sending ${isface} to API:`, error);
    }
};

// Primary capture callback — invoked by the plugin when scanning is complete.
const handleCapture = async (base64) => {
    if (base64.front) {
        const frontBlob = base64ToBlob(base64.front);
        await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
    }
    if (base64.back) {
        const backBlob = base64ToBlob(base64.back);
        await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
    }
};
```

***

### Step 5: Demo Implementation

The following is the **complete, production-ready component**. Copy and paste it directly into `components/IDScanner.vue`. The original logic is preserved exactly as-is.

```vue
<template>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue';

const isReady = ref(false);
let plugin = null;

onMounted(async () => {
  try {
    const { default: IDCardPlugin } = await import('accuraidscanplugin');

    const base64ToBlob = (base64DataURL) => {
        const [meta, content] = base64DataURL.split(",");
        const mimeMatch = meta.match(/:(.*?);/);
        const mime = mimeMatch ? mimeMatch[1] : "image/jpeg";
        const binary = atob(content);
        const array = new Uint8Array(binary.length);
        for (let i = 0; i < binary.length; i++) {
            array[i] = binary.charCodeAt(i);
        }
        return new Blob([array], { type: mime });
    };

    const sendToAPI = async (blob, isface, card_code, filename) => {
        const formData = new FormData();
        formData.append("scan_image", blob, filename);
        formData.append("isface", isface);
        formData.append("country_code", "UGA");
        formData.append("card_code", card_code);
        formData.append("passport", "false");
        formData.append("webcam", "false");

        try {
            console.log(`Sending ${isface} (${card_code}) to API...`);
            const response = await fetch("http://ip:port/doc_liveness.php", {
                method: "POST",
                body: formData,
            });

            const data = await response.json();
            console.log(`API Response (${isface}):`, data);

            if (data && data.score !== undefined) {
                console.log(`Score (${isface}): ${data.score}`);
            }
        } catch (error) {
            console.error(`Error sending ${isface} to API:`, error);
        }
    };


    const handleCapture = async (base64) => {
        console.log("Capture result received:", Object.keys(base64));

        if (base64.front) {
            console.log("Processing front side...");
            const frontBlob = base64ToBlob(base64.front);
            await sendToAPI(frontBlob, "front", "UGNIDF", "front.jpg");
        }
        if (base64.back) {
            console.log("Processing back side...");
            const backBlob = base64ToBlob(base64.back);
            await sendToAPI(backBlob, "back", "UGNIDB", "back.jpg");
        }
    };
    
    plugin = new IDCardPlugin(
      handleCapture,
      {
        countryCode: "UGA",
        cardCode: "UGNIDF",
        topTextSize: "",
        topTextColor: "",
        topTextWeight: "",
        bottomTextSize: "",
        bottomTextColor: "",
        bottomTextWeight: "",
      }
    );
    
    await plugin.start();
    isReady.value = true;
  } catch (error) {
    console.error("Vue plugin error:", error);
  }
});

onUnmounted(() => {
  if (plugin) {
    plugin.destroy();
  }
});
</script>

<style scoped>
</style>
```

***

### Step 6: Usage

Import and render the component in `App.vue`:

```vue
<script setup>
import IDScanner from './components/IDScanner.vue';
</script>

<template>
  <IDScanner />
</template>
```

***

### Step 7: Running the Project

```bash
npm run dev
```
