Skip to content

Generating Custom Bitmoji in Next.js

A Bitmoji is simply an emoji of a person’s resemblance. Users across different social media platforms commonly use them as customized emojis that attempts to replicate a user’s physical appearance.

Here is an example of Bitmojis:

image

This post will cover generating a custom Bitmoji using a Next.js application.

One of the most common platforms for creating and customizing Bitmoji is https://www.bitmoji.com/. Other platforms are:

To fully follow this tutorial, you will need the following:

  • Node.js Installed
  • Mirror AI Account (Mirror AI offers a free subscription for limited API calls)
  • React.js/Next.js

You can get the live demo at CodeSandbox, and the source code is available on GitHub.

For this post, you will use Mirror AI to generate custom Bitmoji. Mirror AI enables a user to generate Bitmojis and stickers with their face. Users upload an image with their face, and the API transforms it into a Bitmoji.

One must have an account to get the API key to use the API. Use this link to create a Free Account: https://business.mirror-ai.com/pricing. Once the account is successfully created, you will be redirected to an API dashboard page containing API keys and links to documentation.

For this post, you will use the /generate API to upload and get a custom Bitmoji.

To test the /generate API, click the Try it out button on the top right. Copy your API key from your account dashboard. Paste the token inside the X-Token input box:

Inside the Request body container, click the Choose File input to upload an image.

Note: For better results, use an up-close image, i.e.:

After selecting an image, click on the blue Execute button:

The API returns the following after a successful execution:

    {
      "ok": true,
      "face": {
        "id": "C7asFWrkQKC001U_8N55pg",
        "version": "yB4",
        "url": "https://f.mirror-ai.net/x/mjmTO_wGOteE7Zlvg9tuj820OaLCMZKcRBXRP7LiiO19QENeSW_1uc1VIIY4LxQJMLALuDzM7CzWD4DA6KYURIkSxNKyb6tRmhdg372x974"
      }
    }
Code language: JSON / JSON with Comments (json)

The Bitmoji created below was obtained from the url inside the response:

To create, open the terminal and run the following:

npx create-next-app bitmoji-generator

Once the installation is complete, run the development server to confirm a successful setup:

npm run dev

For basic styling of the page, you will use bootstrap css. To install bootstrap, run the following in the terminal:

npm i bootstrap@5.2.0

Once the installation is complete, import Bootstrap inside pages/_app.js file:

    import 'bootstrap/dist/css/bootstrap.min.css'
    import '../styles/globals.css'
    function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />
    }
    export default MyApp
Code language: JavaScript (javascript)

Mirror AI is developed for use inside server-side code, but since you are using Next.js, a client-side library, you will have to use a different approach. You will need to install the following modules:

  • multer: A middleware to handle file uploads of type multipart/form-data
  • cors: A Node.js middleware to handle and manage Cross-Origin Resource Sharing(CORS)
  • form-data: A library to be used to submit forms and file uploads to other web applications

Install the modules by running the following command:

npm install multer cors form-data

Inside the pages/api directory, add a new file: mirror.js, then paste the code snippet below:

import multer from 'multer'
const axios = require('axios')
const FormData = require('form-data')
const fs = require('fs')

export const config = {
  api: {
    bodyParser: false,
  },
}

const storage = multer.diskStorage({
  destination: './public/uploads',
  filename: (req, file, cb) => cb(null, file.originalname),
})

const upload = multer({
  storage,
})

export default function mirror(req, res) {
  upload.single('file')(req, {}, async (err) => {
    const filePath = `./public/uploads/${req.file.originalname}`
    const form = new FormData()
    form.append(
      'photo',
      fs.readFileSync(filePath),
      `${req.file.filename};type=${req.file.mimetype}`
    )

    const response = await axios.post(
      'https://public-api.mirror-ai.net/v2/generate',
      form,
      {
        params: {
          style: 'kenga',
        },
        headers: {
          ...form.getHeaders(),
          accept: 'application/json',
          'X-Token': 'f63272366f3b4d56915b620101a7a2e7',
          'Content-Type': 'multipart/form-data',
        },
      }
    )

    if (response.data.ok) {
      res.status(200).json({ msg: response.data })
    } else {
      res.status(500).json({ msg: 'error' })
    }
  })
}
Code language: JavaScript (javascript)

