> 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/svelte.md).

# Svelte

## Accura IDScan Plugin — Svelte Integration Guide

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

### Step 1: Initialize Project

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

```bash
npm create vite@latest my-id-app -- --template svelte
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 `src/lib/IDScanner.svelte`. The following snippet shows only the **plugin import and initialization** logic:

```svelte
<script>
  import { onMount, onDestroy } from 'svelte';

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

  onMount(async () => {
    // Dynamically import the plugin inside onMount to guarantee browser-only execution.
    // Svelte's onMount 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 session is complete
    //   2. A configuration object specifying the target card 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 of front ID 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 is removed from the DOM.
  onDestroy(() => {
    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. This object 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, not text-encoded Base64 strings.
const base64ToBlob = (base64DataURL) => {
    // Split at the comma: left side = MIME header, right side = encoded image data.
    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 using atob().
    const binary = atob(content);

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

    // Wrap the reconstructed binary data in a Blob with the correct MIME type.
    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 `src/lib/IDScanner.svelte`. The original logic is preserved exactly as-is.

```svelte
<script>
  import { onMount, onDestroy } from 'svelte';
  
  let isReady = false;
  let plugin = null;

  onMount(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 = true;
    } catch (e) {
      console.error("Svelte IDScan Error:", e);
    }
  });

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

***

### Step 6: Usage

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

```svelte
<script>
  import IDScanner from './lib/IDScanner.svelte';
</script>

<IDScanner />
```

***

### Step 7: Running the Project

```bash
npm run dev
```
