328faae953
- doc/30-CHAT-MODULE-PORTABILITY.md: step-by-step guide to port the chat agent to other Go apps (files, dependencies, customization) - Fix wave emoji position on mobile (follows button to bottom:5rem right:1rem)
6.5 KiB
6.5 KiB
Chat Module Portability Guide
Project: CV Interactive Website
Last Updated: 2026-04-09
Tag Reference: v1.2.0
Overview
The AI chat agent is a self-contained module that can be ported to other Go web applications. It provides an embeddable chat widget powered by Google Gemini (production) with Ollama fallback (local development).
Module Files
Backend (Go)
| File | Purpose | Dependencies |
|---|---|---|
internal/chat/agent.go |
ADK agent definition, tools, prompt | google.golang.org/adk, your data model |
internal/chat/handler.go |
HTTP handlers, provider init, warmup, icon injection | internal/chat/agent.go, internal/cache |
internal/chat/ollama.go |
Ollama/OpenAI-compatible LLM adapter | None (standalone) |
Frontend (HTML + CSS + JS)
| File | Purpose |
|---|---|
templates/partials/widgets/chat-widget.html |
Complete widget: panel, header, messages, input, JS |
templates/partials/modals/chat-help-modal.html |
Help accordion with suggested questions |
static/css/04-interactive/_chat.css |
All styling: layout modes, responsive, dark mode, animations |
Configuration
| File | Keys |
|---|---|
.env |
GOOGLE_API_KEY, OLLAMA_MODEL, OLLAMA_HOST |
config/systemd/cv.service |
EnvironmentFile for production secrets |
Go Dependencies
Add to your go.mod:
google.golang.org/adk v1.0.0
google.golang.org/genai v1.x.x
Integration Steps
1. Copy the backend files
mkdir -p internal/chat
cp internal/chat/agent.go internal/chat/handler.go internal/chat/ollama.go YOUR_PROJECT/internal/chat/
2. Adapt agent.go
This is the only file that needs significant changes per project:
NewAgent(): Change theInstructionprompt to describe YOUR data, not a CVQueryCVArgs/QueryCVResult: Rename and adapt the tool to query YOUR data sourcenewQueryCVTool(): Replace with a tool that queries your application's data- Filter functions: Adapt
filterExperience(),filterProjects(), etc. to your data model
3. Adapt handler.go
Minimal changes needed:
buildIconMap(): Remove or adapt for your icon system (sprite sheets, image files)formatResponse(): The markdown→HTML converter works generically. Icon injection is optional.NewHandler(dataCache): Change the parameter type to your data source
4. Keep ollama.go as-is
This is a generic Ollama/OpenAI-compatible adapter. No changes needed — it implements model.LLM interface for any ADK agent.
5. Copy frontend files
cp templates/partials/widgets/chat-widget.html YOUR_PROJECT/templates/partials/widgets/
cp templates/partials/modals/chat-help-modal.html YOUR_PROJECT/templates/partials/modals/
cp static/css/04-interactive/_chat.css YOUR_PROJECT/static/css/
6. Adapt the widget
- Change suggested questions (chips) to match your domain
- Change help modal questions
- Update welcome message
- Adjust CSS variables to match your theme
7. Register routes
// In your routes setup:
chatHandler := chat.NewHandler(yourDataSource)
mux.Handle("/api/chat", rateLimiter.Middleware(http.HandlerFunc(chatHandler.HandleChat)))
mux.HandleFunc("/api/chat/warmup", chatHandler.HandleWarmup)
mux.HandleFunc("/api/chat/status", chatHandler.HandleStatus)
8. Include in templates
{{template "chat-widget" .}}
{{template "chat-help-modal" .}}
Conditionally load CSS:
{{if .ChatEnabled}}
<link rel="stylesheet" href="/static/css/_chat.css">
{{end}}
Architecture Overview
User clicks chat → HTMX POST /api/chat
↓
handler.HandleChat()
↓
runAgent(primary) ← Gemini or Ollama
↓
ADK Runner loop:
1. LLM sees prompt + user message
2. LLM calls query tool (function calling)
3. Tool queries your data source
4. LLM generates response from tool results
↓
formatResponse() → HTML with icons + links
↓
HTMX appends to #chat-messages
Features Included
| Feature | What it does |
|---|---|
| Dual provider | Gemini (prod) + Ollama (dev) with auto-fallback |
| Auto-warmup | Local model pre-loaded on startup in dev mode |
| Status polling | /api/chat/status → "Initializing AI model..." indicator |
| 4 layout modes | Compact, Side Panel, Floating (draggable), Full Screen |
| Mobile responsive | Split mode on phones, desktop modes hidden |
| User + bot avatars | Teams-style bubble layout |
| Inline icons | Sprite + image fallback next to navigation links |
| External links | [text](https://...) rendered as clickable links |
| Wave greeting | 👋 animation to attract visitors |
| Help modal | Accordion with suggested questions |
| Chip questions | One-click with instant bubble rendering |
| Rate limiting | 30 req/hour per IP (configurable) |
| Dark mode | Lighter panel to contrast with dark backgrounds |
| HTMX timeout | 120s for slow local models |
Testing
| Test file | Assertions | Covers |
|---|---|---|
tests/mjs/84-chat-layout-modes.test.mjs |
38 | Desktop layout modes, drag, switching, avatars |
tests/mjs/85-chat-mobile.test.mjs |
79 | Mobile on 3 iPhone viewports + desktop sanity |
tests/mjs/83-chat-mascot.test.mjs |
39 | Chat UX, chips, responses, navigation |
What to Customize Per Project
| Component | What to change |
|---|---|
| Agent prompt | agent.go — describe YOUR domain, not a CV |
| Query tool | agent.go — query YOUR data source |
| Suggested questions | chat-widget.html — chips and help modal |
| Welcome message | chat-widget.html — greeting text |
| Icons/sprites | handler.go — buildIconMap() and CSS |
| CSS theme | _chat.css — colors, --accent-green, fonts |
| Rate limits | routes.go — requests per hour |
References
- Google ADK Go Documentation
- Ollama API
- HTMX Documentation
- doc/28-AI-CHAT-AGENT.md — Full technical documentation
- doc/29-AI-CHAT-SHOWCASE.md — Public showcase writeup