Files
cv-site/templates/index.html
T
juanatsap f5276431ea feat: add AI chat widget powered by ADK Go 1.0
Visitors can ask questions about the CV via a floating chat panel.
The agent uses Gemini to answer questions about experience, projects,
skills, and education by querying the cached CV JSON data.

- internal/chat/agent.go: LLM agent with query_cv tool that searches
  CV data by section (experience, projects, skills, etc.) with keyword filtering
- internal/chat/handler.go: POST /api/chat endpoint with session management,
  graceful degradation when GOOGLE_API_KEY is not set
- chat-widget.html: HTMX-powered floating chat panel with Hyperscript toggle
- _chat.css: Responsive chat UI with dark theme support
- Wired into existing architecture via dependency injection (CVHandler,
  routes, main.go) — zero breaking changes, all existing tests pass
2026-04-08 00:20:48 +01:00

70 lines
3.1 KiB
HTML

<!DOCTYPE html>
<html lang="{{if eq .Lang "es"}}es{{else}}en{{end}}">
{{template "head" .}}
<body {{if .ThemeClean}}class="theme-clean"{{end}}
_="on load call initScrollBehavior()
on scroll from window call handleScroll()
on keydown(key, target, ctrlKey, metaKey, altKey)
set ninjaKeys to #cmd-k-bar
set ninjaOpen to (ninjaKeys is not null and ninjaKeys.opened)
set skip to (target.tagName is 'INPUT' or target.tagName is 'TEXTAREA' or ninjaOpen)
set noMod to (not ctrlKey and not metaKey and not altKey)
if key is '?' and noMod and not skip then halt the event then call openModalShortcut('shortcuts-modal') end
if (key is 'l' or key is 'L') and noMod and not skip then halt the event then call handleToggleShortcut('lengthToggle', 'lengthToggleMenu') end
if (key is 'i' or key is 'I') and noMod and not skip then halt the event then call handleToggleShortcut('iconToggle', 'iconToggleMenu') end
if (key is 'v' or key is 'V') and noMod and not skip then halt the event then call handleToggleShortcut('themeToggle', 'themeToggleMenu') end
end">
<!-- ============================================ -->
<!-- TOP NAVIGATION & CONTROLS -->
<!-- ============================================ -->
<div id="top"></div>
{{template "action-bar" .}}
{{template "hamburger-menu" .}}
{{template "color-theme-switcher" .}}
<!-- ============================================ -->
<!-- MAIN CV CONTENT -->
<!-- ============================================ -->
<div id="zoom-wrapper" class="zoom-wrapper">
<div class="cv-container">
{{template "cv-content.html" .}}
</div>
</div>
<!-- ============================================ -->
<!-- PAGE FOOTER & NOTIFICATIONS -->
<!-- ============================================ -->
{{template "page-footer" .}}
{{template "error-toast" .}}
{{template "pdf-toast" .}}
<!-- ============================================ -->
<!-- FLOATING BUTTONS -->
<!-- ============================================ -->
<div class="fixed-buttons-backdrop no-print"></div>
{{template "back-to-top" .}}
{{template "info-button" .}}
{{template "download-button" .}}
{{template "print-friendly-button" .}}
{{template "contact-button" .}}
{{template "zoom-toggle-button" .}}
{{template "shortcuts-button" .}}
{{template "chat-widget" .}}
<!-- ============================================ -->
<!-- MODALS -->
<!-- ============================================ -->
{{template "info-modal" .}}
{{template "shortcuts-modal" .}}
{{template "pdf-modal" .}}
{{template "contact-modal" .}}
{{template "zoom-control" .}}
<!-- ============================================ -->
<!-- SCRIPTS & ANALYTICS -->
<!-- ============================================ -->
{{template "body-scripts" .}}
</body>
</html>