Hi there,
This is part of a two part series, where I am going to show you how to use React and Typescript coupled with FaceIO to sign-up, authenticate a user and consume user data in your website.
FaceIO is a facial authentication framework to authenticate users via face recognition instead of the traditional login/password. It is implemented via a simple JavaScript snippet (like google tag). More here.
The simplicity. We all know the complexity and work that goes into creating a way to authenticate users to your website yet all we want to do is to register a user and be able to login the user every time they came back. In comes FaceIO with the easiest way to add password less authentication to your web based application. As we go on you will see how easy it is leaving us with more time to create amazing user experiences.
FaceIO does not add to the bundle size of your project. As we will see we just add a script to the index.html and you are done.
It is compatible with pretty much every browser out there (Chrome, Firefox, Safari, Edge & Chromium derivatives).
Let me now demonstrate the simplicity of FaceIO by building this sign-up form.
Initializing React, Typescript and Tailwind CSS in our project using Vite.
Fire up you favorite code editor and open the bash terminal.
I am going to use yarn so,
yarn create vite
Follow the prompts as shown below.
You can use yarn dev — host
to host your project and be able to access it via multiple devices.
Let us add Tailwind CSS to our project.
yarn add -D tailwindcss postcss autoprefixer npx tailwindcss init -p
Go into src/tailwind.config.cjs and replace the contents with.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
If you now run yarn dev
Now let me show you how easy it is to add FaceIO to your project.
Go to index.html , note the contents and then replace them with,
<!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>FaceIO authentication using react + ts</title>
</head>
<body>
<script src="https://cdn.faceio.net/fio.js"></script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
As you can see the only thing we have added is
<script src=”https://cdn.faceio.net/fio.js"></script>
above the <div id=”root”></div>
It is as simple as that. More on the integration here.
Before we begin implementing FaceIO in our project you will need to sign up on FaceIO console. Once you have signed up you will come to this page.
Select NEW FACEIO APPLICATION and follow the prompts.
Once done note the public Id.
Before we continue to creating our sign-up form component let us also bring in tailwind css.
Go to index.css and replace the contents with,
@tailwind base;
@tailwind components;
@tailwind utilities;
Go to app.tsx and replace its contents with this,
function App() {
return (
<div className='min-h-screen flex justify-center'>
<h1 className='text-3xl font-bold text-yellow-600'>
FaceIO authentication using react and typescript
</h1>
</div>
);
}
export default App;
Your application should now look like this,
Let us now create a new folder named components and in it a file named SignupForm.tsx
We will use react hook form to create our form let us add it to our project.
yarn add react-hook-form @hookform/resolvers yup
Make the necessary imports in the SignupForm.tsx.
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
Import the form into app.tsx file and make necessary changes,
Let us create the ui for form.
Under the h1 tags in SignupForm.tsx,
<form className='space-y-6'>
<div>
<label
htmlFor=''
className='text-sm font-bold backdrop:bold text-gray-600 block'
>
Name
</label>
<input
type='text'
placeholder='name'
className='w-full p-2 border border-blue-900 rounded mt-1'
/>
</div>
<div>
<label
htmlFor=''
className='text-sm font-bold backdrop:bold text-gray-600 block'
>
Email
</label>
<input
type='text'
placeholder='[email protected]'
className='w-full p-2 border border-blue-900 rounded mt-1'
/>
</div>
<div>
<button className='w-full py-2 px-4 bg-blue-700 rounded-md text-white text-sm'>
Sign Up
</button>
</div>
</form>
Now for the fun part of adding the logic, first let us create a new folder in the folder src with a file to store our types which we are going to use through out our build let us call it,
/** src/@types/user.d.ts */
interface Iuser {
name: string;
email: string;
}
Back to our form let us define the data that we are going to take from the user and submit to faceIO to register the said user using yup. This should be done above the SignupForm declaration. This will also enable us to alert the user if any errors occur.
const SignupSchema = yup
.object({
name: yup.string().required(),
email: yup.string().required(),
})
.required();
Inside the SignupForm function let us use the useForm from react-hook-form. It provides us with some handy functions that will help us to take input from the user and deliver it where we need like, register, handleSubmit and errors, as shown below.
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Iuser>({
resolver: yupResolver(SignupSchema),
});
Let us also create a onSubmit function that will enable us to submit the data we take from the user to FaceIO.
const onSubmit = (data: Iuser) => {
alert(JSON.stringify(data));
handleSignUp(data);
};
As you can see inside there is a handleSignUp function let us define it but before we do that let us load FaceIO into our page using a useEffect hook, make the necessary import of useEffect then,
let faceio: any;
useEffect(() => {
faceio = new faceIO('fioxxxxxx');
}, []);
Note the ‘fioxxxxx’ you should ensure that you have replaced it with your FaceIO public id.
Let us now create the handleSignUp function
const handleSignUp = async (user: Iuser): Promise<any> => {
try {
let response: any = await faceio.enroll({
locale: 'auto',
payload: {
name: `${user.name}`,
email: `${user.email}`,
},
});
alert(
` Unique Facial ID: ${response.facialId}
Enrollment Date: ${response.timestamp}
Gender: ${response.details.gender}
Age Approximation: ${response.details.age}
payload: ${JSON.stringify(response.details)}`
);
} catch (error) {
alert('Unable to register you please refresh page and try again');
}
};
As you can see in it we have a try-catch block where in the try block we call a FaceIO function called enroll which takes a payload containing the name of the user and email which we will attain from the form. For more of the enroll function, check this documentation.
Let us now update the form tags to now be able to take in the user data and submit it.
<form className='space-y-6' onSubmit={handleSubmit(onSubmit)}>
//....
<form/>
And the input fields,
<input
type='text'
placeholder='name'
{...register('name')}
className='w-full p-2 border border-blue-900 rounded mt-1'
/>
{errors.name && <p className='text-red-900'>{errors.name.message}</p>}
//email input
<input
type='text'
placeholder='[email protected]'
{...register('email')}
className='w-full p-2 border border-blue-900 rounded mt-1'
/>
{errors.email && (
<p className='text-red-900'>{errors.email.message}</p>
)}
And with that we are done the whole sign up form looks like,
import React, { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
const SignupSchema = yup
.object({
name: yup.string().required(),
email: yup.string().required(),
})
.required();
const SignupForm = () => {
let faceio: any;
useEffect(() => {
faceio = new faceIO('fioa48b7');
}, []);
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Iuser>({
resolver: yupResolver(SignupSchema),
});
//create a submit function that will submit the data
const onSubmit = (data: Iuser) => {
alert(JSON.stringify(data));
handleSignUp(data);
};
//create a signup function that will submit the data to faceIO by calling the function faceIO enroll
const handleSignUp = async (user: Iuser): Promise<any> => {
try {
let response: any = await faceio.enroll({
locale: 'auto',
payload: {
name: `${user.name}`,
email: `${user.email}`,
},
});
alert(
` Unique Facial ID: ${response.facialId}
Enrollment Date: ${response.timestamp}
Gender: ${response.details.gender}
Age Approximation: ${response.details.age}
payload: ${JSON.stringify(response.details)}`
);
} catch (error) {
alert('Unable to register you please refresh page and try again');
}
};
return (
<div className='max-w-md mx-auto mt-4 bg-yellow-100 p-8 border border-gray-3000'>
<h1 className='text-3xl font-bold text-blue-600 pb-5'>
Sign-up form using FaceIO
</h1>
<form className='space-y-6' onSubmit={handleSubmit(onSubmit)}>
<div>
<label
htmlFor=''
className='text-sm font-bold backdrop:bold text-gray-600 block'
>
Name
</label>
<input
type='text'
placeholder='name'
{...register('name')}
className='w-full p-2 border border-blue-900 rounded mt-1'
/>
{errors.name && <p className='text-red-900'>{errors.name.message}</p>}
</div>
<div>
<label
htmlFor=''
className='text-sm font-bold backdrop:bold text-gray-600 block'
>
Email
</label>
<input
type='text'
placeholder='[email protected]'
{...register('email')}
className='w-full p-2 border border-blue-900 rounded mt-1'
/>
{errors.email && (
<p className='text-red-900'>{errors.email.message}</p>
)}
</div>
<div>
<button className='w-full py-2 px-4 bg-blue-700 rounded-md text-white text-sm'>
Sign Up
</button>
</div>
</form>
</div>
);
};
export default SignupForm;
This should be the finished product.
In case of errors while inputting the form data.
If everything is ok.
If you have loved this add a star to it over in GitHub.
For more on FaceIO.
There are also some very interesting articles to get you on your way.
That is the conclusion for now but part two is here, but always check in this space for more.
Also published here.