Clone Website using HTML, CSS, and JavaScript

Clone Website using HTML, CSS, and JavaScript

Clone Website using HTML, CSS, and JavaScript

Introduction

Hello friends my name is Gautam and you all are welcome to today’s new blog post. Today we have created a beautiful project for you which will play a very important role in your coding journey because this project is very advanced and when you use it, this project will help you a lot.

Friends, you must have heard about Google’s chat bot Google Gemini and you must have used it too, but today we have created a clone of Google Gemini for you which is going to be very amazing. Friends, this is the complete chat bot of Google, Google Gemini’s bot. It works just like that and when you run this bot and add any prompt then you get its answer just like Google’s official chatbot due to which you do not know anything about the clone.

We have also used Api in making this google Gemini chat bot clone and have used html, CSS and JavaScript and I would like to tell you that when you use Api for the first time in your project then you have to face a lot of problems and you have to solve a lot of errors so let’s go now we are going to clone you step by step Let us explain the usual code.

HTML (index.html)

First of all we have to create the structure of our Google Chat Bot with the help of HTML which is a very easy task but we also need to keep in mind some things like which element we have to use at which place otherwise we may face problems later on so let us first explain the HTML code.

  • First of all we have added our title with the help of html <title>Gemini Chatbot</title>
  • To link the CSS to the HTML file we have used the HTML link tag <link rel=”style.cs” url=”style.cs”>
  • <body> This is a very important element because within this element we can write our HTML code and it also has a closing tag </body>
  • Friends, first of all we have created a header section with the help of HTML <header class=”header”> We also call it hero section.
  • Then in the header section, we have added a text with the <h1> heading of the HTML <h1 class=”title”>Hello, there</h1>
  • We have also added a paragraph in the header section which we have added in the <p> tag <p class=”subtitle”>How can I help you today?</p>
  • Friends, we have also added a suggestion list in our chat bot, for which we have created a separate <ul> section <ul class=”suggestive-list”>
  • Within the <ul> element, we have created a section using a list <li> <li class=”suggestive”>
  • then in the <li> element I have added my suggestion which is <h4> heading <h4 class=”text”>Help me plan a game night with my 5 best friends for under $100.</h4>
  • According to the message we have added in our suggestion box, we have added some icons which are exactly below our message <span class=”icon material-symbols-rounded”>draw</span>
  • We have created a chat list container in which all the chats you do with the bot will be displayed but this will only happen if you take the help of javascript <div class=”chat-list”></div>
  • In the footer we have created a typing area where user can type his suggestions <div class=”typing-area”>
  • We have created a section in the typing area with the help of <form> element, in which we have added different buttons and elements <form action=”#” class=”typing-form”>
  • Firstly we have created an input section in which input will be taken from the user like prompt <div class=”input-wrapper”>
  • input main hamne ek search baar ko create kiya hai <input type=”text” placeholder=”Enter a prompt here” class=”typing-input” required />
  • Then we have created a button to send the prompt <button id=”send-message-button” class=”icon material-symbols-rounded”>send</button>
  • We have created another section called action buttons <div class=”action-buttons”>
  • action button main hamne ek dark or light mode ke liye ek button banaya hai <span id=”theme-toggle-button” class=”icon material-symbols-rounded”>light_mode</span>
  • We have also created a delete button in which user can delete his prompt <span id=”delete-chat-button” class=”icon material-symbols-rounded”>delete</span>
  • We have also added a disclaimer at the end of the chat bot which we have added using the <p> element <p class=”disclaimer-text”>
				
					
  <title>Gemini Chatbot | Developergtm</title>
  <!-- Linking Google Fonts For Icons -->
  
  



  <header class="header">
    <!-- Header Greetings -->
    <h1 class="title">Hello, there</h1>
    <p class="subtitle">How can I help you today?</p>

    <!-- Suggestion list -->
    <ul class="suggestion-list">
      <li class="suggestion">
        <h4 class="text">Help me plan a game night with my 5 best friends for under $100.</h4>
        <span class="icon material-symbols-rounded">draw</span>
      </li>
      <li class="suggestion">
        <h4 class="text">What are the best tips to improve my public speaking skills?</h4>
        <span class="icon material-symbols-rounded">lightbulb</span>
      </li>
      <li class="suggestion">
        <h4 class="text">Can you help me find the latest news on web development?</h4>
        <span class="icon material-symbols-rounded">explore</span>
      </li>
      <li class="suggestion">
        <h4 class="text">Write JavaScript code to sum all elements in an array.</h4>
        <span class="icon material-symbols-rounded">code</span>
      </li>
    </ul>
  </header>

  <!-- Chat List / Container -->
  <div class="chat-list"></div>

  <!-- Typing Area -->
  <div class="typing-area">
    
      <div class="input-wrapper">
        
        <button id="send-message-button" class="icon material-symbols-rounded">send</button>
      </div>
      <div class="action-buttons">
        <span id="theme-toggle-button" class="icon material-symbols-rounded">light_mode</span>
        <span id="delete-chat-button" class="icon material-symbols-rounded">delete</span>
      </div>
    
    <p class="disclaimer-text">
      Gemini may display inaccurate info, including about people, so double-check its responses.
    </p>
  </div>

  



				
			

