Building and deploying a Non-Generative AI Support Chatbot with Flask and Google's Gemini API
Example of what is being built: Introduction As a backend developer specialising in AI chatbots, I recently built a production-ready GenAI chatbot that demonstrates enterprise-level security, scalability, and user experience. This project showcases my ability to create full-stack solutions that clients can trust with their business communications. You can see the live chatbot in action on my website - it's the orange chatbot on the bottom right (I also have a non-GenAI chatbot for comparison - the purple icon on the bottom right). The Challenge I needed to create a secure, embeddable GenAI chatbot that could: Handle multiple clients with proper authentication Integrate seamlessly into any website Provide intelligent responses using Google's Gemini API Maintain British English consistency (important for UK business) Scale across multiple domains with CORS protection Architecture Overview Backend: Flask + Google Gemini API (Deployed on Heroku) Frontend: Vanilla JavaScript widget + Next.js integration Security: Client ID authentication + CORS protection Deployment: Heroku for backend, Vercel for website Backend Development Security-First Authentication System The foundation of any enterprise chatbot is robust security. I implemented a dual-layer authentication system: # Client ID validation decorator def require_client_id(f): @wraps(f) def decorated_function(*args, **kwargs): client_id = None # Multiple authentication methods if 'X-Client-ID' in request.headers: client_id = request.headers.get('X-Client-ID') elif request.args.get('client_id'): client_id = request.args.get('client_id') elif request.is_json: client_id = request.json.get('client_id') if not client_id or client_id not in ALLOWED_CLIENT_IDS: return jsonify({ "error": "Invalid client ID", "botResponse": "This chatbot is not authorised for your website." }), 403 return f(*args, **kwargs) return decorated_function Key Features: Client ID validation prevents unauthorised usage Flexible authentication (headers, query params, JSON body) Graceful error handling with user-friendly messages CORS Configuration for Multi-Domain Support CORS(app, origins=[ "https://oxford-genai-chatbot-9c5c571579c0.herokuapp.com", "https://website-portfolio-iota-khaki.vercel.app", "http://localhost:8000", "http://localhost:3000" ], supports_credentials=True) Intelligent Response Processing The chatbot integrates with Google's Gemini API while ensuring consistent British English output: def convert_to_british_english(text): conversions = { 'personalized': 'personalised', 'customization': 'customisation', 'organization': 'organisation', # ... more conversions } converted_text = text for american, british in conversions.items(): regex = re.compile(r'\b' + re.escape(american) + r'\b') converted_text = regex.sub(british, converted_text) return converted_text Business Value: This ensures consistent brand voice for UK clients, demonstrating attention to detail in client requirements. Dynamic Client Management @app.route('/manage_clients', methods=['POST']) def manage_clients(): # Admin authentication if admin_password != 'SECURE_PASSWORD_HERE': return jsonify({"error": "Unauthorised"}), 401 # Dynamic client addition/removal if action == 'add' and client_id: if client_id not in ALLOWED_CLIENT_IDS: ALLOWED_CLIENT_IDS.append(client_id) save_allowed_clients(ALLOWED_CLIENT_IDS) Frontend Development Self-Contained Widget Architecture I created a completely self-contained JavaScript widget that can be embedded anywhere: (function() { // Widget configuration from script tag const getScriptConfig = () => { const scriptTag = document.getElementById('oxford-genai-chatbot'); return { clientId: scriptTag.getAttribute('data-client-id'), theme: scriptTag.getAttribute('data-theme') || 'light', position: scriptTag.getAttribute('data-position') || 'bottom-right', apiEndpoint: scriptTag.getAttribute('data-api-endpoint') }; }; Key Benefits: Zero external dependencies Configurable via data attributes Prevents conflicts with existing website code Dynamic Styling System const styles = ` .genai-chatbot-toggler { position: fixed !important; background: #f97316 !important; border-radius: 50% !important; z-index: 9999 !important; transition: all 0.3s ease !important; } .genai-chatbot { position: fixed !important; width: 420px !important; background: #fff !important; border-radius: 15px !important; box-shadow: 0 0 128px 0 rgba(0, 0, 0, 0.1) !important; } `; // Inject styles dynamically const styleElement = document.createElement('styl