In the code above, multer is used to enable file upload and specify the upload directory:

    const storage = multer.diskStorage({
      destination: './public/uploads',
      filename: (req, file, cb) => cb(null, file.originalname),
    })
    const upload = multer({
      storage,
    })
Code language: JavaScript (javascript)

Inside the mirror() function, you use fetch API to send data to mirror ai API:

    const response = await axios.post(
          'https://public-api.mirror-ai.net/v2/generate',
          form,
          {
            params: {
              style: 'kenga',
            },
            headers: {
              ...form.getHeaders(),
              accept: 'application/json',
              'X-Token': 'f63272366f3b4d56915b620101a7a2e7',
              'Content-Type': 'multipart/form-data',
            },
          }
        )
Code language: JavaScript (javascript)

Once the upload is successful, you return the response:

    if (response.data.ok) {
          res.status(200).json({ msg: response.data })
        } else {
          res.status(500).json({ msg: 'error' })
     }
Code language: JavaScript (javascript)

For a user to upload their image, you will use form input of type that takes in files:

<input type='file' />

Create a new directory called components, add a new file ImageUploadForm.jsx, and add the following snippet below:

    import Image from 'next/image'
    import { useState } from 'react'
    
    const ImageUploadForm = () => {
      // upload image to API
      const [image, setImage] = useState(null)
      const [imgResult, setImgResult] = useState(null)
    
      const handleImageUpload = (e) => {
        // get file from event
        setImage(e.target.files[0])
      }
      const handleSubmit = (e) => {
        e.preventDefault()
        const formData = new FormData()
        formData.append('file', image)
        fetch('/api/mirror', {
          method: 'POST',
          body: formData,
        })
          .then((res) => res.json())
          .then((res) => setImgResult(res.msg.face.url))
          .catch((err) => console.log(err))
      }
      return (
        <div>
          <form className='form form-control' onSubmit={handleSubmit}>
            <div className='m-4'>
              <label htmlFor='formFileLg' className='form-label'>
                Upload Your Photo
              </label>
              <input
                className='form-control form-control-lg'
                type='file'
                required
                onChange={handleImageUpload}
              />
              <button className='btn btn-primary mt-3' type='submit'>
                Submit
              </button>
            </div>
          </form>
          {imgResult && (
            <Image alt='bitmoji' width={500} height='500' src={imgResult} />
          )}
        </div>
      )
    }
    export default ImageUploadForm
    
Code language: JavaScript (javascript)

In the snippet above, you’ve used React Hooks to handle image uploads and get the new image from the API:

      const [image, setImage] = useState(null)
      const [imgResult, setImgResult] = useState(null)
Code language: JavaScript (javascript)

You will have a handleImageUpload() and handleSubmit() to handle events when a user uploads an image and after the image is submited:

     const handleImageUpload = (e) => {
        // get file from event
        setImage(e.target.files[0])
      }
      const handleSubmit = (e) => {
        e.preventDefault()
        const formData = new FormData()
        formData.append('file', image)
        fetch('/api/mirror', {
          method: 'POST',
          body: formData,
        })
          .then((res) => res.json())
          .then((res) => setImgResult(res.msg.face.url))
          .catch((err) => console.log(err))
      }
Code language: JavaScript (javascript)

Run the local server to view the changes:

npm run dev

Try uploading an image with a good view of the face and notice the changes:

This post demonstrates how Mirror API generates custom Bitmoji.

  1. https://github.com/netlify/next-react-server-components
  2. https://vercel.com/blog/everything-about-react-server-components
  3. https://mirror-ai.com/
  4. https://rapidapi.com/mirror-dev-team/api/mirror-ai/
Back to top

Featured Post