How to Create a Google Gemini AI Chatbot Using HTML, CSS, and JavaScript 2025

How to Create a Google Gemini AI Chatbot Using HTML, CSS, and JavaScript

Introduction

Google Gemini AI is one of the most powerful AI chatbots, offering human-like responses,

Features of the Gemini Chatbot

βœ… Google Gemini API Integration
βœ… Best UI with Hover Effects
βœ… Dark Mode & Light Mode
βœ… Voice Input & AI Voice Output
βœ… Chat History Storage
βœ… Multi-Language Support
βœ… Security & Customization Options


Step 1: Get Google Gemini API Key

To integrate Google Gemini AI, you need an API key.

πŸ”Ή Go to Google AI Console: Google AI Console
πŸ”Ή Sign in with Google Account
πŸ”Ή Create a New Project
πŸ”Ή Enable Gemini API
πŸ”Ή Generate API Key & Copy It


Step 2: Set Up Your Project Files

Create the following files in your project folder:
πŸ“Œ index.html – The chatbot interface
πŸ“Œ style.css – The chatbot styling
πŸ“Œ script.js – JavaScript for API integration


How to Create a Google Gemini AI Chatbot Using HTML, CSS, and JavaScript 2025
How to Create a Google Gemini AI Chatbot Using HTML, CSS, and JavaScript 2025

Step 3: Create HTML Structure (index.html)

Here is the basic HTML structure for the chatbot UI:


    <!DOCTYPE html>
