{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreie5htkgyy63emscnniygtp2b3i2eqxe4ijvcbhmfap2c2mdcn2ex4",
"uri": "at://did:plc:pgryn3ephfd2xgft23qokfzt/app.bsky.feed.post/3mpdtg6erdyq2"
},
"path": "/t/creating-a-website-chat-widget-with-gradio-part-iv/177208#post_1",
"publishedAt": "2026-06-28T10:16:50.000Z",
"site": "https://discuss.huggingface.co",
"tags": [
"@John6666",
"@gradio"
],
"textContent": "A while back @John6666 help set up an AI gradio chatbot on my website. Everything was working fine, with the AI chatbot doing a great job.\n\nHowever, I’ve not been monitoring it, and sometime recently(?) it stopped working. The problem is on the client I get the error:\n\n> Access to fetch at [huggingfacespace] from origin [mywebsite] has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Credentials’ header in the response is ‘’ which must be ‘true’ when the request’s credentials mode is ‘include’.\n\nAfter looking around this seems to be related to a change to gradio where they fixed a security issue with CORS. However, the solution I found appeared to suggest the fix was to basically re-write the code to “get around” CORS rather than using it.\n\nIt that really the only solution?\n\nThis is the code that was working before the “fix” broke it:\n\n(website client code)\n\n\n <script type=\"module\">\n import { Client } from \"https://cdn.jsdelivr.net/npm/@gradio/client@/dist/index.min.js\";\n import { marked } from \"https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js\";\n\n async function initChatWidget() {\n const client = await Client.connect(\"https://[myspace].hf.space/\");\n\n const conversationId = crypto.randomUUID(); // NEW FOR LOGGING\n const chatToggle = document.getElementById('chat-toggle');\n const chatContainer = document.getElementById('chat-container');\n const closeChat = document.getElementById('close-chat');\n const chatInput = document.getElementById('chat-input');\n const sendButton = document.getElementById('send-message');\n const messagesContainer = document.getElementById('chat-messages');\n\n chatToggle.addEventListener('click', () => {\n chatContainer.classList.remove('hidden');\n });\n\n closeChat.addEventListener('click', () => {\n chatContainer.classList.add('hidden');\n });\n\n // Auto-open chat on contact page\n if (window.location.pathname.includes('/contact') ||\n window.location.pathname.endsWith('/contact.html') ||\n window.location.pathname.includes('/account') ||\n window.location.pathname.endsWith('/account.html')) {\n chatContainer.classList.remove('hidden');\n }\n\n function appendMessage(text, sender) {\n const div = document.createElement(\"div\");\n div.className = `message ${sender}-message`;\n div.textContent = text; // or marked.parse(text) if you're using marked\n messagesContainer.appendChild(div);\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n }\n\n async function sendMessage() {\n const userMessage = chatInput.value.trim();\n if (!userMessage) return;\n\n appendMessage(userMessage, 'user');\n chatInput.value = '';\n\n try {\n const result = await client.predict(\"/chat\", {\n message: {\"text\": userMessage, \"files\": []},\n conversation_id: conversationId, // NEW FOR LOGGING\n });\n\n const lines = result.data[0]; // list of strings from Python\n const botMessage = Array.isArray(lines) ? lines.join(\"\\n\") : String(lines);\n appendMessage(botMessage, \"bot\");\n\n } catch (error) {\n console.error('Error:', error);\n appendMessage('Sorry, there was an error processing your request.', 'bot');\n }\n }\n\n sendButton.addEventListener('click', sendMessage);\n chatInput.addEventListener('keypress', (e) => {\n if (e.key === 'Enter') sendMessage();\n });\n\n // PRE-SEED: show a bot greeting as soon as the widget is ready\n appendMessage(\"Hey there! What can I help you with today?\", \"bot\");\n }\n\n initChatWidget();\n </script>\n\n\n(code on huggingface space)\n\n\n import json\n import requests # for API code\n import holidays # details of UK holidays\n from datetime import datetime, timedelta, date, time\n from openai import OpenAI\n import gradio as gr\n import os\n import uuid\n\n say_hello = [\n {\n \"role\": \"assistant\",\n \"content\": \"Hey there! What can I help you with today?\",\n }\n ]\n\n # This is the main chat code called by Gradio ChatInterface on user input, sends input to AI, processes response, returns to the Gradio ChatInterface\n def chat(message, history, conversation_id):\n if not conversation_id:\n conversation_id = str(uuid.uuid4())\n\n if isinstance(message, dict): # make sure the user comment is in an acceptable format, and convert to a string\n user_text = message.get(\"text\", \"\")\n else:\n user_text = str(message)\n history = [{\"role\":h[\"role\"], \"content\":h[\"content\"]} for h in history] # clean history for some non openai models\n messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": user_text}] # illusion of memory\n response = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)\n\n # AI STUFF HERE\n\n response_as_a_list = [response.choices[0].message.content] # need to change reponse from string to a list of strings for the chatbot widget\n return response_as_a_list\n\n # Additional (hidden) input so ChatInterface exposes 'conversation_id'\n conversation_id_input = gr.Textbox(\n label=\"conversation_id\",\n visible=False,\n value=\"\",\n )\n\n # Use the Gradio Chatbot component to preload the chat (and history) with an initial greeting, rather than letting the user go first\n chatbot = gr.Chatbot(\n value=say_hello,\n type=\"messages\",\n )\n\n # The main chat interface handled by Gradio\n my_chat = gr.ChatInterface(\n fn=chat,\n type=\"messages\",\n multimodal=True,\n title=\"Widget Demo Bot\",\n api_name=\"chat\",\n additional_inputs=[conversation_id_input], # extra arg to fn\n )\n\n if __name__ == \"__main__\":\n my_chat.launch(ssr_mode=False)\n\n",
"title": "Creating a Website Chat Widget with Gradio Part IV"
}