{"slug": "an-html-code-which-could-be-ran-with-a-pythin-backened-and-ths-is-the-frontend", "title": "AN HTML CODE WHICH COULD BE RAN WITH A PYTHIN BACKENED AND THS IS THE FRONTEND", "summary": "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.", "body_md": "| <!DOCTYPE html> | |\n| <html lang=\"en\"> | |\n| <head> | |\n| <meta charset=\"UTF-8\"> | |\n| <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> | |\n| <title>Local AI Chatbot</title> | |\n| <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap\"> | |\n| <style> | |\n| /* CSS Variables for easy theme adjustments */ | |\n| :root { | |\n| --primary-color: #007bff; /* Bright blue for actions/user messages */ | |\n| --primary-hover: #0056b3; | |\n| --background-color: #f0f2f5; /* Light gray background */ | |\n| --container-bg: #fff; | |\n| --bot-bg: #e9e9eb; /* Light gray for bot message background */ | |\n| --text-color: #333; | |\n| --border-color: #e0e0e0; | |\n| --input-bg: #f7f7f7; | |\n| --shadow-light: 0 4px 12px rgba(0, 0, 0, 0.1); | |\n| } | |\n| /* General Body Styling & Accessibility Enhancements */ | |\n| body { | |\n| font-family: 'Inter', -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif; | |\n| background-color: var(--background-color); | |\n| color: var(--text-color); | |\n| margin: 0; | |\n| display: flex; | |\n| justify-content: center; | |\n| align-items: center; | |\n| min-height: 100vh; | |\n| padding: 0; /* Let the container handle padding */ | |\n| } | |\n| /* Chat Container (Main Layout) */ | |\n| .chat-container { | |\n| width: 90%; /* More responsive width */ | |\n| max-width: 650px; /* Slightly wider max-width */ | |\n| height: 90vh; /* Taller on large screens */ | |\n| display: flex; | |\n| flex-direction: column; | |\n| background-color: var(--container-bg); | |\n| border-radius: 12px; | |\n| box-shadow: var(--shadow-light); | |\n| overflow: hidden; | |\n| transition: all 0.3s ease; /* Smooth transition for resizing/theme changes */ | |\n| } | |\n| /* Chat Box (Messages Area) */ | |\n| .chat-box { | |\n| flex: 1; | |\n| padding: 20px; | |\n| overflow-y: auto; | |\n| display: flex; | |\n| flex-direction: column; | |\n| gap: 12px; /* Slightly smaller gap */ | |\n| scroll-behavior: smooth; /* Smooth scrolling when new messages appear */ | |\n| } | |\n| /* Heading for better semantic structure */ | |\n| .chat-header { | |\n| padding: 15px 20px; | |\n| text-align: center; | |\n| font-size: 1.2em; | |\n| font-weight: 600; | |\n| color: var(--primary-color); | |\n| border-bottom: 1px solid var(--border-color); | |\n| background-color: var(--input-bg); | |\n| } | |\n| /* Individual Message Styling */ | |\n| .message-wrapper { | |\n| display: flex; | |\n| /* Use flex for alignment */ | |\n| } | |\n| .message { | |\n| max-width: 85%; /* Give bot slightly more space */ | |\n| padding: 12px 16px; | |\n| border-radius: 18px; /* Slightly smaller radius for a modern feel */ | |\n| word-wrap: break-word; | |\n| line-height: 1.45; | |\n| box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); /* Lighter shadow */ | |\n| } | |\n| .user-message-wrapper { | |\n| justify-content: flex-end; /* Align user messages to the right */ | |\n| } | |\n| .user-message { | |\n| background-color: var(--primary-color); | |\n| color: #fff; | |\n| border-bottom-right-radius: 6px; | |\n| } | |\n| .bot-message-wrapper { | |\n| justify-content: flex-start; /* Align bot messages to the left */ | |\n| } | |\n| .bot-message { | |\n| background-color: var(--bot-bg); | |\n| color: var(--text-color); | |\n| border-bottom-left-radius: 6px; | |\n| } | |\n| /* Loading Indicator */ | |\n| .loading-indicator { | |\n| background-color: var(--bot-bg); | |\n| color: var(--text-color); | |\n| animation: pulse 1.5s infinite ease-in-out; | |\n| /* Ensure it has the same padding/border as a message */ | |\n| padding: 12px 16px; | |\n| border-radius: 18px; | |\n| border-bottom-left-radius: 6px; | |\n| } | |\n| .loading-wrapper { | |\n| justify-content: flex-start; | |\n| } | |\n| @keyframes pulse { | |\n| 0% { opacity: 0.7; } | |\n| 50% { opacity: 1; } | |\n| 100% { opacity: 0.7; } | |\n| } | |\n| /* Input Area */ | |\n| .input-area { | |\n| display: flex; | |\n| padding: 15px 20px; | |\n| border-top: 1px solid var(--border-color); | |\n| background-color: var(--input-bg); | |\n| } | |\n| .input-area input { | |\n| flex: 1; | |\n| border: 1px solid var(--border-color); | |\n| border-radius: 20px; | |\n| padding: 10px 15px; | |\n| font-size: 16px; | |\n| outline: none; | |\n| transition: border-color 0.2s, box-shadow 0.2s; | |\n| line-height: 1.3; | |\n| } | |\n| .input-area input:focus { | |\n| border-color: var(--primary-color); | |\n| box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25); /* Focus ring for accessibility */ | |\n| } | |\n| .input-area button { | |\n| margin-left: 10px; | |\n| background-color: var(--primary-color); | |\n| color: #fff; | |\n| border: none; | |\n| border-radius: 20px; | |\n| padding: 10px 20px; | |\n| font-size: 16px; | |\n| cursor: pointer; | |\n| transition: background-color 0.2s, opacity 0.2s; | |\n| font-weight: 600; /* Bolder button text */ | |\n| } | |\n| .input-area button:hover:not(:disabled) { | |\n| background-color: var(--primary-hover); | |\n| } | |\n| .input-area button:focus { | |\n| outline: none; | |\n| box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5); /* Focus ring */ | |\n| } | |\n| .input-area button:disabled { | |\n| background-color: #a0c3e7; | |\n| opacity: 0.8; | |\n| cursor: not-allowed; | |\n| } | |\n| /* Media Query for Mobile Responsiveness */ | |\n| @media (max-width: 600px) { | |\n| body { | |\n| padding: 0; | |\n| } | |\n| .chat-container { | |\n| width: 100%; | |\n| height: 100vh; | |\n| border-radius: 0; | |\n| box-shadow: none; | |\n| } | |\n| .input-area { | |\n| padding: 10px 15px; | |\n| } | |\n| .input-area input { | |\n| padding: 8px 12px; | |\n| } | |\n| .input-area button { | |\n| padding: 8px 15px; | |\n| font-size: 14px; | |\n| } | |\n| } | |\n| </style> | |\n| </head> | |\n| <body> | |\n| <div class=\"chat-container\"> | |\n| <header class=\"chat-header\"> | |\n| Local AI Chatbot | |\n| </header> | |\n| <main class=\"chat-box\" id=\"chat-box\" aria-live=\"polite\"> | |\n| <div class=\"message-wrapper bot-message-wrapper\"> | |\n| <div class=\"message bot-message\">Hello! I'm a local AI. How can I help you?</div> | |\n| </div> | |\n| </main> | |\n| <div class=\"input-area\"> | |\n| <form id=\"chat-form\" style=\"display: flex; width: 100%;\"> | |\n| <label for=\"user-input\" class=\"visually-hidden\">Type your message</label> | |\n| <input type=\"text\" id=\"user-input\" placeholder=\"Type your message...\" autofocus aria-label=\"Chat input field\"> | |\n| <button type=\"submit\" id=\"send-button\">Send</button> | |\n| </form> | |\n| </div> | |\n| </div> | |\n| <script> | |\n| document.addEventListener('DOMContentLoaded', () => { | |\n| const chatBox = document.getElementById('chat-box'); | |\n| const userInput = document.getElementById('user-input'); | |\n| const sendButton = document.getElementById('send-button'); | |\n| const chatForm = document.getElementById('chat-form'); // Reference the new form element | |\n| // Helper function to create a message element | |\n| const createMessageElement = (content, sender) => { | |\n| const wrapperDiv = document.createElement('div'); | |\n| wrapperDiv.classList.add('message-wrapper', `${sender}-message-wrapper`); | |\n| const messageDiv = document.createElement('div'); | |\n| messageDiv.classList.add('message', `${sender}-message`); | |\n| messageDiv.textContent = content; | |\n| wrapperDiv.appendChild(messageDiv); | |\n| return wrapperDiv; | |\n| }; | |\n| const addMessage = (content, sender) => { | |\n| const messageElement = createMessageElement(content, sender); | |\n| chatBox.appendChild(messageElement); | |\n| // Ensure chat scrolls to the bottom smoothly | |\n| chatBox.scrollTop = chatBox.scrollHeight; | |\n| }; | |\n| const showLoadingIndicator = () => { | |\n| // Using the same structure as a message for consistency | |\n| const loadingWrapper = document.createElement('div'); | |\n| loadingWrapper.classList.add('message-wrapper', 'loading-wrapper'); | |\n| loadingWrapper.id = 'loading-indicator-wrapper'; | |\n| const loadingDiv = document.createElement('div'); | |\n| loadingDiv.classList.add('message', 'loading-indicator'); | |\n| loadingDiv.textContent = 'Bot is thinking...'; | |\n| loadingWrapper.appendChild(loadingDiv); | |\n| chatBox.appendChild(loadingWrapper); | |\n| chatBox.scrollTop = chatBox.scrollHeight; | |\n| }; | |\n| const removeLoadingIndicator = () => { | |\n| const loadingWrapper = document.getElementById('loading-indicator-wrapper'); | |\n| if (loadingWrapper) { | |\n| loadingWrapper.remove(); | |\n| } | |\n| }; | |\n| const disableInput = (disabled) => { | |\n| userInput.disabled = disabled; | |\n| sendButton.disabled = disabled; | |\n| }; | |\n| const sendMessage = async (event) => { | |\n| event.preventDefault(); // Prevent default form submission/page reload | |\n| const message = userInput.value.trim(); | |\n| if (message === '') return; | |\n| addMessage(message, 'user'); | |\n| userInput.value = ''; | |\n| disableInput(true); // Disable input while waiting for response | |\n| showLoadingIndicator(); | |\n| try { | |\n| // Simulating network delay for local testing | |\n| // await new Promise(resolve => setTimeout(resolve, 1000)); | |\n| const response = await fetch('http://127.0.0.1:5000/chatbot', { | |\n| method: 'POST', | |\n| headers: { | |\n| 'Content-Type': 'application/json', | |\n| }, | |\n| body: JSON.stringify({ message: message }), | |\n| }); | |\n| const data = await response.json(); | |\n| removeLoadingIndicator(); | |\n| if (data.response) { | |\n| addMessage(data.response, 'bot'); | |\n| } else { | |\n| addMessage('Sorry, an empty response was received.', 'bot'); | |\n| } | |\n| } catch (error) { | |\n| removeLoadingIndicator(); | |\n| addMessage('Sorry, I could not connect to the server (Error: ' + error.message + ').', 'bot'); | |\n| console.error('Error:', error); | |\n| } finally { | |\n| disableInput(false); | |\n| userInput.focus(); // Return focus to input for quick typing | |\n| } | |\n| }; | |\n| // Use the form's submit event for both button click and Enter key | |\n| chatForm.addEventListener('submit', sendMessage); | |\n| }); | |\n| </script> | |\n| </body> | |\n| </html> |", "url": "https://wpnews.pro/news/an-html-code-which-could-be-ran-with-a-pythin-backened-and-ths-is-the-frontend", "canonical_source": "https://gist.github.com/LegedsDaD/02b9fe2e71d3daf4af00d5ff9f76b104", "published_at": "2026-06-29 03:44:57+00:00", "updated_at": "2026-07-01 04:18:24.296230+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools"], "entities": [], "alternates": {"html": "https://wpnews.pro/news/an-html-code-which-could-be-ran-with-a-pythin-backened-and-ths-is-the-frontend", "markdown": "https://wpnews.pro/news/an-html-code-which-could-be-ran-with-a-pythin-backened-and-ths-is-the-frontend.md", "text": "https://wpnews.pro/news/an-html-code-which-could-be-ran-with-a-pythin-backened-and-ths-is-the-frontend.txt", "jsonld": "https://wpnews.pro/news/an-html-code-which-could-be-ran-with-a-pythin-backened-and-ths-is-the-frontend.jsonld"}}