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

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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