AI Chatbot with Speaking ( Free Custom and Without API )

AI Chatbot with Speaking ( Free Custom and Without API )

Suraj (UI/UX Developer)
Dec 2025
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>CKD | AI Chatbot with Speaking</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>

<body>
<div class="text-center">
 <h2>AI Chatbot with Speaking</h2> 
</div>

<button class="chat-toggle-custome" onclick="toggleChat()">💬</button>

<div class="chat-container" id="chatContainer">
 
 <div class="chat-header">
   <span>Chat AI</span>
   <button class="close-btn" onclick="closeChat()">✖</button>
 </div>

 <div class="chat-box" id="chatBox">
   <div class="message from-bot">Hello! How can I help you?</div>
 </div>

 <div class="input-area">
   <input id="userInput" placeholder="Type your message..." oninput="enableSendButton()">
   <button id="sendButton" onclick="sendMessage()" disabled>➤</button>
 </div>
</div>

<div id="myData" style="display:none;">
 <div data-triggers="hello,hi,hey" data-answer="Hello!||Namaste!||Kaise ho aap?"></div>
 <div data-triggers="name,who are you" data-answer="Mera naam Shona hai.||I am Shona AI"></div>
 <div data-triggers="bye,goodbye" data-answer="Bye bye ||Phir milenge"></div>
 <div data-triggers="good morning,gm" data-answer="Good morning ||good day"></div>
 <div class="fallback" data-answer="Samajh nahi aaya ||Thoda aur simple likhiye||dubara Pucho"></div>
</div>

<script src="js/js.js"></script>
</body>
</html>
 

CSS

.text-center{text-align:center; font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;}

.chat-toggle-custome{
 position:fixed;
 bottom:20px;
 right:20px;
 width:60px;
 height:60px;
 border-radius:50%;
 border:none;
 background:linear-gradient(135deg,#ff7350,#ff7350,#001);
 color:#fff;
 font-size:24px;
 cursor:pointer;
 z-index:1000;
  animation: pulseShadow 2s infinite;
}

@keyframes pulseShadow {
 0% {
   box-shadow: 0 0 0 0 rgb(255 115 80);
 }
 70% {
   box-shadow: 0 0 0 30px rgba(79, 172, 254, 0);
 }
 100% {
   box-shadow: 0 0 0 0 rgba(79, 172, 254, 0);
 }
}

.chat-container{
 position:fixed;
 bottom:90px;
 right:20px;
 width:340px;
 height:501px;
 background:#ffffff;
 border-radius:21px;
 box-shadow:0 8px 31px rgba(0,0,0,.2);
 display:none;
 flex-direction:column;
 overflow:hidden;
 z-index:999;
}

.chat-header{
 background:#ff7351;
 color:#ffffff;
 padding:12px 16px;
 display:flex;
 justify-content:space-between;
 align-items:center;
}

.chat-header span{
 font-weight:700;
}

.close-btn{
 background:none;
 border:none;
 color:#ffffff;
 font-size:21px;
 cursor:pointer;
}

.chat-box{
 flex:1;
 padding:14px;
 background:#f9f8fb;
 overflow-y:auto;
 display:flex;
 flex-direction:column;
 gap:10px;
}

.message{
 max-width:75%;
 padding:10px 14px;
 border-radius:18px;
 font-size:16px;
 font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
}

.from-user{
 background:#ff7350;
 color:#fff;
 align-self:flex-end;
 border-bottom-right-radius:5px;
}

.from-bot{
 background:#e5e5ea;
 color:#111;
 align-self:flex-start;
 border-bottom-left-radius:5px;
}

.input-area{
 display:flex;
 padding:10px;
 border-top:1px solid #ddd;
}

#userInput{
 flex:1;
 padding:12px;
 border-radius:25px;
 border:1px solid #ddd;
 outline:none;
}

#sendButton{
 margin-left:10px;
 padding:12px 16px;
 border-radius:50%;
 border:none;
 background:#ff7350;
 color:#fff;
 cursor:pointer;
}

#sendButton:disabled{
 background:#ccc;
}

JavaScript

let faq = [], fallbacks = [];

document.querySelectorAll("#myData div[data-triggers]").forEach(d => {
 faq.push({
   triggers: d.dataset.triggers.split(",").map(t => t.trim().toLowerCase()),
   answers: d.dataset.answer.split("||")
 });
});
fallbacks = document.querySelector(".fallback").dataset.answer.split("||");

function toggleChat() {
 let chat = document.getElementById("chatContainer");
 let input = document.getElementById("userInput");

 if (chat.style.display === "flex") {
   chat.style.display = "none";
 } else {
   chat.style.display = "flex";
   setTimeout(() => input.focus(), 200);
 }
}

function closeChat() {
 document.getElementById("chatContainer").style.display = "none";
}

document.addEventListener("click", e => {
 let chat = document.getElementById("chatContainer");
 let btn = document.querySelector(".chat-toggle-custome");

 if (
   chat.style.display === "flex" &&
   !chat.contains(e.target) &&
   !btn.contains(e.target)
 ) {
   chat.style.display = "none";
 }
});

function sendMessage() {
 let input = document.getElementById("userInput");
 let text = input.value.trim();
 if (!text) return;

 display(text, "from-user");
 input.value = "";
 sendButton.disabled = true;

 let clean = text.toLowerCase();
 let found = false;

 for (let f of faq) {
   for (let t of f.triggers) {
     if (clean.includes(t)) {
       reply(f.answers);
       found = true;
       break;
     }
   }
   if (found) break;
 }

 if (!found) reply(fallbacks);
}

function reply(arr) {
 let msg = arr[Math.floor(Math.random() * arr.length)];
 setTimeout(() => {
   display(msg, "from-bot");
   speak(msg);
 }, 600);
}

function display(msg, cls) {
 let d = document.createElement("div");
 d.className = "message " + cls;
 d.textContent = msg;
 chatBox.appendChild(d);
 chatBox.scrollTop = chatBox.scrollHeight;
}

function enableSendButton() {
 sendButton.disabled = userInput.value.trim() === "";
}

function speak(text) {
 if (!window.speechSynthesis) return;
 let u = new SpeechSynthesisUtterance(text);
 u.lang = "hi-IN";
 speechSynthesis.cancel();
 speechSynthesis.speak(u);
}

userInput.addEventListener("keypress", e => {
 if (e.key === "Enter" && !sendButton.disabled) {
   sendMessage();
 }
});