cd /news/artificial-intelligence/an-html-code-which-could-be-ran-with… · home topics artificial-intelligence article
[ARTICLE · art-45900] src=gist.github.com ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

AN HTML CODE WHICH COULD BE RAN WITH A PYTHIN BACKENED AND THS IS THE FRONTEND

A developer created an HTML frontend for a local AI chatbot with a Python backend. The interface features a modern chat design with user and bot message styling, a loading indicator, and responsive layout.

read9 min views12 publishedJun 29, 2026

| <!DOCTYPE html> | | | <html lang="en"> | | | <head> | |

| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Local AI Chatbot</title> | |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"> | |

| <style> | | | /* CSS Variables for easy theme adjustments */ | |

| :root { | |
| --primary-color: #007bff; /* Bright blue for actions/user messages */ | |
| --primary-hover: #0056b3; | |
| --background-color: #f0f2f5; /* Light gray background */ | |
| --container-bg: #fff; | |
| --bot-bg: #e9e9eb; /* Light gray for bot message background */ | |
| --text-color: #333; | |
| --border-color: #e0e0e0; | |
| --input-bg: #f7f7f7; | |
| --shadow-light: 0 4px 12px rgba(0, 0, 0, 0.1); | |

| } | | | /* General Body Styling & Accessibility Enhancements */ | | | body { | |

| font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| background-color: var(--background-color); | |
| color: var(--text-color); | |
| margin: 0; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| min-height: 100vh; | |

| padding: 0; /* Let the container handle padding / | | | } | | | / Chat Container (Main Layout) / | | | .chat-container { | | | width: 90%; / More responsive width / | | | max-width: 650px; / Slightly wider max-width / | | | height: 90vh; / Taller on large screens */ | |

| display: flex; | |
| flex-direction: column; | |
| background-color: var(--container-bg); | |
| border-radius: 12px; | |
| box-shadow: var(--shadow-light); | |
| overflow: hidden; | |

| transition: all 0.3s ease; /* Smooth transition for resizing/theme changes */ | | | } | |

| /* Chat Box (Messages Area) */ | |
| .chat-box { | |
| flex: 1; | |
| padding: 20px; | |
| overflow-y: auto; | |
| display: flex; | |
| flex-direction: column; | |

| gap: 12px; /* Slightly smaller gap / | | | scroll-behavior: smooth; / Smooth scrolling when new messages appear / | | | } | | | / Heading for better semantic structure */ | |

| .chat-header { | |
| padding: 15px 20px; | |
| text-align: center; | |
| font-size: 1.2em; | |
| font-weight: 600; | |
| color: var(--primary-color); | |
| border-bottom: 1px solid var(--border-color); | |
| background-color: var(--input-bg); | |

| } | | | /* Individual Message Styling */ | |

| .message-wrapper { | |
| display: flex; | |

| /* Use flex for alignment */ | | | } | | | .message { | |

| max-width: 85%; /* Give bot slightly more space */ | |
| padding: 12px 16px; | |

| border-radius: 18px; /* Slightly smaller radius for a modern feel */ | |

| word-wrap: break-word; | |
| line-height: 1.45; | |
| box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); /* Lighter shadow */ | |

| } | |

| .user-message-wrapper { | |
| justify-content: flex-end; /* Align user messages to the right */ | |

| } | |

| .user-message { | |
| background-color: var(--primary-color); | |
| color: #fff; | |
| border-bottom-right-radius: 6px; | |

| } | |

| .bot-message-wrapper { | |
| justify-content: flex-start; /* Align bot messages to the left */ | |

| } | |

| .bot-message { | |
| background-color: var(--bot-bg); | |
| color: var(--text-color); | |
| border-bottom-left-radius: 6px; | |

| } | | | /* Indicator */ | |

| .-indicator { | |
| background-color: var(--bot-bg); | |
| color: var(--text-color); | |
| animation: pulse 1.5s infinite ease-in-out; | |

| /* Ensure it has the same padding/border as a message */ | |

| padding: 12px 16px; | |
| border-radius: 18px; | |
| border-bottom-left-radius: 6px; | |

| } | |

| .-wrapper { | |
| justify-content: flex-start; | |

| } | | | @keyframes pulse { | |

| 0% { opacity: 0.7; } | |
| 50% { opacity: 1; } | |
| 100% { opacity: 0.7; } | |

| } | | | /* Input Area */ | |

| .input-area { | |
| display: flex; | |
| padding: 15px 20px; | |
| border-top: 1px solid var(--border-color); | |
| background-color: var(--input-bg); | |

| } | |

| .input-area input { | |
| flex: 1; | |
| border: 1px solid var(--border-color); | |
| border-radius: 20px; | |
| padding: 10px 15px; | |
| font-size: 16px; | |
| outline: none; | |
| transition: border-color 0.2s, box-shadow 0.2s; | |
| line-height: 1.3; | |

| } | |

| .input-area input:focus { | |
| border-color: var(--primary-color); | |
| box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25); /* Focus ring for accessibility */ | |

| } | |

| .input-area button { | |
| margin-left: 10px; | |
| background-color: var(--primary-color); | |
| color: #fff; | |
| border: none; | |
| border-radius: 20px; | |
| padding: 10px 20px; | |
| font-size: 16px; | |
| cursor: pointer; | |
| transition: background-color 0.2s, opacity 0.2s; | |
| font-weight: 600; /* Bolder button text */ | |

| } | |

