Building a Random Password Generator with UI in Next.js

Passwords are the primary means of securing access to online services, applications, and sensitive information. Given the increasing complexity of cyber threats, it's essential to use strong, unique passwords. A random password generator can simplify this process by allowing users to generate passwords that include letters, numbers, symbols, and customizable lengths, ensuring a high level of security.

In this blog, we'll walk through how to build a random password generator with a user-friendly UI using Next.js. The project will allow users to:

  1. Choose the length of the password.

  2. Include/exclude uppercase, lowercase, numbers, and symbols.

  3. Copy the generated password to the clipboard with a button click.

Prerequisites

To follow along, you'll need:

  • Basic knowledge of TypeScript, React, and Next.js.

  • Node.js installed on your system.

  • A code editor like VS Code.

Let's get started!

Step 1: Setting up the Next.js project

First, we’ll need to create a new Next.js project.

  1. Open your terminal and create a new Next.js project:

     npx create-next-app@latest password-generator
    
  2. Navigate into the project directory:

     cd password-generator
    
  3. Start the development server:

     npm run dev
    

Your Next.js project is now up and running, and you can access it by going to http://localhost:3000.


Step 2: Designing the Password Generator UI

Let's begin by designing the UI for our password generator. We'll use basic HTML and CSS, and integrate it with React state management to allow users to interact with the password generator.

In the pages/index.js file, replace the default content with the following:

"use client";
import { useState } from "react";

export default function Home() {
  const [password, setPassword] = useState("");
  const [passwordLength, setPasswordLength] = useState(12);
  const [includeUppercase, setIncludeUppercase] = useState(true);
  const [includeLowercase, setIncludeLowercase] = useState(true);
  const [includeNumbers, setIncludeNumbers] = useState(true);
  const [includeSymbols, setIncludeSymbols] = useState(false);

  const generatePassword = () => {
    const upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const lowerCaseChars = "abcdefghijklmnopqrstuvwxyz";
    const numberChars = "0123456789";
    const symbolChars = "!@#$%^&*()_+-=[]{}|;:'\",.<>?/";

    let availableChars = "";
    if (includeUppercase) availableChars += upperCaseChars;
    if (includeLowercase) availableChars += lowerCaseChars;
    if (includeNumbers) availableChars += numberChars;
    if (includeSymbols) availableChars += symbolChars;

    if (availableChars === "") {
      alert("Please select at least one character set!");
      return;
    }

    let newPassword = "";
    for (let i = 0; i < passwordLength; i++) {
      const randomIndex = Math.floor(Math.random() * availableChars.length);
      newPassword += availableChars[randomIndex];
    }

    setPassword(newPassword);
  };

  return (
    <div className="container">
      <h1>Password Generator</h1>

      <div className="output-section">
        <input
          type="text"
          value={password}
          readOnly
          placeholder="Generated password"
          className="password-display"
        />
        <button
          onClick={() => navigator.clipboard.writeText(password)}
          className="copy-btn"
        >
          Copy
        </button>
      </div>

      <div className="controls">
        <label>
          Password Length:
          <input
            type="number"
            min="4"
            max="30"
            value={passwordLength}
            onChange={(e: any) => setPasswordLength(e.target.value)}
            className="length-input"
          />
        </label>

        <label>
          <input
            type="checkbox"
            checked={includeUppercase}
            onChange={() => setIncludeUppercase(!includeUppercase)}
          />
          Include Uppercase Letters
        </label>

        <label>
          <input
            type="checkbox"
            checked={includeLowercase}
            onChange={() => setIncludeLowercase(!includeLowercase)}
          />
          Include Lowercase Letters
        </label>

        <label>
          <input
            type="checkbox"
            checked={includeNumbers}
            onChange={() => setIncludeNumbers(!includeNumbers)}
          />
          Include Numbers
        </label>

        <label>
          <input
            type="checkbox"
            checked={includeSymbols}
            onChange={() => setIncludeSymbols(!includeSymbols)}
          />
          Include Symbols
        </label>

        <button className="generate-btn" onClick={generatePassword}>
          Generate Password
        </button>
      </div>

      <style jsx>{`
        .container {
          max-width: 500px;
          margin: 100px auto;
          padding: 20px;
          background-color: #f9fafb;
          border-radius: 10px;
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
          text-align: center;
        }

        h1 {
          margin-bottom: 20px;
          font-size: 28px;
          color: #333;
          font-weight: 600;
        }

        .output-section {
          display: flex;
          align-items: center;
          justify-content: center;
          margin-bottom: 30px;
        }

        .password-display {
          width: 70%;
          padding: 12px;
          font-size: 18px;
          border: 2px solid #e5e7eb;
          border-radius: 8px;
          margin-right: 10px;
          background-color: #f1f5f9;
        }

        .copy-btn {
          padding: 10px 15px;
          font-size: 16px;
          background-color: #3b82f6;
          color: white;
          border: none;
          border-radius: 8px;
          cursor: pointer;
          transition: background-color 0.3s ease;
        }

        .copy-btn:hover {
          background-color: #2563eb;
        }

        .controls {
          margin-top: 20px;
        }

        label {
          display: flex;
          align-items: center;
          margin-bottom: 12px;
          font-size: 16px;
          color: #555;
        }

        input[type="checkbox"] {
          margin-right: 10px;
          cursor: pointer;
        }

        .length-input {
          margin-left: 10px;
          width: 60px;
          padding: 8px;
          border-radius: 8px;
          border: 2px solid #e5e7eb;
          background-color: #f1f5f9;
        }

        .generate-btn {
          margin-top: 20px;
          padding: 12px 25px;
          background-color: #3b82f6;
          color: white;
          border: none;
          border-radius: 10px;
          font-size: 18px;
          cursor: pointer;
          transition: background-color 0.3s ease;
        }

        .generate-btn:hover {
          background-color: #2563eb;
        }
      `}</style>
    </div>
  );
}

