Creating a KYC flow and deploying it
What will be covered in this guide
In this guide, we will start a new project, create a KYC flow, customize its UI and translations, and deploy it to Netlify. Source code and deployed app also available.
Glossary
- Flow - A group of UI steps which collect the necessary information to verify the identity of a user, letting the user confirm the information, and ending in a verification step and a result.
- KYC - Know Your Customer
- KYB - Know Your Business
Pre-requisites
- Basic knowledge of HTML and TypeScript
- A code editor of your choice (VSCode, WebStorm, etc.)
- A browser (Chrome, Firefox, Safari, etc.)
- A package manager (pnpm, yarn, npm, etc.)
Setup
For the purpose of this guide we’ll be using a clean Vite + TypeScript template. Run the following command in your working directory to create a new project:
pnpm create vite ballerine-kyc-flow --template vanilla-ts
npm create vite ballerine-kyc-flow -- --template vanilla-ts
yarn create vite ballerine-kyc-flow --template vanilla-ts
Open the new project in your code editor and cd into the directory if you haven’t already.
cd ballerine-kyc-flow
Now, remove everything but main.ts
and vite-env.d.ts
from the src
directory and empty out main.ts
.
Installation
Make sure you run the following command in the root of the project we’ve created in the previous step.
pnpm install @ballerine/web-ui-sdk@1.3.19
npm install @ballerine/web-ui-sdk@1.3.19
yarn install @ballerine/web-ui-sdk@1.3.19
Creating a KYC flow
Now that we’ve created a new project and installed the Ballerine SDK, we can start creating our KYC flow. Let’s start by going to index.html
and then add a div
with the id of kyc-container
.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ballerine KYC Flow</title>
</head>
<body>
<!-- Element to pass into mount to contain the flow -->
<div id="kyc-container"></div>
<!-- flows.init and flows.mount -->
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Next, we’ll go to src/main.ts
, import flows
from @ballerine/web-ui-sdk
, create our flow, and mount it.
// src/main.ts
import { flows } from '@ballerine/web-ui-sdk';
flows
.init({
endUserInfo: {
id: 'test',
},
uiConfig: {
// Specify the steps you want to include in the flow.
flows: {
// Same name as the argument passed into mount.
'my-kyc-flow': {
steps: [
{
name: 'welcome',
id: 'welcome',
},
// Let the user choose verification by passport, license, etc.
{
name: 'document-selection',
id: 'document-selection',
documentOptions: ['id_card'],
},
{
name: 'document-photo',
id: 'document-photo',
},
// Let the user confirm if the document photo is okay.
{
name: 'check-document',
id: 'check-document',
},
{
name: 'loading',
id: 'loading',
},
{
name: 'final',
id: 'final',
},
],
},
},
},
})
.then(() => {
// mount(flowName: string, elementId: string);
// flowName matches the flow name specified in uiConfig.
// elementId is the id of the element to mount the flow into, the id of the div we've added in index.html.
flows.mount({
flowName: 'my-kyc-flow',
elementId: 'kyc-container',
useModal: true,
});
});
Let’s run the dev
script.
pnpm run dev
npm run dev
yarn run dev
Now if we navigate to http://127.0.0.1:5173/ in the browser we should see the following:
![Ballerine KYC Flow](/flow.png)
Customizing the UI
Great! Now that we’ve created our flow, let’s start personalizing it. uiConfig
also exposes properties to change things like colors and fonts. Back in src/main.ts
let’s add the following.
// src/main.ts
import { flows } from '@ballerine/web-ui-sdk';
flows
.init({
endUserInfo: {
id: 'test',
},
uiConfig: {
// Change the color and font of the flow.
general: {
colors: {
primary: '#1F9F31',
},
fonts: {
name: 'Roboto',
link: 'https://fonts.googleapis.com/css2?family=Roboto:wght@500;700&display=swap',
weight: [500, 700],
},
},
// Specify the steps you want to include in the flow.
flows: {
// Same name as the argument passed into mount.
'my-kyc-flow': {
steps: [
{
name: 'welcome',
id: 'welcome',
},
// Let the user choose verification by passport, license, etc.
{
name: 'document-selection',
id: 'document-selection',
documentOptions: ['id_card'],
},
{
name: 'document-photo',
id: 'document-photo',
},
// Let the user confirm if the document photo is okay.
{
name: 'check-document',
id: 'check-document',
},
{
name: 'loading',
id: 'loading',
},
{
name: 'final',
id: 'final',
},
],
},
},
},
})
.then(() => {
// mount(flowName: string, elementId: string);
// flowName matches the flow name specified in uiConfig.
// elementId is the id of the element to mount the flow into, the id of the div we've added in index.html.
flows.mount({
flowName: 'my-kyc-flow',
elementId: 'kyc-container',
useModal: true,
}).then();
});
Let’s see our changes in the browser!
![Ballerine KYC Flow - customized](/flow-customized.png)
Adding a translation
Now, what would we do if our product is used globally or English is not our own native language? For that we can specify overrides on a per flow step basis for different locales. Let’s add a translation for the welcome
step.
// src/main.ts
import { flows } from '@ballerine/web-ui-sdk';
flows
.init({
// Add translations.
translations: {
overrides: {
// Can be any locale as long as it is matched in endUserInfo.language below.
fr: {
// Translations for the welcome step.
welcome: {
title: 'Vérifiez Votre Identité',
button: 'Choisissez le type de document',
description:
'Nous avons besoin de certaines informations pour nous aider à confirmer votre identité.',
tip: 'La vérification prend généralement quelques secondes.',
},
},
},
},
endUserInfo: {
id: 'test',
// Specify the locale (should exist in the overrides).
language: 'fr',
},
uiConfig: {
// Change the color and font of the flow.
general: {
colors: {
primary: '#1F9F31',
},
fonts: {
name: 'Roboto',
link: 'https://fonts.googleapis.com/css2?family=Roboto:wght@500;700&display=swap',
weight: [500, 700],
},
},
// Specify the steps you want to include in the flow.
flows: {
// Same name as the argument passed into mount.
'my-kyc-flow': {
steps: [
{
name: 'welcome',
id: 'welcome',
},
// Let the user choose verification by passport, license, etc.
{
name: 'document-selection',
id: 'document-selection',
documentOptions: ['id_card'],
},
{
name: 'document-photo',
id: 'document-photo',
},
// Let the user confirm if the document photo is okay.
{
name: 'check-document',
id: 'check-document',
},
{
name: 'loading',
id: 'loading',
},
{
name: 'final',
id: 'final',
},
],
},
},
},
})
.then(() => {
// mount(flowName: string, elementId: string);
// flowName matches the flow name specified in uiConfig.
// elementId is the id of the element to mount the flow into, the id of the div we've added in index.html.
flows.mount({
flowName: 'my-kyc-flow',
elementId: 'kyc-container',
useModal: true,
}).then();
});
Let’s try and see our changes in the browser!
![Ballerine KYC Flow - translated](/flow-translated.png)
Deployment
Now that we’ve created our flow, let’s deploy it to the web. For the purpose of this guide we’ll do a manual deployment to Netlify. If you haven’t already, sign up and sign in to Netlify.
- Build the project - doing so will generate a
dist
directory at the root of the project.
pnpm run build
npm run build
yarn run build
- Compress the
dist
directory into a zip file. - Navigate to Netlify’s drop deployment.
- Upload the zip file by dragging and dropping it into the upload box, and wait for the upload to finish. If this step gives you issues, give
browse to upload
a try, in my case uploading from Firefox instead of Chrome worked. - Congratulations, we did it!
![Netlify's successful deployment](/deploy-success.png)
Where to go from here
- Flows documentation
- SDK source code
- Need help or got a question? Join our Discord!