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

May 31, 2025 - 14:40
 0
Building and deploying a Non-Generative AI Support Chatbot with Flask and Google's Gemini API

Example of what is being built:
Image description

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

  1. 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
  1. 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)
  1. 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.

  1. 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

  1. 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
  1. 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);
  1. 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)

  1. Environment Configuration: Secure API keys via environment variables
  2. Production Optimisation: Disabled debug mode, optimised CORS settings
  3. 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

  1. 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.

  2. Security Through Obscurity + Authentication

  3. Client ID system prevents unauthorised API usage

  4. CORS protection blocks cross-origin attacks

  5. Admin panel for dynamic client management

  6. User Experience Focus

  7. Smooth animations and transitions

  8. Mobile-responsive design

  9. Consistent British English for UK market

  10. Visual text input feedback

  11. Production-Ready Error Handling

  12. Graceful API failure recovery

  13. User-friendly error messages

  14. 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

  1. Security First: Implementing proper authentication from day one prevents future headaches
  2. Self-Contained Widgets: Avoiding external dependencies makes integration seamless
  3. User Experience Matters: Small details like text visibility and smooth animations significantly impact perception
  4. 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

Tags

ai #chatbot #flask #javascript #backend #frontend #heroku #nextjs