12. UI Polish

Chapter 12 of 15 · 20 min

Four improvements that make the chatbot usable:

Auto-scroll. After each token, scroll the chat div to the bottom:

function scrollToBottom() {
  const chat = document.getElementById("chat");
  chat.scrollTop = chat.scrollHeight;
}

Markdown rendering. Use a lightweight regex replacer for bold, italic, inline code, and code blocks—no external library needed:

function renderMarkdown(text) {
  return text
    .replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
    .replace(/\*(.+?)\*/g, "<em>$1</em>")
    .replace(/`([^`]+)`/g, "<code>$1</code>")
    .replace(/```([\s\S]+?)```/g, "<pre><code>$1</code></pre>");
}

Typing indicator. Show "..." while waiting for the first token:

let typingIndicator = null;
async function sendMessage() {
  typingIndicator = document.createElement("div");
  typingIndicator.textContent = "Model is thinking...";
  chat.appendChild(typingIndicator);
  // ... stream response ...
  if (typingIndicator) typingIndicator.remove();
}

Clear button. Add a clear-history button that POSTs to /sessions/{sessionId}/clear and reloads the chat div.

Failure mode: The markdown regex will corrupt text that contains ** as part of a URL. Use a proper tokenizer for production.

Local verification checkpoint

Run the smallest example from this chapter in a local workspace and record the package version, runtime, data path, and observed output. If the result depends on model size, vector count, CPU/GPU backend, or available memory, note that constraint beside the exercise so the lesson remains reproducible.

Local verification checkpoint

Run the smallest example from this chapter in a local workspace and record the package version, runtime, data path, and observed output. If the result depends on model size, vector count, CPU/GPU backend, or available memory, note that constraint beside the exercise so the lesson remains reproducible.

EXERCISE

Add a token counter showing estimated prompt+response tokens (count characters / 4 as a rough proxy) after each response completes.