Close Menu

    Subscribe to Updates

    Get the latest creative post from Developer Goutam about Web Development & design.

    What's Hot

    Simple Startup Landing Page Using HTML CSS

    September 29, 2024

    Responsive Google Gemini Clone Using HTML CSS JavaScript

    September 19, 2024

    Password Generator Using HTML CSS JS

    September 17, 2024
    Facebook X (Twitter) Instagram
    • Terms & Conditions
    • Disclaimer
    • Privacy Policy
    • Contact Me
    • About Us
    Instagram YouTube Telegram
    DevGoutam
    • Home
    • Projects
    • Contact
    • web development

      Simple Startup Landing Page Using HTML CSS

      September 29, 2024

      Responsive Google Gemini Clone Using HTML CSS JavaScript

      September 19, 2024

      Password Generator Using HTML CSS JS

      September 17, 2024

      Foody Restaurant Website Using HTML CSS

      September 13, 2024

      Coffee Shop Website Using HTML CSS

      September 10, 2024
    DevGoutam
    Home»Google Gemini Clone»Responsive Google Gemini Clone Using HTML CSS JavaScript
    Google Gemini Clone

    Responsive Google Gemini Clone Using HTML CSS JavaScript

    Developer GoutamBy Developer GoutamSeptember 19, 2024No Comments12 Mins Read
    Facebook Twitter Pinterest LinkedIn Tumblr WhatsApp Email
    Responsive Google Gemini Clone Using HTML CSS JavaScript

    Responsive Google Gemini Clone Using HTML CSS JavaScript With Free Source Code

    Introduction

    Hello coders, Today in this article we’ve made a Responsive Google Gemini Clone Using HTML CSS JavaScript. This responsive chat bot is a clone of google Gemini. In this we’ll learn that how to create this type of project. 

    In this era of artificial intelligence everyone aware about AI chat bot. Basically AI chat bot’s are the tool which provides us information about any topic or any particular thing. We’ve build this responsive google Gemini clone Using HTML CSS and JavaScript. In this project you’ll get to know that how API works. 

    To create this project, we’ve used HTML CSS and JS. Like all other projects HTML is used to create the basic structure of the clone and then CSS is applied to give styling to the project. Lastly, JavaScript is added to provide functionality to our project. If you also want to create advance type of project then you should definitely check out our website. We’ve much more stuff for you guys. 

    Let’s see the code.


    Password Generator Using HTML CSS JS

    index.html

    This is our HTML Code. Using this code we’ve developed the basic structure of our website. The code starts with a tag  doctype which define that it is a HTML document. After that html tag specifies the language as English. 

    The <head> contains UTF-8 character set and a viewport meta tag to make the page adapt to all screen sizes. “Gemini Chatbot” appears as the page title, and the design includes custom icons from Google Fonts.

    The <body> starts with a header that welcomes users and shows a list of questions the chatbot can help with. These cover topics such as game night planning public speaking improvement, web development news updates, and JavaScript coding. Each topic has a matching icon next to it.

    Below the header, you’ll find a chat area and a section to type in your own questions. The design has buttons to send messages, change themes, and erase chats. A notice warns users that the chatbot might give wrong information. The page also connects to separate CSS and JavaScript files to control its look and how it works.

    				
    					<!DOCTYPE html>
    <!-- Coding By CodingNepal - www.codingnepalweb.com -->
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Gemini Chatbot | CodingNepal</title><link rel="preload" as="image" imagesrcset="https://developergoutam.com/wp-content/uploads/2024/09/post19-768x376.png 768w, https://developergoutam.com/wp-content/uploads/2024/09/post19-300x147.png 300w, https://developergoutam.com/wp-content/uploads/2024/09/post19-1024x502.png 1024w, https://developergoutam.com/wp-content/uploads/2024/09/post19-1536x753.png 1536w, https://developergoutam.com/wp-content/uploads/2024/09/post19-150x73.png 150w, https://developergoutam.com/wp-content/uploads/2024/09/post19-450x220.png 450w, https://developergoutam.com/wp-content/uploads/2024/09/post19-1200x588.png 1200w, https://developergoutam.com/wp-content/uploads/2024/09/post19.png 1837w" imagesizes="(max-width: 749px) 100vw, 749px" /><link rel="preload" as="font" href="https://developergoutam.com/wp-content/themes/smart-mag/css/icons/fonts/ts-icons.woff2?v3.0" type="font/woff2" crossorigin="anonymous" />
      <!-- Linking Google Fonts For Icons -->
      <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0,0" />
      <link rel="stylesheet" href="style.css">
    </head>
    <body>
      <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">
        <form action="#" class="typing-form">
          <div class="input-wrapper">
            <input type="text" placeholder="Enter a prompt here" class="typing-input" required />
            <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>
        </form>
        <p class="disclaimer-text">
          Gemini may display inaccurate info, including about people, so double-check its responses.
        </p>
      </div>
    
      <script src="script.js"></script>
    
    </body>
    </html>
    				
    			

    styles.css

    This is our CSS code. It starts by importing google font Poppins. Then it resets the margin, padding and  some other properties using universal selector. The :root tag is used to define some variable in the code so that they can be used later in code. For light mode some variables are created. 

    A background color is given to body using variable. Margin and width is given to header, chat-list, message and typing form. After that we styled all the other tags of the HTML like header, chat-list and more. Inside the .header, a gradient is applied to the title text, creating a colorful, eye-catching effect, while the subtitle uses a more subdued color.

    After that we styled suggestion list. Suggestion list is styled horizontally scrollable. A hover effect is also added on the cards of suggestion list to make it more interactive. Some icons are added into the suggestion list.

    Messages in the chat list have different styles for incoming messages and errors. All the elements of chat list are styled according to their importance and you can see that in the code below. Loading animations are defined by the keyframes like rotate and loading and a feedback option is also styled when messages are being processed. 

    In the bottom typing area is fixed, makes sure its visible to user type message. Input fields and icons within the form adjust in size and appearance based on user interaction. At the end media queries are used to make our project responsive for smaller screens.

    This is all about our CSS code.

    				
    					/* Import Google Font - Poppins */
    @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&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;
      }
    }
    				
    			

    script.js

    This is JavaScript code for the chatbot: message processing, change of theme, and interaction with an API. First, it selects some key HTML elements using document.querySelector and document.querySelectorAll. There are typed forms, the container for the chat, suggestions, and buttons to change the theme and remove chats.

    To store the user’s message, I have used state variables, together with one flag that tells whether the chatbot is generating at some point. The required API key is stored in API_KEY along with setting API_URL to use the language model API.

    loadDataFromLocalstorage Loads saved chats and the selected theme when page loads from local storage. It applies the theme, restoring saved chats that scroll the chat container to the bottom.

    The function createMessageElement dynamically creates message elements in a chat. It accepts a piece of message content and optional CSS classes and appends the element at the bottom of the chat container.

    We implement the function called showTypingEffect. The function implements a real-time typing effect in which words are typed one by one. The function uses an interval so that after each word, it displays the word and updates the chat when all words have been displayed.

    In reply to the user message shared above, it fetches the response of an API. Then, by sending a POST request to the API, its response blinks to create a typing effect. The errors are displayed as the error message in the chat.

    The showLoadingAnimation function appends a loading message with blink bars for creating a loading animation until when the response is ready to be shown.

    There are also several functions in the class: copyMessage for copying chat text to the clipboard, handleOutgoingChat for sending user messages, listeners of toggling the theme, deleting chats, and suggestion click event.

    And at last, on page load, there is loadDataFromLocalstorage function running.

    				
    					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 = () => {
      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) => {
      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) => {
      const words = text.split(' ');
      let currentWordIndex = 0;
    
      const typingInterval = setInterval(() => {
        // 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) => {
      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 = () => {
      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 onClick="copyMessage(this)" 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) => {
      const messageText = copyButton.parentElement.querySelector(".text").innerText;
    
      navigator.clipboard.writeText(messageText);
      copyButton.innerText = "done"; // Show confirmation icon
      setTimeout(() => copyButton.innerText = "content_copy", 1000); // Revert icon after 1 second
    }
    
    // Handle sending outgoing chat messages
    const handleOutgoingChat = () => {
      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.jpg" 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", () => {
      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", () => {
      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 => {
      suggestion.addEventListener("click", () => {
        userMessage = suggestion.querySelector(".text").innerText;
        handleOutgoingChat();
      });
    });
    
    // Prevent default form submission and handle outgoing chat
    typingForm.addEventListener("submit", (e) => {
      e.preventDefault(); 
      handleOutgoingChat();
    });
    
    loadDataFromLocalstorage();
    				
    			
    DOWNLOAD CODE
    google gemini clone using html css js project using html css js web development
    Share. Facebook Twitter Pinterest LinkedIn Tumblr WhatsApp Email
    Developer Goutam
    Developer Goutam
    • Website

    Related Posts

    Simple Startup Landing Page Using HTML CSS

    September 29, 2024

    Password Generator Using HTML CSS JS

    September 17, 2024

    Foody Restaurant Website Using HTML CSS

    September 13, 2024

    Coffee Shop Website Using HTML CSS

    September 10, 2024

    Responsive Hoodie Store Website Using HTML CSS

    September 7, 2024

    Personal Portfolio Using HTML CSS

    September 5, 2024
    Add A Comment
    Leave A Reply Cancel Reply

    Follow Me
    • Instagram
    • YouTube
    • Telegram
    Our Post

    Simple Startup Landing Page Using HTML CSS

    September 29, 2024

    Responsive Google Gemini Clone Using HTML CSS JavaScript

    September 19, 2024

    Password Generator Using HTML CSS JS

    September 17, 2024

    Foody Restaurant Website Using HTML CSS

    September 13, 2024

    Subscribe to Updates

    Get the latest creative post from Developer Goutam about Web Development & design.

    Instagram YouTube Telegram
    • Home
    • Privacy Policy
    • Disclaimer
    • About Us
    • Terms & Conditions
    • Contact Me
    © 2025 Developer Goutam. Designed by Goutam Prajapat.

    Type above and press Enter to search. Press Esc to cancel.