CSS (Style.css)

Friends, this code is of our CSS which is going to be very important for our chat bot because today we have created a clone website for you which is a chatbot and this chatbot should be completely real i.e. it should not look like a clone to any user, so it has to be designed properly like color combination etc. Therefore, CSS has a great contribution in it, so let us explain the CSS code.

  • To ensure that our chat bot does not look like a clone, we have used the same font which is used in the real bot font-family: “Poppins”, font-only;
  • We have used this color in the background of the chat bot background: var(–primary-color);
  • We have kept max-width: 980px; in header, .chat-list, .message, .typing-form; you can keep it as per your requirement
  • The header section is separated from the margin-top with margin-top: 6rem; and padding: 1rem; and overflow-x: hidden; so that it doesn’t overflow the content
  • We have kept the font size of the butterfly added in the header as font-size: 3rem; and background-clip: text; so that the text matches the background
  • In the bottom text of the header we have used mixed color background: linear-gradient(right, #4285f4, #d96570);
  • We have kept the font size of the header section text at 6rem
  • We have given the width of the suggestions list as width: 100%;, the bullet points are given as none list-style: none; and gap: 1.25rem;
  • We have also used hover effect in our suggestion list in which when the user hovers, he will see this color background: var(–secondary-hover-color);
  • As per the suggestion, we have added the icon in the suggestion box whose width: 42px; and the height is also kept the same so that there is no problem in rounding it border-radius: 50%;
  • To center the icon we have used justify-content: center; or align-items: center; so that the icon is centered but to make it work you will have to use display: flex;
  • We have added white color in the background of the icon background: var(–primary-color);
  • In the chat list we have used a little padding padding: 2rem 1rem 12rem; along with main overflow-y: auto; and most importantly scrollbar-color: #999 transparent;
  • Now let’s talk about the typing area, we have kept it position: fixed; so that when the user scrolls, the typing area does not move up and down
  • For typing area we have kept width: 100%; and set left to 0 and top to 0 and used padding padding: 1rem;
				
					/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&amp;display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}

:root {
  /* Dark mode colors */
  --text-color: #E3E3E3;
  --subheading-color: #828282;
  --placeholder-color: #A6A6A6;
  --primary-color: #242424;
  --secondary-color: #383838;
  --secondary-hover-color: #444;
}

.light_mode {
  /* Light mode colors */
  --text-color: #222;
  --subheading-color: #A0A0A0;
  --placeholder-color: #6C6C6C;
  --primary-color: #FFF;
  --secondary-color: #E9EEF6;
  --secondary-hover-color: #DBE1EA;
}

body {
  background: var(--primary-color);
}

.header, .chat-list .message, .typing-form {
  margin: 0 auto;
  max-width: 980px;
}

.header {
  margin-top: 6vh;
  padding: 1rem;
  overflow-x: hidden;
}

body.hide-header .header {
  margin: 0;
  display: none;
}

.header :where(.title, .subtitle) {
  color: var(--text-color);
  font-weight: 500;
  line-height: 4rem;
}