Key Points:

  • We use useState to store the password, password length, and inclusion/exclusion of character types.

  • The handleGeneratePassword function dynamically creates a password based on the user’s input.

  • The UI consists of input fields for selecting the length of the password, checkboxes to include/exclude characters, and buttons to generate and copy the password.


Step 3: Adding Logic for Password Generation

The logic for password generation is simple but effective. Here's a breakdown of how it works:

  1. Character Sets: We define sets of characters for uppercase letters, lowercase letters, numbers, and symbols.

  2. Available Characters: Depending on user preferences (e.g., if they check "Include Uppercase Letters"), we concatenate the relevant character sets to form a pool of available characters.

  3. Random Selection: We randomly select characters from this pool for the password's length.

  4. Clipboard: We allow the user to copy the password to the clipboard using navigator.clipboard.writeText().


Step 4: Styling the UI

The password generator UI is simple but can be styled for a better look. Here's how the styling works:

  1. Container: We center the UI on the page using basic margin and text alignment.

  2. Output: The generated password is shown in a read-only text field with a "Copy" button next to it.

  3. Controls: Users can select options like password length and which character types to include, with clear labels and inputs.


Step 5: Enhancing the User Experience

You can improve the user experience by adding features like:

  • Password strength indicator: You can show a visual indicator of the password's strength based on its length and composition.

  • Error handling: Display a message if the user tries to generate a password without selecting any character type.

Example code for adding a password strength indicator:

const getPasswordStrength = () => {
  if (passwordLength < 6) return "Weak";
  if (passwordLength >= 6 && passwordLength < 10) return "Medium";
  return "Strong";
};

<div className="strength">Strength: {getPasswordStrength()}</div>


Step 6: Testing and Deploying the App

Once you’ve tested your password generator locally and confirmed that it works, you can deploy it using Vercel, which is optimized for Next.js apps.

  1. Install Vercel globally if you haven't already:

     npm i -g vercel
    
  2. Run the following command to deploy:

     vercel
    

    Follow the prompts, and your password generator will be live!


Conclusion
Building a random password generator with a UI in Next.js is a great way to improve your React and Next.js skills while creating something practical. You’ve learned how to:
  1. Set up a basic Next.js project.

  2. Create a UI with React components and state management.

  3. Implement the password generation logic.

  4. Style the UI and improve user experience.

Feel free to extend this project by adding more customization options, improving the UI, or integrating password strength analysis tools. Happy coding!

10
Subscribe to my newsletter

Read articles from ByteScrum Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ByteScrum Technologies
ByteScrum Technologies

Our company comprises seasoned professionals, each an expert in their field. Customer satisfaction is our top priority, exceeding clients' needs. We ensure competitive pricing and quality in web and mobile development without compromise.