Skip to content

Building an Angular Document Scanner web app in TypeScript

Kevin March 28, 2025 8 mins read
app store

In this tutorial, we’ll create a web app for scanning documents and exporting them as PDF files using Angular 19 and the Scanbot Web Document Scanner SDK.

Scanning a document with our Angular web app and exporting it as a PDF file

Angular 19 includes several notable improvements over older versions. One improvement relative to this tutorial is that it treats all components as standalone by default, so there is no need to specify this metadata property throughout your app.

We’ll create our Angular document scanning app by following these steps:

  1. Setting up the project
  2. Creating the document scanner service
  3. Creating the document scanner component
  4. Updating the app component

Let’s get started!

Requirements

Step 1: Set up the project

First, open a terminal and install the Angular CLI globally with the -g option.

npm install -g @angular/cli@latest

We’ll start with a fresh Angular 19 project using the CLI, which automatically creates all the necessary Angular framework files.

In your terminal, navigate to where you want to place the app and create a new project (we’ll go with the name “scanbot-tut”) using the following command:

ng new scanbot-tut --skip-git

We add --skip-git simply so that Angular doesn’t try to initialize a new Git repo for this demo.

When prompted, select:

  • “CSS” (default) for stylesheet format
  • “N” (default) to enabling SSR and SSG/Prerendering

Once the project is created, navigate into it and install the Scanbot Web SDK package with npm using the --save option to add it to your project’s dependencies:

cd scanbot-tut
npm install scanbot-web-sdk --save

⚠️ The SDK’s size might slightly exceed the budget specified in your angular.json file, preventing you from building the app. To fix this, simply set "maximumError" to "2mb".

Since Angular’s build process doesn’t automatically handle WebAssembly (WASM) files, we need to ensure that these files are included in the final build output. Copy all the files from /scanbot-tut/node_modules/scanbot-web-sdk/bundle/bin/complete/ to a new directory called wasm inside the app’s public directory.

You can quickly copy them using the following command:

mkdir -p public/wasm && cp -r node_modules/scanbot-web-sdk/bundle/bin/complete/* public/wasm

💡 To ensure these files are always copied to the same directory for all users and updated when the SDK itself is updated, you can add the command as a post-installation script to your package.json:

"postinstall": "mkdir -p public/wasm && cp -r node_modules/scanbot-web-sdk/bundle/bin/complete/* public/wasm"

Now we have our Angular project ready and scaffolded along with the Scanbot SDK and the engine files needed to run the SDK. Let’s start coding!

Step 2: Create the document scanner service

First, let’s create a service to handle the document scanner’s initialization, configuration, and PDF export handling.

To create this service, run the command ng generate service services/document-scanner and replace the contents of src/app/services/document-scanner.service.ts with the following code:

import { Injectable, signal } from '@angular/core';
import ScanbotSDK from 'scanbot-web-sdk/ui';
import { DocumentScannerUIResult } from 'scanbot-web-sdk/@types/ui2/configuration/document/DocumentScannerUIResult';
import { PdfConfiguration } from 'scanbot-web-sdk/@types';

@Injectable({
  providedIn: 'root',
})
export class DocumentScannerService {
  private readonly scanResult = signal<DocumentScannerUIResult | null>(null);

  constructor() {
    this.initializeSDK();
  }

  private async initializeSDK() {
    try {
      await ScanbotSDK.initialize({
        licenseKey: '', // Empty for 60-second trial mode
        enginePath: '/wasm/',
      });
    } catch (error) {
      console.error('Error initializing Scanbot SDK:', error);
    }
  }

  async createDocumentScanner() {
    const config = new ScanbotSDK.UI.Config.DocumentScanningFlow();
    return await ScanbotSDK.UI.createDocumentScanner(config);
  }

  getScanResult() {
    return this.scanResult.asReadonly();
  }

  setScanResult(result: DocumentScannerUIResult | null) {
    this.scanResult.set(result);
  }

  async handleDocumentExport() {
    const result = this.scanResult();
    if (!result) return;

    try {
      const options: Partial<PdfConfiguration> & { runOcr: boolean } = {
        pageSize: 'A4',
        pageDirection: 'PORTRAIT',
        pageFit: 'FIT_IN',
        dpi: 72,
        jpegQuality: 80,
        runOcr: false,
      };

      const document = await result.document.createPdf(options);
      await this.exportPdf(document);
    } catch (error) {
      console.error('Error exporting PDF:', error);
    }
  }

  private async exportPdf(documentData: ArrayBuffer) {
    const a = document.createElement('a');
    document.body.appendChild(a);
    a.style.display = 'none';
    const blob = new Blob([documentData], { type: 'application/pdf' });
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = 'scanned-document.pdf';
    a.click();
    window.URL.revokeObjectURL(url);
    document.body.removeChild(a);
  }
}

In this service, we initialize the Scanbot SDK with an empty license key and tell it where to find the WASM engine files.

💡 Leave the key empty to use a trial mode that works for 60 seconds per session or get a free 7-day trial by submitting the trial license form on our website.

The createDocumentScanner method sets up the SDK’s document scanning flow, then launches the scanner with the provided config. The scanner provides real-time document detection with user guidance, auto-cropping, perspective correction, and other features. This method is activated on clicking the “Run Scanner” button in the component we will create in the next section.

Meanwhile, the handleDocumentExport method, activated on clicking the “Export PDF” button, exports the scanned pages as a PDF and triggers a download with exportPdf. To customize the look of the final PDF export, change the PdfConfiguration properties accordingly. For example, if you need very high-quality scans, you can set jpegQuality to 100 instead of 80.

For more advanced configuration, see the API Reference page for the Web Document Scanner API. You may also learn how the PdfConfiguration class works and see what other values are accepted for pageSize, pageDirection, pageFit, and so on.

Step 3: Create the document scanner component

Next, we will add a document scanner component that can be added anywhere else in your application, to which the scanner service will be attached (injected).

To create this component, use ng generate component components/document-scanner and add the following code to the src/app/components/document-scanner.component.ts file:

import { Component, inject } from '@angular/core';
import { DocumentScannerService } from '../../services/document-scanner.service';

@Component({
  selector: 'app-document-scanner',
  template: `
    <div>
      <button (click)="runDocumentScanner()" class="scan-button">
        Run Scanner
      </button>
      @if (scanResult()) {
        <button (click)="handleDocumentExport()" class="export-button">
          Export PDF
        </button>
      }
    </div>
  `,
  styles: [`
    .scan-button, .export-button {
      margin: 10px;
      padding: 10px 20px;
      font-size: 16px;
    }
  `],
})
export class DocumentScannerComponent {
  private readonly documentScannerService = inject(DocumentScannerService);
  protected readonly scanResult = this.documentScannerService.getScanResult();

  async runDocumentScanner() {
    try {
      const result = await this.documentScannerService.createDocumentScanner();
      if (result) {
        this.documentScannerService.setScanResult(result);
      }
    } catch (error) {
      console.error('Error during document scanning:', error);
    }
  }

  async handleDocumentExport() {
    await this.documentScannerService.handleDocumentExport();
  }
}

This component provides buttons to run the document scanner and export the scanned document as a PDF. It uses Angular’s signal-based state management to track the scan result and conditionally render the export button.

The actual scanning- and export-related tasks are provided by the document scanner service we created earlier, which includes the Document Scanner Ready-To-Use UI.

Step 4: Update the app component

Now, let’s update the root app component to use our document scanner component.

Replace the contents of src/app/app.component.ts with the following:

import { Component } from '@angular/core';
import { DocumentScannerComponent } from './components/document-scanner/document-scanner.component';

@Component({
  selector: 'app-root',
  imports: [DocumentScannerComponent],
  template: `
    <main class="app-container">
      <h1>Angular Document Scanner</h1>
      <app-document-scanner />
    </main>
  `,
  styles: [`
    .app-container {
      text-align: center;
      padding: 20px;
    }
  `],
})
export class AppComponent {}

The AppComponent acts as the main view for the app, showing the DocumentScannerComponent with its “Run Scanner” and “Export PDF” buttons. This simple setup ensures that the document scanner can be launched right away when you run and open the app.

Got some documents handy? Let’s run the app, scan a few pages, and try the PDF export feature!

Scanning a document with our Angular web app and exporting it as a PDF file

💡 To test your web app on your phone, you have a few options. One option is to use a service like ngrok, which creates a tunnel to one of their SSL-certified domains. Their Quick Start guide will help you get up and running quickly.

You can also use ng serve in your terminal with host as a wildcard address (0.0.0.0) or your current IP address, and specify the --ssl option:

ng serve --ssl --host 0.0.0.0

Angular will then serve your app on the local network with a self-signed SSL certificate for HTTPS.

Conclusion

🎉 Congratulations! You now have a fully functional document scanner integrated into your Angular 19 application that lets you export documents as PDF.

For more customization options, check out the RTU UI Documentation and the API Documentation.

If this tutorial has piqued your interest in integrating document scanning functionalities into your web app, make sure to take a look at our SDK’s other neat features in our documentation.

Should you have questions about this tutorial or run into any issues, we’re happy to help! Just shoot us an email via tutorial-support@scanbot.io.