- Agent prompt rewritten to first person ("I worked at...", "I built...")
- Bot avatar replaced with dni-thumb.jpeg (2.6KB, 56x56 retina)
- Greeting: "Pregúntame lo que quieras sobre mi currículum"
- Underlined "mi currículum" with floating tooltip disclaimer
- Every response ends with cordial email contact invitation
- Background photos now visible in production (random per load)
- Toggle button remains dev-only
Dev-only toggle button enables/disables photo backgrounds. Photos are
auto-discovered from static/images/backgrounds/ and randomly selected
on each page load. Production is unaffected — no button, no photo.
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
- Merge lang package into constants (add IsValidLang, ValidateLang, AllLangs)
- Rename internal/services to internal/email for consistency with pdf package
- Rename types to avoid redundancy: EmailService→Service, EmailConfig→Config
- Update all imports and references across codebase
- Delete internal/lang directory (functions moved to constants)
- Update all imports from 'constants' to 'c' for brevity
- Replace all 'constants.' references with 'c.'
- Fix remaining hardcoded content-type headers in httputil
- Fix remaining hardcoded User-Agent and Accept headers
- Rename CSRF receiver from 'c' to 'csrf' to avoid conflict
- Add ContentTypePlainSimple constant for Accept header matching
- Fix JSONCached to use proper integer formatting
- Create internal/constants package with all hardcoded values
(environment, cookies, themes, headers, routes, cache)
- Create internal/httputil package for HTTP helper functions
- Update all handlers and middleware to use centralized constants
- Reorganize documentation with numbered prefixes (00-26)
- Remove duplicate docs from validation folder and docs/
- Delete handlers/constants.go (moved to internal/constants)
Eliminate per-request file I/O by loading CV and UI data once at startup.
## Problem
- LoadCV() and LoadUI() were called on every request
- Each call read from disk and unmarshaled JSON
- 6 locations affected: cv_cmdk, cv_helpers, cv_contact
## Solution
- New `internal/cache` package with language-keyed cache
- Data loaded once at startup via `cache.New(["en", "es"])`
- Handlers use `h.dataCache.GetCV(lang)` / `GetUI(lang)`
- Thread-safe concurrent reads via sync.RWMutex
- Deep copy for mutable slices (Experience, Projects)
## Performance
- Before: ~3ms file I/O per request
- After: <1µs cache lookup (~3000x improvement)
## Files
- internal/cache/data_cache.go (new)
- internal/cache/data_cache_test.go (new)
- internal/cache/README.md (new)
- internal/handlers/cv.go (added dataCache field)
- internal/handlers/cv_*.go (use cache)
- main.go (initialize cache at startup)
- Fix golangci-lint errcheck errors by using t.Setenv() instead of os.Setenv()
- Add CSS bundle build step to deploy workflow for production
- Add graceful fallback to modular CSS if bundle doesn't exist
- Remove unused os import from preferences_test.go
1. Removed unused getPreferenceCookie and setPreferenceCookie functions
- These were flagged by golangci-lint as unused
- Cookie preferences now handled client-side via localStorage
- Removed unused net/http import
2. Fixed desktop sidebar accordion auto-opening
- Updated handleLandscapeAccordions() to open accordions in desktop view (≥769px)
- Sidebars now show content in desktop, landscape mobile, and portrait mobile
- Only keep accordions collapsed in portrait mobile for space saving
3. Created comprehensive multi-viewport test (66-comprehensive-all-viewports-test.mjs)
- Tests desktop (1278px), portrait mobile (375×667), landscape mobile (667×375)
- Validates sidebars, accordion state, content visibility, AND all buttons
- Checks button backdrop visibility in mobile views
- Every feature now has corresponding test coverage
Fixes golangci-lint errors:
- internal/handlers/cv_helpers.go:366: func getPreferenceCookie is unused
- internal/handlers/cv_helpers.go:375: func setPreferenceCookie is unused
- internal/handlers/cv_helpers.go:7: net/http imported and not used