<!-- Coding By CodingNepal - youtube.com/@codingnepal -->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Gemini Chatbot | CodingNepal</title>
    <!-- Linking Google Fonts For Icons -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@32,400,0,0" />
    <link rel="stylesheet" href="style.css" />
    <style>
        /* 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 theme colors */
  --text-color: #edf3ff;
  --subheading-color: #97a7ca;
  --placeholder-color: #c3cdde;
  --primary-color: #101623;
  --secondary-color: #283045;
  --secondary-hover-color: #333e58;
  --scrollbar-color: #626a7f;
}
body.light-theme {
  /* Light theme colors */
  --text-color: #090c13;
  --subheading-color: #7b8cae;
  --placeholder-color: #606982;
  --primary-color: #f3f7ff;
  --secondary-color: #dce6f9;
  --secondary-hover-color: #d2ddf2;
  --scrollbar-color: #a2aac2;
}
body {
  color: var(--text-color);
  background: var(--primary-color);
}
.container {
  overflow-y: auto;
  padding: 32px 0 60px;
  height: calc(100vh - 127px);
  scrollbar-color: var(--scrollbar-color) transparent;
}
.container :where(.app-header, .suggestions, .message, .prompt-wrapper) {
  position: relative;
  margin: 0 auto;
  width: 100%;
  padding: 0 20px;
  max-width: 990px;
}
.container .app-header {
  margin-top: 3vh;
}
.app-header .heading {
  width: fit-content;
  font-size: 3rem;
  background: linear-gradient(to right, #1d7efd, #8f6fff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
.app-header .sub-heading {
  font-size: 2.6rem;
  margin-top: -5px;
  color: var(--subheading-color);
}
.container .suggestions {
  width: 100%;
  list-style: none;
  display: flex;
  gap: 15px;
  margin-top: 9.5vh;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
body.chats-active .container :where(.app-header, .suggestions) {
  display: none;
}
.suggestions .suggestions-item {
  cursor: pointer;
  padding: 18px;
  width: 228px;
  flex-shrink: 0;
  display: flex;
  scroll-snap-align: center;
  flex-direction: column;
  align-items: flex-end;
  border-radius: 12px;
  justify-content: space-between;
  background: var(--secondary-color);
  transition: 0.3s ease;
}
.suggestions .suggestions-item:hover {
  background: var(--secondary-hover-color);
}
.suggestions .suggestions-item .text {
  font-size: 1.1rem;
}
.suggestions .suggestions-item .icon {
  width: 45px;
  height: 45px;
  display: flex;
  font-size: 1.4rem;
  margin-top: 35px;
  align-self: flex-end;
  align-items: center;
  border-radius: 50%;
  justify-content: center;
  color: #1d7efd;
  background: var(--primary-color);
}
.suggestions .suggestions-item:nth-child(2) .icon {
  color: #28a745;
}
.suggestions .suggestions-item:nth-child(3) .icon {
  color: #ffc107;
}
.suggestions .suggestions-item:nth-child(4) .icon {
  color: #6f42c1;
}
.container .chats-container {
  display: flex;
  gap: 20px;
  flex-direction: column;
}
.chats-container .message {
  display: flex;
  gap: 11px;
  align-items: center;
}
.chats-container .message .avatar {
  width: 43px;
  height: 43px;
  flex-shrink: 0;
  align-self: flex-start;
  border-radius: 50%;
  padding: 6px;
  margin-right: -7px;
  background: var(--secondary-color);
  border: 1px solid var(--secondary-hover-color);
}
.chats-container .message.loading .avatar {
  animation: rotate 3s linear infinite;
}
@keyframes rotate {
  100% {
    transform: rotate(360deg);
  }
}
.chats-container .message .message-text {
  padding: 3px 16px;
  word-wrap: break-word;
  white-space: pre-line;
}
.chats-container .bot-message {
  margin: 9px auto;
}
.chats-container .user-message {
  flex-direction: column;
  align-items: flex-end;
}
.chats-container .user-message .message-text {
  padding: 12px 16px;
  max-width: 75%;
  background: var(--secondary-color);
  border-radius: 13px 13px 3px 13px;
}
.chats-container .user-message .img-attachment {
  margin-top: -7px;
  width: 50%;
  border-radius: 13px 3px 13px 13px;
}
.chats-container .user-message .file-attachment {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 10px;
  margin-top: -7px;
  border-radius: 13px 3px 13px 13px;
  background: var(--secondary-color);
}
.chats-container .user-message .file-attachment span {
  color: #1d7efd;
}
.container .prompt-container {
  position: fixed;
  width: 100%;
  left: 0;
  bottom: 0;
  padding: 16px 0;
  background: var(--primary-color);
}
.prompt-container :where(.prompt-wrapper, .prompt-form, .prompt-actions) {
  display: flex;
  gap: 12px;
  height: 56px;
  align-items: center;
}
.prompt-container .prompt-form {
  height: 100%;
  width: 100%;
  border-radius: 130px;
  background: var(--secondary-color);
}
.prompt-form .prompt-input {
  width: 100%;
  height: 100%;
  background: none;
  outline: none;
  border: none;
  font-size: 1rem;
  color: var(--text-color);
  padding-left: 24px;
}
.prompt-form .prompt-input::placeholder {
  color: var(--placeholder-color);
}
.prompt-wrapper button {
  width: 56px;
  height: 100%;
  flex-shrink: 0;
  cursor: pointer;
  border-radius: 50%;
  font-size: 1.4rem;
  border: none;
  color: var(--text-color);
  background: var(--secondary-color);
  transition: 0.3s ease;
}
.prompt-wrapper :is(button:hover, #cancel-file-btn, .file-icon) {
  background: var(--secondary-hover-color);
}
.prompt-form .prompt-actions {
  gap: 5px;
  margin-right: 7px;
}
.prompt-wrapper .prompt-form :where(.file-upload-wrapper, button, img) {
  position: relative;
  height: 45px;
  width: 45px;
}
.prompt-form .prompt-actions #send-prompt-btn {
  color: #fff;
  display: none;
  background: #1d7efd;
}
.prompt-form .prompt-input:valid~.prompt-actions #send-prompt-btn {
  display: block;
}
.prompt-form #send-prompt-btn:hover {
  background: #0264e3;
}
.prompt-form .file-upload-wrapper :where(button, img) {
  display: none;
  border-radius: 50%;
  object-fit: cover;
  position: absolute;
}
.prompt-form .file-upload-wrapper.active #add-file-btn {
  display: none;
}
.prompt-form .file-upload-wrapper #add-file-btn,
.prompt-form .file-upload-wrapper.active.img-attached img,
.prompt-form .file-upload-wrapper.active.file-attached .file-icon,
.prompt-form .file-upload-wrapper.active:hover #cancel-file-btn {
  display: block;
}
.prompt-form :is(#stop-response-btn:hover, #cancel-file-btn) {
  color: #d62939;
}
.prompt-wrapper .prompt-form .file-icon {
  color: #1d7efd;
}
.prompt-form #stop-response-btn,
body.bot-responding .prompt-form .file-upload-wrapper {
  display: none;
}
body.bot-responding .prompt-form #stop-response-btn {
  display: block;
}
.prompt-container .disclaimer-text {
  font-size: 0.9rem;
  text-align: center;
  padding: 16px 20px 0;
  color: var(--placeholder-color);
}
/* Responsive media query code for small screens */
@media (max-width: 768px) {
  .container {
    padding: 20px 0 100px;
  }
  .app-header :is(.heading, .sub-heading) {
    font-size: 2rem;
    line-height: 1.4;
  }
  .app-header .sub-heading {
    font-size: 1.7rem;
  }
  .container .chats-container {
    gap: 15px;
  }
  .chats-container .bot-message {
    margin: 4px auto;
  }
  .prompt-container :where(.prompt-wrapper, .prompt-form, .prompt-actions) {
    gap: 8px;
    height: 53px;
  }
  .prompt-container button {
    width: 53px;
  }
  .prompt-form :is(.file-upload-wrapper, button, img) {
    height: 42px;
    width: 42px;
  }
  .prompt-form .prompt-input {
    padding-left: 20px;
  }
  .prompt-form .file-upload-wrapper.active #cancel-file-btn {
    opacity: 0;
  }
  .prompt-wrapper.hide-controls :where(#theme-toggle-btn, #delete-chats-btn) {
    display: none;
  }
}
    </style>
  </head>
  <body>
    <div class="container">
      <!-- App Header -->
      <header class="app-header">
        <h1 class="heading">Hello, there</h1>
        <h4 class="sub-heading">How can I help you today?</h4>
      </header>
      <!-- Suggestions List -->
      <ul class="suggestions">
        <li class="suggestions-item">
          <p class="text">Design a home office setup for remote work under $500.</p>
          <span class="icon material-symbols-rounded">draw</span>
        </li>
        <li class="suggestions-item">
          <p class="text">How can I level up my web development expertise in 2025?</p>
          <span class="icon material-symbols-rounded">lightbulb</span>
        </li>
        <li class="suggestions-item">
          <p class="text">Suggest some useful tools for debugging JavaScript code.</p>
          <span class="icon material-symbols-rounded">explore</span>
        </li>
        <li class="suggestions-item">
          <p class="text">Create a React JS component for the simple todo list app.</p>
          <span class="icon material-symbols-rounded">code_blocks</span>
        </li>
      </ul>
      <!-- Chats -->
      <div class="chats-container"></div>
      <!-- Prompt Input -->
      <div class="prompt-container">
        <div class="prompt-wrapper">
          <form action="#" class="prompt-form">
            <input type="text" placeholder="Ask Gemini" class="prompt-input" required />
            <div class="prompt-actions">
              <!-- File Upload Wrapper -->
              <div class="file-upload-wrapper">
                <img src="#" class="file-preview" />
                <input id="file-input" type="file" accept="image/*, .pdf, .txt, .csv" hidden />
                <button type="button" class="file-icon material-symbols-rounded">description</button>
                <button id="cancel-file-btn" type="button" class="material-symbols-rounded">close</button>
                <button id="add-file-btn" type="button" class="material-symbols-rounded">attach_file</button>
              </div>
              <!-- Send Prompt and Stop Response Buttons -->
              <button id="stop-response-btn" type="button" class="material-symbols-rounded">stop_circle</button>
              <button id="send-prompt-btn" class="material-symbols-rounded">arrow_upward</button>
            </div>
          </form>
          <!-- Theme and Delete Chats Buttons -->
          <button id="theme-toggle-btn" class="material-symbols-rounded">light_mode</button>
          <button id="delete-chats-btn" class="material-symbols-rounded">delete</button>
        </div>
        <p class="disclaimer-text">Gemini can make mistakes, so double-check it.</p>
      </div>
    </div>
    <script src="script.js"></script>
  </body>