.header .title {
  width: fit-content;
  font-size: 3rem;
  background-clip: text;
  background: linear-gradient(to right, #4285f4, #d96570);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.header .subtitle {
  font-size: 2.6rem;
  color: var(--subheading-color);
}

.suggestion-list {
  width: 100%;
  list-style: none;
  display: flex;
  gap: 1.25rem;
  margin-top: 9.5vh;
  overflow: hidden;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.suggestion-list .suggestion {
  cursor: pointer;
  padding: 1.25rem;
  width: 222px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  border-radius: 0.75rem;
  justify-content: space-between;
  background: var(--secondary-color);
  transition: 0.2s ease;
}

.suggestion-list .suggestion:hover {
  background: var(--secondary-hover-color);
}

.suggestion-list .suggestion :where(.text, .icon) {
  font-weight: 400;
  color: var(--text-color);
}

.suggestion-list .suggestion .icon {
  width: 42px;
  height: 42px;
  display: flex;
  font-size: 1.3rem;
  margin-top: 2.5rem;
  align-self: flex-end;
  align-items: center;
  border-radius: 50%;
  justify-content: center;
  color: var(--text-color);
  background: var(--primary-color);
}

.chat-list {
  padding: 2rem 1rem 12rem;
  max-height: 100vh;
  overflow-y: auto;
  scrollbar-color: #999 transparent;
}

.chat-list .message.incoming {
  margin-top: 1.5rem;
}

.chat-list .message .message-content {
  display: flex;
  gap: 1.5rem;
  width: 100%;
  align-items: center;
}

.chat-list .message .text {
  color: var(--text-color);
  white-space: pre-wrap;
}

.chat-list .message.error .text {
  color: #e55865;
}

.chat-list .message.loading .text {
  display: none;
}

.chat-list .message .avatar {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 50%;
  align-self: flex-start;
}

.chat-list .message.loading .avatar {
  animation: rotate 3s linear infinite;
}

@keyframes rotate {
  100% {
    transform: rotate(360deg);
  }
}

.chat-list .message .icon {
  color: var(--text-color);
  cursor: pointer;
  height: 35px;
  width: 35px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  font-size: 1.25rem;
  margin-left: 3.5rem;
  visibility: hidden;
}

.chat-list .message .icon.hide {
  visibility: hidden;
}

.chat-list .message:not(.loading, .error):hover .icon:not(.hide){
  visibility: visible;
}

.chat-list .message .icon:hover {
  background: var(--secondary-hover-color);
}

.chat-list .message .loading-indicator {
  display: none;
  gap: 0.8rem;
  width: 100%;
  flex-direction: column;
}

.chat-list .message.loading .loading-indicator {
  display: flex;
}

.chat-list .message .loading-indicator .loading-bar {
  height: 11px;
  width: 100%;
  border-radius: 0.135rem;
  background-position: -800px 0;
  background: linear-gradient(to right, #4285f4, var(--primary-color), #4285f4);
  animation: loading 3s linear infinite;
}

.chat-list .message .loading-indicator .loading-bar:last-child {
  width: 70%;
}

@keyframes loading {
  0% {
    background-position: -800px 0;
  }

  100% {
    background-position: 800px 0;
  }
}

.typing-area {
  position: fixed;
  width: 100%;
  left: 0;
  bottom: 0;
  padding: 1rem;
  background: var(--primary-color);
}

.typing-area :where(.typing-form, .action-buttons) {
  display: flex;
  gap: 0.75rem;
}

.typing-form .input-wrapper {
  width: 100%;
  height: 56px;
  display: flex;
  position: relative;
}

.typing-form .typing-input {
  height: 100%;
  width: 100%;
  border: none;
  outline: none;
  resize: none;
  font-size: 1rem;
  color: var(--text-color);
  padding: 1.1rem 4rem 1.1rem 1.5rem;
  border-radius: 100px;
  background: var(--secondary-color);
}

.typing-form .typing-input:focus {
  background: var(--secondary-hover-color);
}

.typing-form .typing-input::placeholder {
  color: var(--placeholder-color);
}

.typing-area .icon {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  cursor: pointer;
  border-radius: 50%;
  display: flex;
  font-size: 1.4rem;
  color: var(--text-color);
  align-items: center;
  justify-content: center;
  background: var(--secondary-color);
  transition: 0.2s ease;
}

.typing-area .icon:hover {
  background: var(--secondary-hover-color);
}

.typing-form #send-message-button {
  position: absolute;
  right: 0;
  outline: none;
  border: none;
  transform: scale(0);
  background: transparent;
  transition: transform 0.2s ease;
}

.typing-form .typing-input:valid ~ #send-message-button {
  transform: scale(1);
}

.typing-area .disclaimer-text {
  text-align: center;
  font-size: 0.85rem;
  margin-top: 1rem;
  color: var(--placeholder-color);
}

/* Responsive media query code for small screen */
@media (max-width: 768px) {
  .header :is(.title, .subtitle) {
    font-size: 2rem;
    line-height: 2.6rem;
  }

  .header .subtitle {
    font-size: 1.7rem;
  }

  .typing-area :where(.typing-form, .action-buttons) {
    gap: 0.4rem;
  }

  .typing-form .input-wrapper {
    height: 50px;
  }

  .typing-form .typing-input {
    padding: 1.1rem 3.5rem 1.1rem 1.2rem;
  }

  .typing-area .icon {
    height: 50px;
    width: 50px;
  }

  .typing-area .disclaimer-text {
    font-size: 0.75rem;
    margin-top: 0.5rem;
  }
}
				
			

Javascript (Script.js)

This code is of our Javascript, without which this chat bot is of no use because without Javascript you cannot use the prompt in this chat bot. When the user sends his prompt, what answer should he get, all this happens through Javascript and API. You can create a chat bot without Javascript, but it will not work. For this you need to have knowledge of Javascript and API, so let’s understand some Javascript code now.

  • First of all you have to check whether you have added the name of your id correctly or not, then you have to add them in javascript exactly like this const typingForm = document.querySelector(“.typing-form”);
  • We have added important Eid in this way
  • Friends, we have used API in our chat bot, so you have to paste your API here. custom API_Key = “paste-your-api-key”;
  • To save the chat of chat bot we have used const loadDataFromLocalstorage with the help of which we have saved the chat const savedChats = localStorage.getItem(“saved-chats”);
  • And whatever theme you use in your chat bot, you will get its theme in your local storage const isLightMode = (localStorage.getItem(“themeColor”) === “light_mode”);
  • If you want, you can clear the chat or even restore itinnerHTML = savedChats || ”; document.body.classList.toggle(“hide-header”, savedChats);

Friends, I would like to tell you that we have used a lot of javascript but we have explained some important code to you. We have added everything in this project like saving the chat list, you can clear it or even restore it because this chat is saved in your local storage and along with it the light or dark mode etc. you can check all this in the code.

				
					const typingForm = document.querySelector(".typing-form");
const chatContainer = document.querySelector(".chat-list");
const suggestions = document.querySelectorAll(".suggestion");
const toggleThemeButton = document.querySelector("#theme-toggle-button");
const deleteChatButton = document.querySelector("#delete-chat-button");

// State variables
let userMessage = null;
let isResponseGenerating = false;

// API configuration
const API_KEY = "PASTE-YOUR-API-KEY"; // Your API key here
const API_URL = `https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key=${API_KEY}`;

// Load theme and chat data from local storage on page load
const loadDataFromLocalstorage = () =&gt; {
  const savedChats = localStorage.getItem("saved-chats");
  const isLightMode = (localStorage.getItem("themeColor") === "light_mode");

  // Apply the stored theme
  document.body.classList.toggle("light_mode", isLightMode);
  toggleThemeButton.innerText = isLightMode ? "dark_mode" : "light_mode";

  // Restore saved chats or clear the chat container
  chatContainer.innerHTML = savedChats || '';
  document.body.classList.toggle("hide-header", savedChats);

  chatContainer.scrollTo(0, chatContainer.scrollHeight); // Scroll to the bottom
}

// Create a new message element and return it
const createMessageElement = (content, ...classes) =&gt; {
  const div = document.createElement("div");
  div.classList.add("message", ...classes);
  div.innerHTML = content;
  return div;
}

// Show typing effect by displaying words one by one
const showTypingEffect = (text, textElement, incomingMessageDiv) =&gt; {
  const words = text.split(' ');
  let currentWordIndex = 0;

  const typingInterval = setInterval(() =&gt; {
    // Append each word to the text element with a space
    textElement.innerText += (currentWordIndex === 0 ? '' : ' ') + words[currentWordIndex++];
    incomingMessageDiv.querySelector(".icon").classList.add("hide");

    // If all words are displayed
    if (currentWordIndex === words.length) {
      clearInterval(typingInterval);
      isResponseGenerating = false;
      incomingMessageDiv.querySelector(".icon").classList.remove("hide");
      localStorage.setItem("saved-chats", chatContainer.innerHTML); // Save chats to local storage
    }
    chatContainer.scrollTo(0, chatContainer.scrollHeight); // Scroll to the bottom
  }, 75);
}

// Fetch response from the API based on user message
const generateAPIResponse = async (incomingMessageDiv) =&gt; {
  const textElement = incomingMessageDiv.querySelector(".text"); // Getting text element

  try {
    // Send a POST request to the API with the user's message
    const response = await fetch(API_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ 
        contents: [{ 
          role: "user", 
          parts: [{ text: userMessage }] 
        }] 
      }),
    });

    const data = await response.json();
    if (!response.ok) throw new Error(data.error.message);

    // Get the API response text and remove asterisks from it
    const apiResponse = data?.candidates[0].content.parts[0].text.replace(/\*\*(.*?)\*\*/g, '$1');
    showTypingEffect(apiResponse, textElement, incomingMessageDiv); // Show typing effect
  } catch (error) { // Handle error
    isResponseGenerating = false;
    textElement.innerText = error.message;
    textElement.parentElement.closest(".message").classList.add("error");
  } finally {
    incomingMessageDiv.classList.remove("loading");
  }
}

