# Get started with Capacitor

> Build a small Capacitor app that enrols your face and verifies it offline, on your own phone.

Source: https://docs.faceping.ai/start/capacitor/

What you'll build

### A face check that works in airplane mode

An app that enrols your face, verifies it live with a head-turn liveness check, and still matches with no network.

About 10 minutes
Android phone or iPhone
Free sandbox key

## Get a sandbox key

Sign up at [app.faceping.ai/signup](https://app.faceping.ai/signup) with your email, then open [**Developers → Sandbox keys → Create sandbox key**](https://app.faceping.ai/developers). It starts with `fp_test_`.

The sandbox is free and instant: up to 25 faces per device, each deleted 24 hours after it was enrolled. No card, no approval.

## Create the project

You need Node 22 or later and a phone with a cable: an Android phone (Android 7 or later, 64-bit) with USB debugging on, the Android SDK and JDK 21 (both come with [Android Studio](https://developer.android.com/studio)), or an iPhone (iOS 16 or later) and a Mac with Xcode 26 or later.

A web app built with Vite and TypeScript, wrapped by Capacitor 8:

```bash
npm create vite@latest facecheck -- --template vanilla-ts
cd facecheck
npm install
npm install @capacitor/core @capacitor/android @capacitor/ios
npm install -D @capacitor/cli
npx cap init FaceCheck com.example.facecheck --web-dir dist
```

Already have a Capacitor app (Ionic, Angular, React or Vue)? Skip to step 3: FacePing works the same in any of them.

First Capacitor app on this machine?

The 10 minutes assume your machine already builds Capacitor apps for your phone. If it doesn't, follow Capacitor's [environment set-up](https://capacitorjs.com/docs/getting-started/environment-setup) (Android Studio, or Xcode on a Mac; both take a while to download).

## Add FacePing

One package from npm. It brings the face models, liveness checks and its own camera screen with it. FacePing for Capacitor is in preview, under the `preview` tag:

```bash
npm install @faceping/capacitor@preview
npm run build
npx cap add android
npx cap add ios
```

`npx cap add` creates the native `android` and `ios` projects. Android gets the FacePing SDK from Maven Central; iOS gets it as a Swift package from [faceping/faceping-ios](https://github.com/faceping/faceping-ios). See [npm](https://www.npmjs.com/package/@faceping/capacitor) for the latest version.

## Allow the camera

- **iOS:** open the project with `npx cap open ios`. In the **App** target, set **General → Minimum Deployments** to **iOS 16.0**. On the **Info** tab, add **Privacy - Camera Usage Description** (`NSCameraUsageDescription`) with a sentence such as "FaceCheck uses the camera to verify your face." iOS shows it to the person before the camera turns on, and stops the app without it. Then run `npx cap sync ios`.
- **Android:** nothing to add. The FacePing library declares the camera permission (and `INTERNET`, to activate your key).

The camera screen asks the person for the camera the first time it opens.

**Why iOS 16?** The FacePing iOS SDK needs iOS 15.1, and Capacitor's Swift Package Manager setup rounds the app's target down to a whole version. Apps that use CocoaPods can stay on iOS 15.1. See [iOS versions](https://docs.faceping.ai/sdk/capacitor/#ios-versions).

## Turn FacePing on

Set FacePing up once, when the app starts, with your sandbox key. Add this to `src/main.ts`, under the imports:

```ts title="src/main.ts"
import { FacePing } from '@faceping/capacitor';

// Starts loading the face models in the background, so the first check is quick.
FacePing.init({ sandboxKey: 'fp_test_…' }).catch((e) => console.warn(e.message));
```

To keep the key out of your code, put `VITE_FACEPING_SANDBOX_KEY=fp_test_...` in `.env.local` (the Vite template keeps it out of git) and use `import.meta.env.VITE_FACEPING_SANDBOX_KEY`, as the starter app does.

## Add the screen

Two buttons: one enrols your face on the phone, the other verifies it. Each opens FacePing's camera screen, which closes itself when the check is done. Replace `src/main.ts` (the `init` call from step 5 is at the top).

```ts title="src/main.ts"
import { FacePing } from '@faceping/capacitor';

// Starts loading the face models in the background, so the first check is quick.
FacePing.init({ sandboxKey: 'fp_test_…' }).catch((e) => console.warn(e.message));

document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
  <button id="enroll">Enrol my face</button>
  <button id="verify">Verify</button>
  <p id="status"></p>`;

const status = document.querySelector<HTMLParagraphElement>('#status')!;

// For example no connection on the very first run (the sandbox key is activated once), or the camera screen closed.
const act = (action: () => Promise<string>) =>
  action().then((text) => (status.textContent = text), (e: Error) => (status.textContent = e.message));

document.querySelector('#enroll')!.addEventListener('click', () =>
  act(async () => {
    const result = await FacePing.enroll('me'); // opens the camera screen and takes a photo
    return result.isEnrolled ? 'Enrolled. Now tap Verify.' : `Try again: ${result.outcome}`;
  }),
);

document.querySelector('#verify')!.addEventListener('click', () =>
  act(async () => {
    // A live check: matches your face, then asks you to turn your head (liveness).
    const result = await FacePing.verifyLive('me');
    const time = (result.elapsedMs / 1000).toFixed(2);
    return result.isMatch ? `Match · ${time} s` : `Try again: ${result.outcome}`;
  }),
);
```

## Run it on your phone

Plug your phone in, build the web app, copy it into the native projects and run one of these (Capacitor asks which device):

```bash
npm run build && npx cap sync
npx cap run android
npx cap run ios
```

A debug build is fine: the FacePing core inside the SDK is already compiled for speed, whichever build you run. On iOS, pick your team in Xcode under **Signing & Capabilities** first (`npx cap open ios`), or run the app from Xcode. The first time, turn on **Developer Mode** on the iPhone (**Settings → Privacy & Security → Developer Mode**).

The first run needs a connection, to activate your sandbox key. Tap **Enrol my face** and take a photo, then tap **Verify** and turn your head when asked: you should see `Match`. Emulators and the simulator have no real front camera, so use your phone.

**Now switch on airplane mode and tap Verify again.** Still a match: the check ran entirely on your phone.

## You've built a face check that works offline

Next, make it real: verify the people in your app (members, staff or people with tickets), and apply to go live when you're ready.

- [Clone the finished app](https://github.com/faceping/capacitor-starter): github.com/faceping/capacitor-starter
- [How the SDK works](https://docs.faceping.ai/sdk/): Liveness, storage, sandbox limits
- [Capacitor reference](https://docs.faceping.ai/sdk/capacitor/): Every type and method
- [@faceping/capacitor on npm](https://www.npmjs.com/package/@faceping/capacitor): Versions and changelog