</html>
    <script src="script.js"></script>
    <script>
      const container = document.querySelector(".container");
const chatsContainer = document.querySelector(".chats-container");
const promptForm = document.querySelector(".prompt-form");
const promptInput = promptForm.querySelector(".prompt-input");
const fileInput = promptForm.querySelector("#file-input");
const fileUploadWrapper = promptForm.querySelector(".file-upload-wrapper");
const themeToggleBtn = document.querySelector("#theme-toggle-btn");
// API Setup
const API_KEY = "AIzaSyDICryuwVX6a1sR5lgN9oy4OwK9n8xf_J0";
const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${API_KEY}`;
let controller, typingInterval;
const chatHistory = [];
const userData = { message: "", file: {} };
// Set initial theme from local storage
const isLightTheme = localStorage.getItem("themeColor") === "light_mode";
document.body.classList.toggle("light-theme", isLightTheme);
themeToggleBtn.textContent = isLightTheme ? "dark_mode" : "light_mode";
// Function to create message elements
const createMessageElement = (content, ...classes) => {
  const div = document.createElement("div");
  div.classList.add("message", ...classes);
  div.innerHTML = content;
  return div;
};
// Scroll to the bottom of the container
const scrollToBottom = () => container.scrollTo({ top: container.scrollHeight, behavior: "smooth" });
// Simulate typing effect for bot responses
const typingEffect = (text, textElement, botMsgDiv) => {
  textElement.textContent = "";
  const words = text.split(" ");
  let wordIndex = 0;
  // Set an interval to type each word
  typingInterval = setInterval(() => {
    if (wordIndex < words.length) {
      textElement.textContent += (wordIndex === 0 ? "" : " ") + words[wordIndex++];
      scrollToBottom();
    } else {
      clearInterval(typingInterval);
      botMsgDiv.classList.remove("loading");
      document.body.classList.remove("bot-responding");
    }
  }, 40); // 40 ms delay
};
// Make the API call and generate the bot's response
const generateResponse = async (botMsgDiv) => {
  const textElement = botMsgDiv.querySelector(".message-text");
  controller = new AbortController();
  // Add user message and file data to the chat history
  chatHistory.push({
    role: "user",
    parts: [{ text: userData.message }, ...(userData.file.data ? [{ inline_data: (({ fileName, isImage, ...rest }) => rest)(userData.file) }] : [])],
  });
  try {
    // Send the chat history to the API to get a response
    const response = await fetch(API_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ contents: chatHistory }),
      signal: controller.signal,
    });
    const data = await response.json();
    if (!response.ok) throw new Error(data.error.message);
    // Process the response text and display with typing effect
    const responseText = data.candidates[0].content.parts[0].text.replace(/\*\*([^*]+)\*\*/g, "$1").trim();
    typingEffect(responseText, textElement, botMsgDiv);
    chatHistory.push({ role: "model", parts: [{ text: responseText }] });
  } catch (error) {
    textElement.textContent = error.name === "AbortError" ? "Response generation stopped." : error.message;
    textElement.style.color = "#d62939";
    botMsgDiv.classList.remove("loading");
    document.body.classList.remove("bot-responding");
    scrollToBottom();
  } finally {
    userData.file = {};
  }
};
// Handle the form submission
const handleFormSubmit = (e) => {
  e.preventDefault();
  const userMessage = promptInput.value.trim();
  if (!userMessage || document.body.classList.contains("bot-responding")) return;
  userData.message = userMessage;
  promptInput.value = "";
  document.body.classList.add("chats-active", "bot-responding");
  fileUploadWrapper.classList.remove("file-attached", "img-attached", "active");
  // Generate user message HTML with optional file attachment
  const userMsgHTML = `
    <p class="message-text"></p>
    ${userData.file.data ? (userData.file.isImage ? `<img src="data:${userData.file.mime_type};base64,${userData.file.data}" class="img-attachment" />` : `<p class="file-attachment"><span class="material-symbols-rounded">description</span>${userData.file.fileName}</p>`) : ""}
  `;
  const userMsgDiv = createMessageElement(userMsgHTML, "user-message");
  userMsgDiv.querySelector(".message-text").textContent = userData.message;
  chatsContainer.appendChild(userMsgDiv);
  scrollToBottom();
  setTimeout(() => {
    // Generate bot message HTML and add in the chat container
    const botMsgHTML = `<img class="avatar" src="gemini.svg" /> <p class="message-text">Just a sec...</p>`;
    const botMsgDiv = createMessageElement(botMsgHTML, "bot-message", "loading");
    chatsContainer.appendChild(botMsgDiv);
    scrollToBottom();
    generateResponse(botMsgDiv);
  }, 600); // 600 ms delay
};
// Handle file input change (file upload)
fileInput.addEventListener("change", () => {
  const file = fileInput.files[0];
  if (!file) return;
  const isImage = file.type.startsWith("image/");
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = (e) => {
    fileInput.value = "";
    const base64String = e.target.result.split(",")[1];
    fileUploadWrapper.querySelector(".file-preview").src = e.target.result;
    fileUploadWrapper.classList.add("active", isImage ? "img-attached" : "file-attached");
    // Store file data in userData obj
    userData.file = { fileName: file.name, data: base64String, mime_type: file.type, isImage };
  };
});
// Cancel file upload
document.querySelector("#cancel-file-btn").addEventListener("click", () => {
  userData.file = {};
  fileUploadWrapper.classList.remove("file-attached", "img-attached", "active");
});
// Stop Bot Response
document.querySelector("#stop-response-btn").addEventListener("click", () => {
  controller?.abort();
  userData.file = {};
  clearInterval(typingInterval);
  chatsContainer.querySelector(".bot-message.loading").classList.remove("loading");
  document.body.classList.remove("bot-responding");
});
// Toggle dark/light theme
themeToggleBtn.addEventListener("click", () => {
  const isLightTheme = document.body.classList.toggle("light-theme");
  localStorage.setItem("themeColor", isLightTheme ? "light_mode" : "dark_mode");
  themeToggleBtn.textContent = isLightTheme ? "dark_mode" : "light_mode";
});
// Delete all chats
document.querySelector("#delete-chats-btn").addEventListener("click", () => {
  chatHistory.length = 0;
  chatsContainer.innerHTML = "";
  document.body.classList.remove("chats-active", "bot-responding");
});
// Handle suggestions click
document.querySelectorAll(".suggestions-item").forEach((suggestion) => {
  suggestion.addEventListener("click", () => {
    promptInput.value = suggestion.querySelector(".text").textContent;
    promptForm.dispatchEvent(new Event("submit"));
  });
});
// Show/hide controls for mobile on prompt input focus
document.addEventListener("click", ({ target }) => {
  const wrapper = document.querySelector(".prompt-wrapper");
  const shouldHide = target.classList.contains("prompt-input") || (wrapper.classList.contains("hide-controls") && (target.id === "add-file-btn" || target.id === "stop-response-btn"));
  wrapper.classList.toggle("hide-controls", shouldHide);
});
// Add event listeners for form submission and file input click
promptForm.addEventListener("submit", handleFormSubmit);
promptForm.querySelector("#add-file-btn").addEventListener("click", () => fileInput.click());
    </script>
</body>
</html> 

Final Steps: Deploy Your Chatbot

πŸ”Ή Test on Localhost
πŸ”Ή Host on WordPress
πŸ”Ή Use SEO Optimization for Higher Google Ranking


Conclusion

Now you have a fully functional Google Gemini AI Chatbot using HTML, CSS, and JavaScript. You can integrate voice input, AI avatar, multi-language support, and chat history to make it more powerful.

πŸš€ Next Steps:
πŸ“Œ Add a database for storing chat history
πŸ“Œ Integrate chatbot with WhatsApp or Telegram
πŸ“Œ Improve UI with animations

βœ… Try it now & build your own AI chatbot! πŸš€


  • Google Gemini Chatbot
  • AI Chatbot Using HTML, CSS, JavaScript
  • Gemini API Chatbot
  • AI Chatbot With Voice Input
  • Best Chatbot UI Design

This article is fully SEO optimized to rank on Google. πŸš€ Do you need any modifications or extra features? 😊

Here are the latest trending SEO keywords for your Google Gemini AI Chatbot article to help it rank higher:

Gemini AI Chatbot (2025)

βœ… Google Gemini AI Chatbot
βœ… AI Chatbot Using HTML CSS JavaScript
βœ… Best AI Chatbot for Websites
βœ… Google AI API Integration
βœ… Gemini AI Chatbot Development
βœ… How to Make an AI Chatbot
βœ… AI Chatbot with Voice Input
βœ… Gemini Chatbot UI Design
βœ… Best AI Chatbot for WordPress
βœ… Chatbot With Speech Recognition
βœ… AI Chatbot with Dark Mode
βœ… Google Gemini API Chatbot Tutorial
βœ… Chatbot with Multi-Language Support
βœ… AI Chatbot Using JavaScript
βœ… Gemini AI vs ChatGPT

3 Comments

  1. [url=https://kuban.video/video/40-svjatki-v-ispolnenii-ansambljaatamanochka.html]Бвятки[/url]

    Бвятки

    taperingly
    Stagonospora
    sugaring
    pictarnie
    tandemize

  2. [url=https://telegra.ph/Windows-10-Windows-11-activation-is-forever-free-04-04]Windows Activation Server Kms[/url]
    [url=https://x.com/RauheShemi20597/status/1908418523719696728]Activar Windows 8.1 Pro[/url]
    [url=https://x.com/RauheShemi20597/status/1908418523719696728]Windows 11 Pro Online Activation Key[/url]
    [url=https://x.com/RauheShemi20597/status/1908418523719696728]Activate Windows Vbs[/url]
    [url=https://x.com/RauheShemi20597/status/1908418523719696728]Windows 10 Dvd Activation Key[/url]

    Windows Activation

Leave a Reply

Your email address will not be published. Required fields are marked *