~/TechPurAI
~/tutorials/ai-projects-with-python/adding-a-simple-web-ui-to-your-python-chatbot
beginner·part 3 of 22·3 min read

Adding a Simple Web UI to Your Python Chatbot

Updated Aug 16, 2026Python · AI

Part 2's chatbot works, but only in a terminal — no real Bright Leaf Coffee visitor could use it. This part turns it into a real, working web application using Flask, a genuinely minimal Python web framework, before this series moves to Django starting in part 4.

Real, practical setup

bash
pip install flask

The real, complete Flask application

python
# app.py
from flask import Flask, request, session, render_template
from shared.ai_client import get_client

app = Flask(__name__)
app.secret_key = "a-real-random-secret-key-here"

PLAN_DATA = """
- Gift Subscription: $18/mo, 1 bag, free shipping
- Monthly Subscription: $16/mo, 1 bag, free shipping
"""

SYSTEM_PROMPT = f"""You are a customer support assistant for Bright
Leaf Coffee. Real, current plan data:\n{PLAN_DATA}\nOnly answer using
this real data. Keep responses to 2-3 sentences."""

@app.route("/", methods=["GET", "POST"])
def chat():
    if "history" not in session:
        session["history"] = []

    if request.method == "POST":
        user_message = request.form["message"]
        session["history"].append({"role": "user", "content": user_message})

        client = get_client()
        response = client.messages.create(
            model="claude-sonnet-5",
            max_tokens=1024,
            system=SYSTEM_PROMPT,
            messages=session["history"],
        )

        answer = response.content[0].text
        session["history"].append({"role": "assistant", "content": answer})
        session.modified = True

    return render_template("chat.html", history=session.get("history", []))

if __name__ == "__main__":
    app.run(debug=True)

The real, minimal template

html
<!-- templates/chat.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Bright Leaf Coffee Support</title>
  </head>
  <body>
    <h1>Ask us anything</h1>
    <div>
      {% for message in history %}
        <p><strong>{{ message.role }}:</strong> {{ message.content }}</p>
      {% endfor %}
    </div>
    <form method="POST">
      <input type="text" name="message" required />
      <button type="submit">Send</button>
    </form>
  </body>
</html>

This is directly the HTML series' own real forms guidance applied here — a genuine, semantic <form> with a real, associated input, submitting to the same route that renders the page.

Why session — not a global variable — holds the real conversation

text
A global Python variable: shared across EVERY real visitor at once —
  one person's conversation would leak into another's
Flask's session: a real, per-visitor cookie-backed store — each real
  browser gets its own, separate conversation history

This is a genuinely important, real correctness detail specific to moving from a single-user terminal script to a real, multi-visitor web application — the exact same history list from part 2's chatbot now has to be scoped per real visitor, not shared globally across everyone hitting the server.

Why it matters

This session-scoping requirement is the real, first genuine difference between "a script that works" and "a real, deployable web feature" — it's a structural concern that has nothing to do with the AI logic itself, and it's exactly the kind of detail this series will keep surfacing as each project moves from a standalone script toward something genuinely production-shaped.

A real, honest limitation: Flask's session isn't built for this at scale

text
Flask's default session store keeps data in a real, signed browser
  cookie — genuinely fine for a small real demo, but a real,
  growing conversation history (part 9's context-window problem)
  eventually exceeds a practical real cookie size limit

A real, production chat feature would store conversation history server-side (a real database or cache), keyed by a session ID, rather than in the cookie itself — a genuine, deliberate simplification for this part's teaching purpose, revisited properly once this series reaches Django's real database layer in part 5.

Next: integrating an LLM API into a real Django project — the foundational pattern part 5's actual Django chatbot builds on.

VK

Vijay Kumar

Founder of TechPurAI — writing hands-on tutorials and honest tool breakdowns.

LinkedIn ↗
← previous2. Build an AI Chatbot with Pythonnext →4. Integrate an LLM API into a Django Project