Speed up UI development with realistic test data using Faker

Speed up UI development with realistic test data using Faker

J

Jihan Jasper Al Rashid

Jun 19, 2025

11 minutes

Are you developing a web application? Do you need realistic test data to speed up your UI development? Then this guide is for you.


At a glance


Install Faker

Let's install Faker in our project. The -D flag is there to install it as a development dependency since we only need it for development and testing purposes, not for production.

Inside the code snippets below, I'll typically include the file path as a comment at the top. This isn't Gospel. It's just there to help you understand where code like that should typically go in your project's file structure.

# npm
npm install -D @faker-js/faker

# pnpm
pnpm add -D @faker-js/faker

Create a utility function to generate fake data

Let's put Faker to work right away by creating a utility function which will serve as the core of our entire process. It's a simple function that generates whatever data we ask of it and returns it in a structured format. For the purpose of this guide, let's pick an employee as our target resource.

Let's create a file dedicated to this function and import Faker.

// src/lib/generators/generate-fake-employee.ts

import { faker } from "@faker-js/faker";

Let's work with a simple type definition for an employee and assume that Employee has the following structure.

type Employee = {
  id: string;
  firstName: string;
  lastName: string;
  email: string;
  avatar?: string;
  currentJob: {
    id: string;
    title: string;
    department?: string;
    startDate: string;
  };
  company: {
    id: string;
    name: string;
    logo?: string;
    email: string;
    phone: string;
    address: string;
    website: string;
  };
  metadata: {
    createdAt: string;
    updatedAt?: string;
  };
};

Faker has a many built-in methods. One of the most useful ones is faker.datatype.boolean(). It simply returns either true or false. It has an optional parameter, probability, which allows us to control the likelihood of it returning true. The default value is 0.5 which is 50%. We can use this to randomize the generation of optional fields in our data structure. Since our Employee type has 4 optional fields, we can build a utility function, randomlyInclude(), for reusability. This is simply to keep our code DRY. If you find TypeScript generics confusing or prefer not to use it for any other reason, you can safely skip it. For example, I didn't use it for the avatar field just as a reference.

// src/lib/generators/generate-fake-employee.ts

function randomlyInclude<T>(value: T, probability?: number): T | undefined {
  return faker.datatype.boolean({ probability: probability || 0.5 })
    ? value
    : undefined;
}

Now onto the main function that generates a fake employee. This function will return an object of type Employee with all the fields populated with random data generated by Faker.

// src/lib/generators/generate-fake-employee.ts

function generateFakeEmployee(): Employee {
  const firstName = faker.person.firstName();
  const lastName = faker.person.lastName();
  const companyName = faker.company.name();
  const companyDomain = faker.helpers
    .slugify(companyName)
    .replaceAll("-", "")
    .toLowerCase()
    .concat(faker.helpers.arrayElement([".com", ".net", ".org"]));

  return {
    id: faker.string.uuid(),
    firstName: firstName,
    lastName: lastName,
    email: faker.internet
      .email({
        firstName: firstName,
        lastName: lastName,
        provider: faker.helpers.arrayElement([
          "gmail.com",
          "yahoo.com",
          "hotmail.com",
        ]),
        allowSpecialCharacters: false,
      })
      .toLowerCase(),
    avatar: faker.datatype.boolean({ probability: 0.5 })
      ? faker.image.avatar()
      : undefined,
    currentJob: {
      id: faker.string.uuid(),
      title: faker.person.jobTitle(),
      department: randomlyInclude(faker.person.jobArea(), 0.5),
      startDate: faker.date.past({ years: 5 }).toISOString(),
    },
    company: {
      id: faker.string.uuid(),
      name: companyName,
      logo: randomlyInclude(
        faker.image.dataUri({
          type: "svg-uri",
          height: 512,
          width: 512,
          color: faker.color.human(),
        }),
        0.9,
      ),
      email: `info@${companyDomain}`,
      phone: faker.phone.number({ style: "international" }),
      address: faker.location.streetAddress({ useFullAddress: true }),
      website: `https://${companyDomain}`,
    },
    metadata: {
      createdAt: faker.date.past({ years: 5 }).toISOString(),
      updatedAt: randomlyInclude(
        faker.date.recent({ days: 7 }).toISOString(),
        0.9,
      ),
    },
  };
}

Before decorating the employee object, we generate a few supporting values to add more realism to the data. For example, an employee's email is usually based on their name, and a company's domain typically reflects its name. It wouldn't make sense for someone named Steve Jobs to have an email like bill_gates@hotmail.com while working at a company named Google with a domain like www.ibm.com.

So, what's happening here?

Note that I'm not even scratching the surface of what Faker can do. This isn't Faker's documentation. The chances are that if you can think of it, Faker can generate it. Please refer to the official Faker documentation and find out how to tailor it perfectly for your needs.

The interesting thing here is that this is the only time we use Faker directly. The rest of the guide will simply invoke this function in various ways to generate fake employees. It's that simple.

Create functions to fetch fake data