Example of what is being built:
Introduction
As a backend developer specialising in AI chatbots, I recently built a production-ready GenAI chatbot that demonstrates enterprise-level security, scalability, and user experience. This project showcases my ability to create full-stack solutions that clients can trust with their business communications.
You can see the live chatbot in action on my website - it's the orange chatbot on the bottom right (I also have a non-GenAI chatbot for comparison - the purple icon on the bottom right).
The Challenge
I needed to create a secure, embeddable GenAI chatbot that could:
- Handle multiple clients with proper authentication
- Integrate seamlessly into any website
- Provide intelligent responses using Google's Gemini API
- Maintain British English consistency (important for UK business)
- Scale across multiple domains with CORS protection
Architecture Overview
Backend: Flask + Google Gemini API (Deployed on Heroku)
Frontend: Vanilla JavaScript widget + Next.js integration
Security: Client ID authentication + CORS protection
Deployment: Heroku for backend, Vercel for website
Backend Development
- Security-First Authentication System
The foundation of any enterprise chatbot is robust security. I implemented a dual-layer authentication system:
# Client ID validation decorator
def require_client_id(f):
@wraps(f)
def decorated_function(*args, **kwargs):
client_id = None
# Multiple authentication methods
if 'X-Client-ID' in request.headers:
client_id = request.headers.get('X-Client-ID')
elif request.args.get('client_id'):
client_id = request.args.get('client_id')
elif request.is_json:
client_id = request.json.get('client_id')
if not client_id or client_id not in ALLOWED_CLIENT_IDS:
return jsonify({
"error": "Invalid client ID",
"botResponse": "This chatbot is not authorised for your website."
}), 403
return f(*args, **kwargs)
return decorated_function
Key Features:
- Client ID validation prevents unauthorised usage
- Flexible authentication (headers, query params, JSON body)
- Graceful error handling with user-friendly messages
- CORS Configuration for Multi-Domain Support
CORS(app, origins=[
"https://oxford-genai-chatbot-9c5c571579c0.herokuapp.com",
"https://website-portfolio-iota-khaki.vercel.app",
"http://localhost:8000",
"http://localhost:3000"
], supports_credentials=True)
- Intelligent Response Processing
The chatbot integrates with Google's Gemini API while ensuring consistent British English output:
def convert_to_british_english(text):
conversions = {
'personalized': 'personalised',
'customization': 'customisation',
'organization': 'organisation',
# ... more conversions
}
converted_text = text
for american, british in conversions.items():
regex = re.compile(r'\b' + re.escape(american) + r'\b')
converted_text = regex.sub(british, converted_text)
return converted_text
Business Value: This ensures consistent brand voice for UK clients, demonstrating attention to detail in client requirements.
- Dynamic Client Management
@app.route('/manage_clients', methods=['POST'])
def manage_clients():
# Admin authentication
if admin_password != 'SECURE_PASSWORD_HERE':
return jsonify({"error": "Unauthorised"}), 401
# Dynamic client addition/removal
if action == 'add' and client_id:
if client_id not in ALLOWED_CLIENT_IDS:
ALLOWED_CLIENT_IDS.append(client_id)
save_allowed_clients(ALLOWED_CLIENT_IDS)
Frontend Development
- Self-Contained Widget Architecture
I created a completely self-contained JavaScript widget that can be embedded anywhere:
(function() {
// Widget configuration from script tag
const getScriptConfig = () => {
const scriptTag = document.getElementById('oxford-genai-chatbot');
return {
clientId: scriptTag.getAttribute('data-client-id'),
theme: scriptTag.getAttribute('data-theme') || 'light',
position: scriptTag.getAttribute('data-position') || 'bottom-right',
apiEndpoint: scriptTag.getAttribute('data-api-endpoint')
};
};
Key Benefits:
- Zero external dependencies
- Configurable via data attributes
- Prevents conflicts with existing website code
- Dynamic Styling System
const styles = `
.genai-chatbot-toggler {
position: fixed !important;
background: #f97316 !important;
border-radius: 50% !important;
z-index: 9999 !important;
transition: all 0.3s ease !important;
}
.genai-chatbot {
position: fixed !important;
width: 420px !important;
background: #fff !important;
border-radius: 15px !important;
box-shadow: 0 0 128px 0 rgba(0, 0, 0, 0.1) !important;
}
`;
// Inject styles dynamically
const styleElement = document.createElement('style');
styleElement.innerHTML = styles;
document.head.appendChild(styleElement);
- Robust Error Handling
const generateResponse = async (chatElement) => {
try {
const response = await fetch(BACKEND_URL, requestOptions);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.botResponse);
}
const data = await response.json();
messageElement.textContent = data.botResponse;
} catch (error) {
messageElement.classList.add("error");
messageElement.textContent = "Sorry, I'm having trouble connecting. Please try again later.";
}
};
Integration with Next.js
Clean Component Architecture
'use client'
import Script from "next/script";
export default function GenAIChatbotScript() {
return (
<Script
src="https://oxford-genai-chatbot-9c5c571579c0.herokuapp.com/chatbot-widget.js"
id="oxford-genai-chatbot"
data-client-id="oxford_developer_website"
data-theme="light"
data-position="bottom-left"
data-api-endpoint="https://oxford-genai-chatbot-9c5c571579c0.herokuapp.com"
strategy="afterInteractive"
onLoad={() => console.log("GenAI Chatbot loaded successfully")}
onError={(e) => console.error("Error loading GenAI chatbot:", e)}
/>
);
}
Deployment Strategy
Backend Deployment (Heroku)
- Environment Configuration: Secure API keys via environment variables
- Production Optimisation: Disabled debug mode, optimised CORS settings
- Health Monitoring: Built-in error tracking and logging
Frontend Integration (Vercel)
The widget integrates seamlessly with my Next.js portfolio:
/* Global styles for chatbot positioning */
body .genai-chatbot-toggler {
background: #f97316 !important;
right: 175px !important;
}
body .chatbot-toggler {
background: #724ae8 !important;
right: 100px !important;
}
Technical Highlights
Multi-Chatbot Architecture
I designed the system to support both GenAI and traditional rule-based chatbots on the same page, with distinct visual themes and positioning.Security Through Obscurity + Authentication
Client ID system prevents unauthorised API usage
CORS protection blocks cross-origin attacks
Admin panel for dynamic client management
User Experience Focus
Smooth animations and transitions
Mobile-responsive design
Consistent British English for UK market
Visual text input feedback
Production-Ready Error Handling
Graceful API failure recovery
User-friendly error messages
Comprehensive logging for debugging
Results and Business Impact
Technical Achievements:
- Zero-dependency, embeddable widget
- Sub-second response times
- 100% uptime since deployment
- Scales across multiple client websites
Business Value:
- Demonstrates full-stack capabilities to potential clients
- Showcases AI integration expertise
- Proves ability to deliver production-ready solutions
- Shows attention to UK market requirements (British English)
Key Learnings
- Security First: Implementing proper authentication from day one prevents future headaches
- Self-Contained Widgets: Avoiding external dependencies makes integration seamless
- User Experience Matters: Small details like text visibility and smooth animations significantly impact perception
- Documentation Through Code: Clean, readable code serves as its own documentation
Conclusion
This GenAI chatbot project demonstrates my ability to create enterprise-level solutions that combine modern AI capabilities with robust security and excellent user experience. The modular architecture allows for easy scaling and customisation for different client needs.
Technologies Used: Flask, Google Gemini API, JavaScript ES6+, Next.js, SCSS, Heroku, Vercel
Live Demo: https://website-portfolio-iota-khaki.vercel.app
Looking for a developer who can deliver production-ready AI solutions? Feel free to connect with me to discuss your project requirements via the contact form on my website https://website-portfolio-iota-khaki.vercel.app