<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<title>CFB Chat</title>
<style>
body { font-family: system-ui, -apple-system, sans-serif; margin: 0; background: #0b0b0c; color: #f2f2f2; }
.wrap { max-width: 820px; margin: 0 auto; padding: 12px; display: flex; flex-direction: column; height: 100vh; }
.header { font-weight: 700; padding: 8px 4px; opacity: 0.95; }
.chat { flex: 1; overflow-y: auto; padding: 10px 4px; display: flex; flex-direction: column; gap: 10px; }
.msg { padding: 10px 12px; border-radius: 12px; white-space: pre-wrap; line-height: 1.35; max-width: 85%; }
.user { align-self: flex-end; background: #1f3a8a; }
.bot { align-self: flex-start; background: #1f2937; }
.bar { display: flex; gap: 8px; padding: 10px 4px; }
input { flex: 1; padding: 12px; border-radius: 10px; border: 1px solid #333; background: #0f1115; color: #f2f2f2; font-size: 16px; }
button { padding: 12px 14px; border-radius: 10px; border: 0; background: #2563eb; color: white; font-weight: 600; cursor: pointer; }
button:disabled { opacity: 0.6; cursor: not-allowed; }
.small { font-size: 12px; opacity: 0.7; padding: 0 4px 8px; }
</style>
</head>
<body>
<div class="wrap">
<div class="header">CFB Chat</div>
<div class="small">Tip: Add to Home Screen for app-like use.</div>
<div id="chat" class="chat"></div>
<div class="bar">
<input id="input" placeholder="Ask about a game, team, player, last 5..." autocomplete="off" />
<button id="send">Send</button>
</div>
</div>
<script>
// For personal use: store a token in localStorage once (or hardcode during dev).
// In production, prefer a login flow.
const API_BASE = "/cfb-mcp/api"; // Caddy routes /cfb-mcp/api to the backend
const TOKEN_KEY = "cfb_token";
const THREAD_KEY = "cfb_thread_id";
const chatEl = document.getElementById("chat");
const inputEl = document.getElementById("input");
const sendBtn = document.getElementById("send");
function append(role, text) {
const div = document.createElement("div");
div.className = `msg ${role}`;
div.textContent = text;
chatEl.appendChild(div);
chatEl.scrollTop = chatEl.scrollHeight;
}
function getToken() {
let t = localStorage.getItem(TOKEN_KEY);
if (!t) {
t = prompt("Enter access token:");
if (t) localStorage.setItem(TOKEN_KEY, t);
}
return t || "";
}
function getThreadId() {
let id = localStorage.getItem(THREAD_KEY);
if (!id) {
id = crypto.randomUUID();
localStorage.setItem(THREAD_KEY, id);
}
return id;
}
async function send() {
const msg = inputEl.value.trim();
if (!msg) return;
const token = getToken();
if (!token) {
append("bot", "Please enter your access token to continue.");
return;
}
append("user", msg);
inputEl.value = "";
sendBtn.disabled = true;
try {
const res = await fetch(`${API_BASE}/chat`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
},
body: JSON.stringify({
message: msg,
thread_id: getThreadId()
})
});
if (!res.ok) {
const err = await res.text();
append("bot", `Error ${res.status}: ${err}`);
return;
}
const data = await res.json();
if (data.thread_id) localStorage.setItem(THREAD_KEY, data.thread_id);
append("bot", data.reply || "");
} catch (e) {
append("bot", `Network error: ${e.message}`);
} finally {
sendBtn.disabled = false;
inputEl.focus();
}
}
sendBtn.addEventListener("click", send);
inputEl.addEventListener("keydown", (e) => {
if (e.key === "Enter") send();
});
append("bot", "Ready. Ask me about CFB.");
inputEl.focus();
</script>
</body>
</html>