> 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
```


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.accurascan.com/language/web-plugin/id-plugin/vue.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