| .input-area button:hover:not(:disabled) { | |
| background-color: var(--primary-hover); | |

| } | |

| .input-area button:focus { | |
| outline: none; | |
| box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5); /* Focus ring */ | |

| } | |

| .input-area button:disabled { | |
| background-color: #a0c3e7; | |
| opacity: 0.8; | |
| cursor: not-allowed; | |

| } | | | /* Media Query for Mobile Responsiveness */ | | | @media (max-width: 600px) { | | | body { | | | padding: 0; | | | } | |

| .chat-container { | |
| width: 100%; | |
| height: 100vh; | |
| border-radius: 0; | |
| box-shadow: none; | |

| } | |

| .input-area { | |
| padding: 10px 15px; | |

| } | |

| .input-area input { | |
| padding: 8px 12px; | |

| } | |

| .input-area button { | |
| padding: 8px 15px; | |
| font-size: 14px; | |

| } | | | } | | | </style> | | | </head> | | | <body> | |

| <div class="chat-container"> | |
| <header class="chat-header"> | |

| Local AI Chatbot | | | </header> | |

| <main class="chat-box" id="chat-box" aria-live="polite"> | |
| <div class="message-wrapper bot-message-wrapper"> | |

| <div class="message bot-message">Hello! I'm a local AI. How can I help you?</div> | | | </div> | | | </main> | |

| <div class="input-area"> | |
| <form id="chat-form" style="display: flex; width: 100%;"> | |
| <label for="user-input" class="visually-hidden">Type your message</label> | |
| <input type="text" id="user-input" placeholder="Type your message..." autofocus aria-label="Chat input field"> | |
| <button type="submit" id="send-button">Send</button> | |

| </form> | | | </div> | | | </div> | | | <script> | |

| document.addEventListener('DOMContentLoaded', () => { | |
| const chatBox = document.getElementById('chat-box'); | |
| const userInput = document.getElementById('user-input'); | |
| const sendButton = document.getElementById('send-button'); | |
| const chatForm = document.getElementById('chat-form'); // Reference the new form element | |

| // Helper function to create a message element | |

| const createMessageElement = (content, sender) => { | |
| const wrapperDiv = document.createElement('div'); | |
| wrapperDiv.classList.add('message-wrapper', `${sender}-message-wrapper`); | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.classList.add('message', `${sender}-message`); | |
| messageDiv.textContent = content; | |
| wrapperDiv.appendChild(messageDiv); | |

| return wrapperDiv; | |

| }; | |
| const addMessage = (content, sender) => { | |
| const messageElement = createMessageElement(content, sender); | |
| chatBox.appendChild(messageElement); | |

| // Ensure chat scrolls to the bottom smoothly | | | chatBox.scrollTop = chatBox.scrollHeight; | |

| }; | |
| const showIndicator = () => { | |

| // Using the same structure as a message for consistency | |

| const Wrapper = document.createElement('div'); | |
| Wrapper.classList.add('message-wrapper', '-wrapper'); | |
| Wrapper.id = '-indicator-wrapper'; | |
| const Div = document.createElement('div'); | |
| Div.classList.add('message', '-indicator'); | |

| Div.textContent = 'Bot is thinking...'; | |

| Wrapper.appendChild(Div); | |
| chatBox.appendChild(Wrapper); | |

| chatBox.scrollTop = chatBox.scrollHeight; | |

| }; | |
| const removeIndicator = () => { | |
| const Wrapper = document.getElementById('-indicator-wrapper'); | |
| if (Wrapper) { | |
| Wrapper.remove(); | |

| } | |

| }; | |
| const disableInput = (disabled) => { | |
| userInput.disabled = disabled; | |
| sendButton.disabled = disabled; | |
| }; | |
| const sendMessage = async (event) => { | |

| event.preventDefault(); // Prevent default form submission/page reload | |

| const message = userInput.value.trim(); | |
| if (message === '') return; | |
| addMessage(message, 'user'); | |
| userInput.value = ''; | |

| disableInput(true); // Disable input while waiting for response | | | showIndicator(); | | | try { | | | // Simulating network delay for local testing | |

| // await new Promise(resolve => setTimeout(resolve, 1000)); | |
| const response = await fetch('http://127.0.0.1:5000/chatbot', { | |

| method: 'POST', | | | headers: { | | | 'Content-Type': 'application/json', | | | }, | |

| body: JSON.stringify({ message: message }), | |
| }); | |
| const data = await response.json(); | |
| removeIndicator(); | |
| if (data.response) { | |
| addMessage(data.response, 'bot'); | |
| } else { | |

| addMessage('Sorry, an empty response was received.', 'bot'); | | | } | |

| } catch (error) { | |
| removeIndicator(); | |
| addMessage('Sorry, I could not connect to the server (Error: ' + error.message + ').', 'bot'); | |
| console.error('Error:', error); | |
| } finally { | |
| disableInput(false); | |

| userInput.focus(); // Return focus to input for quick typing | | | } | | | }; | | | // Use the form's submit event for both button click and Enter key | |

| chatForm.addEventListener('submit', sendMessage); | |
| }); | |

| </script> | | | </body> | | | </html> |

── more in #artificial-intelligence 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/an-html-code-which-c…] indexed:0 read:9min 2026-06-29 ·