Now that we have a function to generate a single fake employee, we can easily create asynchronous functions to simulate fetching employees from an API. Let's create two: one to fetch a single employee by its id and another to fetch all employees. These are extremely common use cases.

Let's also add a little bit of delay to simulate the latency of a real API call. The value is in milliseconds.

// src/lib/api/employees.ts

export async function fetchFakeEmployeeById(
  id: string,
): Promise<Employee | null> {
  await new Promise((resolve) => setTimeout(resolve, 500));

  const employee = generateFakeEmployee();

  employee.id = String(id);

  return employee;
}

export async function fetchAllFakeEmployees(
  limit?: number,
): Promise<Employee[]> {
  await new Promise((resolve) => setTimeout(resolve, 500));

  const employees = Array.from({ length: limit || 16 }, () =>
    generateFakeEmployee(),
  );

  return employees;
}

What to expect from generated data

Just as a reference, the fake employees will look something like this:

[
  {
    "id": "56ce30e2-3f76-4217-a39c-602684c4e342",
    "firstName": "Gust",
    "lastName": "Jaskolski",
    "email": "gust_jaskolski@yahoo.com",
    "avatar": "https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/92.jpg",
    "currentJob": {
      "id": "ca055bb2-865d-40ee-b8c9-d3fde4efedce",
      "title": "Lead Paradigm Supervisor",
      "department": "Paradigm",
      "startDate": "2022-09-06T03:45:56.517Z"
    },
    "company": {
      "id": "668a6e0a-886a-4421-b3ba-34a8664a6f9f",
      "name": "Johnson - Ferry",
      "logo": "data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22512%22%20height%3D%22512%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22black%22%2F%3E%3Ctext%20x%3D%22256%22%20y%3D%22256%22%20font-size%3D%2220%22%20alignment-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20fill%3D%22white%22%3E512x512%3C%2Ftext%3E%3C%2Fsvg%3E",
      "email": "info@johnsonferry.net",
      "phone": "+13588397955",
      "address": "63350 Aaron Cliff Apt. 807",
      "website": "https://johnsonferry.net"
    },
    "metadata": {
      "createdAt": "2023-02-20T08:15:31.947Z",
      "updatedAt": "2025-07-06T18:43:33.395Z"
    }
  },
  {
    "id": "60302341-8095-4b91-a788-1268d15f7f6b",
    "firstName": "Tremayne",
    "lastName": "Wiza",
    "email": "tremayne_wiza54@gmail.com",
    "avatar": "https://avatars.githubusercontent.com/u/95719771",
    "currentJob": {
      "id": "cfdffe94-3755-4ce8-952f-29d4930b916a",
      "title": "International Interactions Analyst",
      "department": "Factors",
      "startDate": "2024-09-05T15:48:31.777Z"
    },
    "company": {
      "id": "ed14ad8f-5c1b-4e01-9a0b-3ed783ca6287",
      "name": "Huel Inc",
      "logo": "data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22512%22%20height%3D%22512%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22olive%22%2F%3E%3Ctext%20x%3D%22256%22%20y%3D%22256%22%20font-size%3D%2220%22%20alignment-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20fill%3D%22white%22%3E512x512%3C%2Ftext%3E%3C%2Fsvg%3E",
      "email": "info@huelinc.net",
      "phone": "+14704658910",
      "address": "4252 Bins Cape Apt. 232",
      "website": "https://huelinc.net"
    },
    "metadata": {
      "createdAt": "2021-07-08T06:56:46.558Z",
      "updatedAt": "2025-07-10T02:36:38.543Z"
    }
  }
]

Reuse a data set

Sometimes, you might want to reuse the same set of fake employees across multiple components or even coding sessions. This is especially useful when you're having troubles with certain combinations of data and UI components, and you want to ensure consistency throughout your fixes. faker.seed() has got you covered.

// src/lib/generators/generate-fake-employee.ts

faker.seed(42);

Simply put this at the top of the file where you use Faker. You don't have to do anything else. It'll use the same data set every time. The number you pass can be any integer you like. The important thing is that it should not be changed for as long as you want to maintain the same data set. As soon as you change it, Faker will generate a new set of data and then stick to that. Leaving it empty is the same as not using it at all (i.e. random).

Use fake data to build your UI

And we're done with the whole process. Now, we can use these fake employees to build our UI components as we normally would.

Here's what it would look like in a React (Next.js) component:

import { EmployeeCard } from "@/components/employees/employee-card";
import { fetchAllFakeEmployees } from "@/lib/api/employees";

export default async function EmployeesPage() {
  const employees = await fetchAllFakeEmployees(16);

  return (
    <main>
      <div>
        {employees.map((employee) => (
          <EmployeeCard key={employee.id} employee={employee} />
        ))}
      </div>
    </main>
  );
}

And here's a Vue.js (Nuxt) component:

<script setup lang="ts">
import { fetchAllFakeEmployees } from '@/lib/api/employees';

const employees = await fetchAllFakeEmployees(16);
</script>

<template>
  <main>
    <div>
      <EmployeeCard v-for="employee in employees" :key="employee.id" :employee="employee" />
    </div>
  </main>
</template>

Have fun building your UI out in the wild.