// Show a loading animation while waiting for the API response
const showLoadingAnimation = () =&gt; {
  const html = `<div class="message-content">
                  <img decoding="async" class="avatar" src="images/gemini.svg" alt="Gemini avatar">
                  <p class="text"></p>
                  <div class="loading-indicator">
                    <div class="loading-bar"></div>
                    <div class="loading-bar"></div>
                    <div class="loading-bar"></div>
                  </div>
                </div>
                <span class="icon material-symbols-rounded">content_copy</span>`;

  const incomingMessageDiv = createMessageElement(html, "incoming", "loading");
  chatContainer.appendChild(incomingMessageDiv);

  chatContainer.scrollTo(0, chatContainer.scrollHeight); // Scroll to the bottom
  generateAPIResponse(incomingMessageDiv);
}

// Copy message text to the clipboard
const copyMessage = (copyButton) =&gt; {
  const messageText = copyButton.parentElement.querySelector(".text").innerText;

  navigator.clipboard.writeText(messageText);
  copyButton.innerText = "done"; // Show confirmation icon
  setTimeout(() =&gt; copyButton.innerText = "content_copy", 1000); // Revert icon after 1 second
}

// Handle sending outgoing chat messages
const handleOutgoingChat = () =&gt; {
  userMessage = typingForm.querySelector(".typing-input").value.trim() || userMessage;
  if(!userMessage || isResponseGenerating) return; // Exit if there is no message or response is generating

  isResponseGenerating = true;

  const html = `<div class="message-content">
                  <img decoding="async" class="avatar" src="images/user.avif" alt="User avatar">
                  <p class="text"></p>
                </div>`;

  const outgoingMessageDiv = createMessageElement(html, "outgoing");
  outgoingMessageDiv.querySelector(".text").innerText = userMessage;
  chatContainer.appendChild(outgoingMessageDiv);
  
  typingForm.reset(); // Clear input field
  document.body.classList.add("hide-header");
  chatContainer.scrollTo(0, chatContainer.scrollHeight); // Scroll to the bottom
  setTimeout(showLoadingAnimation, 500); // Show loading animation after a delay
}

