feat: chat module portability guide + fix mobile wave position

- 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)
This commit is contained in:
juanatsap
2026-04-09 13:08:17 +01:00
parent e56a86860f
commit 328faae953
2 changed files with 203 additions and 0 deletions
+197
View File
@@ -0,0 +1,197 @@
# 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
```bash
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 the `Instruction` prompt to describe YOUR data, not a CV
- **`QueryCVArgs` / `QueryCVResult`**: Rename and adapt the tool to query YOUR data source
- **`newQueryCVTool()`**: 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
```bash
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
```go
// 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
```html
{{template "chat-widget" .}}
{{template "chat-help-modal" .}}
```
Conditionally load CSS:
```html
{{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](https://google.github.io/adk-docs/)
- [Ollama API](https://github.com/ollama/ollama/blob/main/docs/api.md)
- [HTMX Documentation](https://htmx.org/docs/)
- [doc/28-AI-CHAT-AGENT.md](./28-AI-CHAT-AGENT.md) — Full technical documentation
- [doc/29-AI-CHAT-SHOWCASE.md](./29-AI-CHAT-SHOWCASE.md) — Public showcase writeup