// Toggle between light and dark themes
toggleThemeButton.addEventListener("click", () =&gt; {
  const isLightMode = document.body.classList.toggle("light_mode");
  localStorage.setItem("themeColor", isLightMode ? "light_mode" : "dark_mode");
  toggleThemeButton.innerText = isLightMode ? "dark_mode" : "light_mode";
});

// Delete all chats from local storage when button is clicked
deleteChatButton.addEventListener("click", () =&gt; {
  if (confirm("Are you sure you want to delete all the chats?")) {
    localStorage.removeItem("saved-chats");
    loadDataFromLocalstorage();
  }
});

// Set userMessage and handle outgoing chat when a suggestion is clicked
suggestions.forEach(suggestion =&gt; {
  suggestion.addEventListener("click", () =&gt; {
    userMessage = suggestion.querySelector(".text").innerText;
    handleOutgoingChat();
  });
});

// Prevent default form submission and handle outgoing chat
typingForm.addEventListener("submit", (e) =&gt; {
  e.preventDefault(); 
  handleOutgoingChat();
});

loadDataFromLocalstorage();
				
			

Output:

Disclaimer: The code provided in this post is sourced from GitHub and is distributed under the MIT License. All credits for the original code go to the respective owner. We have shared this code for educational purposes only. Please refer to the original repository for detailed information and any additional usage rights or restrictions.

Online Quiz System using Java With Source Code Graphical User Interface [GUI] Introduction: The online Quiz Program is a Java-based desktop application …

Clone Website using HTML, CSS, and JavaScript Introduction Hello friends my name is Gautam and you all are welcome to today’s new …

Travel Booking App UI Clone Using HTML, CSS, and JavaScript Introduction Hello friends, you all are welcome to this new blog post. …

Custom Music Player with Playlist Using JavaScript Introduction Hello friends , welcome to another new blog. Hope you all are doing good. …

Get Huge Discounts
More Python Projects