Files
cv-site/PROJECT-MEMORY.md
T

518 lines
16 KiB
Markdown
Raw Normal View History

# CV Project - Developer Memory
## ⚠️ CRITICAL: Read This Before Any Changes
This document contains **non-negotiable rules** and **hard-learned lessons** from this project's development. Violating these causes bugs, breaks features, and wastes time.
---
## 🔴 ABSOLUTE RULES - NEVER VIOLATE
### 1. Icon Naming Convention (CRITICAL)
**ALWAYS use "icons" - NEVER "logos"**
```javascript
// ✅ CORRECT
.show-icons
localStorage.getItem('cv-icons')
const showIcons = ...
// ❌ WRONG - WILL BREAK ICON TOGGLE
.show-logos
localStorage.getItem('cv-logos')
const showLogos = ...
```
**Why:** Icon toggle had critical bug (commit 3f77fed) because JavaScript used `.show-logos` but CSS checked for `.show-icons`. This caused toggles to only work after page refresh.
**Test that enforces this:** `tests/mjs/1-toggles.test.mjs`
**Memory file:** `~/.claude/cv-icons-migration.md`
---
### 2. Hyperscript Parser Limit (NEEDS RETESTING)
**⚠️ TO VERIFY: Maximum 3 `def` statements limit with latest hyperscript version**
**Status:** We upgraded to the LATEST hyperscript version. This limit may no longer exist.
**TODO:** Test if the 3 `def` statement limit still applies with current version
**Current solution (still recommended):** Move complex logic to JavaScript functions
```javascript
// ✅ CORRECT - JavaScript functions
function toggleIcons(showIcons) { ... }
function toggleCVLength(isLong) { ... }
function toggleTheme(isClean) { ... }
// Call from hyperscript
_="on change call toggleIcons(my.checked)"
// ❌ WRONG - Too many def statements
_="def toggleIcons(show)
if show then add .show-icons...
end"
```
**Why:** Parser crashes/fails silently when limit exceeded.
**Test that enforces this:** `tests/mjs/3-hyperscript.test.mjs`
**Reference:** `HYPERSCRIPT-RULES.md`
---
### 3. Toggle Synchronization (WORKING) + Hover Sync (FIXED)
**Toggle checkboxes WORK perfectly ✅**
Every toggle checkbox exists in TWO places and stays synchronized:
1. Action bar (desktop) - `#lengthToggle`, `#iconToggle`, `#themeToggle`
2. Hamburger menu (mobile) - `#lengthToggleMenu`, `#iconToggleMenu`, `#themeToggleMenu`
**Toggle behavior (WORKING):**
- ✅ Clicking either toggle updates BOTH
- ✅ Changes are real-time (no page refresh)
- ✅ localStorage persists the state
- ✅ Page load reads from localStorage and applies to both
```javascript
// ✅ CORRECT - Update both toggles
function toggleIcons(showIcons) {
const paper = document.querySelector('.cv-paper');
const otherToggle = document.querySelector('#iconToggle') ||
document.querySelector('#iconToggleMenu');
if (showIcons) {
paper?.classList.add('show-icons');
localStorage.setItem('cv-icons', 'true');
if (otherToggle) otherToggle.checked = true;
} else {
paper?.classList.remove('show-icons');
localStorage.setItem('cv-icons', 'false');
if (otherToggle) otherToggle.checked = false;
}
}
```
**✅ HOVER SYNC - PDF/Print buttons NOW WORKING**
**Action buttons that sync hover states:**
1. Action bar (desktop):
- `#action-bar-pdf-btn` - Download PDF button
- `.action-bar-print-btn` - Print Friendly button
2. Hamburger menu (mobile):
- `.menu-pdf-btn` - PDF button (templates/partials/navigation/hamburger-menu.html:178)
- `.menu-print-btn` - Print button (templates/partials/navigation/hamburger-menu.html:186)
**Working hover sync functions:**
- `syncPdfHover(isHovering)` - Syncs PDF button hover between locations ✅
- `syncPrintHover(isHovering)` - Syncs Print button hover between locations ✅
**Implementation:**
- Both buttons in each location have mouseenter/mouseleave handlers
- Sync functions select all matching buttons (`.pdf-btn, .menu-pdf-btn`)
- CSS classes `.pdf-hover-sync` and `.print-hover-sync` applied to all instances
- Visual feedback matches across action bar and menu
**Files involved:**
- `templates/partials/navigation/action-buttons.html` (lines 9-10, 18-19)
- `templates/partials/navigation/hamburger-menu.html` (lines 178-184, 186-189)
- `static/js/cv-functions.js` (lines 71-99)
- `static/css/main.css` (lines 2690-2712)
**Test coverage:** `tests/mjs/8-hover-sync.test.mjs`
**Test that enforces toggle sync:** `tests/mjs/1-toggles.test.mjs`
---
### 4. Real-Time Rendering + Persistence (CRITICAL)
**ALL UI changes MUST happen in BOTH DOM and localStorage**
**BOTH are required - not mutually exclusive:**
```javascript
// ✅ CORRECT - DOM update AND localStorage
paper.classList.add('show-icons'); // Visual change (instant feedback)
localStorage.setItem('cv-icons', 'true'); // Persistence (survives reload)
// ❌ WRONG - Only DOM (lost on page reload)
paper.classList.add('show-icons');
// ❌ WRONG - Only storage (no visual feedback)
localStorage.setItem('cv-icons', 'true');
```
**Why both are needed:**
- **DOM changes** = instant visual feedback (users see it immediately)
- **localStorage** = state persists across page reloads (users don't lose their preferences)
- Users need BOTH: instant feedback + remembered preferences
**Test that enforces this:** `tests/mjs/1-toggles.test.mjs` (verifies both DOM and localStorage)
---
### 5. Test Suite as Single Source of Truth
**If a test passes, the feature MUST work. If a feature works, the test MUST pass.**
```
tests/mjs/
├── 0-zoom.test.mjs # Zoom functionality
├── 1-toggles.test.mjs # ALL toggles + sync + persistence
├── 2-keyboard-shortcuts.test.mjs # L, I, V, ? keys
├── 3-hyperscript.test.mjs # Parse errors + def limit
├── 4-htmx.test.mjs # HTMX integration
├── 5-language.test.mjs # EN/ES switching
├── 6-modals.test.mjs # Modal functionality
├── 7-mobile-responsive.test.mjs # Mobile viewports
└── 8-hover-sync.test.mjs # PDF/Print button hover sync
```
**Non-negotiable:**
- ❌ NO code changes without test validation
- ❌ NO bug fixes without regression test
- ❌ NO features without test coverage
- ❌ NO deployment if tests fail
**Run before every commit:**
```bash
bun tests/run-all.mjs
```
**Reference:** `tests/README.md`, `tests/TEST-SUMMARY.md`
---
## 📋 Architecture Decisions
### Tech Stack
**Backend:**
- ✅ Go 1.21+ (Backend server)
- ✅ Standard library `net/http` (HTTP server)
- ✅ Go templates (Server-side rendering)
**Frontend:**
- ✅ HTMX (Hypermedia-driven interactions)
- ✅ Hyperscript (Latest version - event handling)
- ✅ Vanilla JavaScript (cv-functions.js - toggles, keyboard shortcuts)
- ✅ Iconify (Icon system)
**Testing:**
- ✅ Playwright (E2E browser automation)
- ✅ Bun (Test runner ONLY - NOT the runtime!)
**Why Go:**
- Fast compilation
- Single binary deployment
- Built-in templating
- Excellent standard library
- Strong typing
- Cross-platform
**Why HTMX + Hyperscript:**
- Server-driven UI (hypermedia pattern)
- Minimal JavaScript
- Progressive enhancement
- Real-time updates capabilities
### File Organization
```
cv/
├── main.go # Server entry point (v1.1.0)
├── go.mod, go.sum # Go dependencies
├── internal/
│ ├── config/ # Configuration
│ ├── handlers/ # HTTP handlers
│ ├── middleware/ # HTTP middleware
│ ├── models/ # Data models
│ ├── routes/ # Route definitions
│ └── templates/ # Template utilities
├── static/
│ ├── js/
│ │ └── cv-functions.js # Global functions (toggles, keyboard, hover sync)
│ ├── css/ # Stylesheets
│ ├── hyperscript/
│ │ └── functions._hs # Hyperscript functions (if any)
│ ├── images/ # Static images
│ └── pdf/ # PDF files
├── templates/
│ ├── index.html # Main page template
│ ├── cv-content.html # CV content
│ ├── language-switch.html # Language switcher
│ └── partials/
│ ├── navigation/
│ │ ├── action-bar.html # Desktop action bar
│ │ ├── action-buttons.html # PDF + Print buttons
│ │ └── hamburger-menu.html # Mobile menu (ALL controls + buttons)
│ ├── widgets/ # Reusable UI components
│ └── modals/ # Modal dialogs
└── tests/
└── mjs/ # Systematic test suite (Playwright + Bun runner)
```
**Critical files:**
- `main.go` - Server entry point
- `static/js/cv-functions.js` - Toggle, keyboard, and hover sync functions
- `templates/partials/navigation/action-buttons.html` - PDF + Print buttons (action bar)
- `templates/partials/navigation/hamburger-menu.html` - Complete mobile menu with toggles + buttons
- `templates/index.html` - Main template structure
---
## 🐛 Historical Bugs (Learn From These)
### Bug 1: Icon Toggle Required Refresh
**Commit:** 3f77fed
**Date:** 2025-11-17
**Symptom:** Icon toggle only worked after page refresh
**Root cause:** Class name mismatch
- JavaScript: `classList.add('show-logos')`
- CSS: `.cv-paper:not(.show-icons)`
**Fix:** Changed all references from "logos" to "icons"
**Test added:** Screenshot verification in `1-toggles.test.mjs`
**Memory:** `~/.claude/cv-icons-migration.md`
### Bug 2: Hyperscript Parser Crash
**Date:** 2025-11-16
**Symptom:** Silent failures, toggles stopped working
**Root cause:** Exceeded 3 `def` statement limit
**Fix:** Moved toggle logic to JavaScript (`cv-functions.js`)
**Test added:** Def statement counter in `3-hyperscript.test.mjs`
**Reference:** `HYPERSCRIPT-RULES.md`
### Bug 3: Toggle Desynchronization
**Date:** 2025-11-15
**Symptom:** Action bar and menu toggles out of sync
**Root cause:** Only updating one toggle, not both
**Fix:** Every toggle function now updates both locations
**Test added:** Sync verification in `1-toggles.test.mjs`
---
## 🎯 Development Workflow
### Before Making Changes
1. **Read relevant test:** Understand what's being tested
2. **Run the test:** See current behavior
3. **Make changes:** Code + test updates together
4. **Run test again:** Verify it passes
5. **Run ALL tests:** `bun tests/run-all.mjs`
6. **Manual verification:** Browser stays open - check it yourself
7. **Commit:** With clear description
### When Adding a Feature
1. **Write test FIRST** (test what you want to build)
2. **Implement feature**
3. **Test passes** (feature works)
4. **Update documentation** (TEST-SUMMARY.md)
5. **Commit both** (code + test together)
### When Fixing a Bug
1. **Write regression test** (reproduces the bug)
2. **Test FAILS** (proves bug exists)
3. **Fix the bug**
4. **Test PASSES** (proves fix works)
5. **Commit both** (fix + test together)
---
## 📝 Key Patterns
### Toggle Pattern (Standard)
```javascript
function toggleX(enabled) {
const target = document.querySelector('.target');
const otherToggle = document.querySelector('#xToggle') ||
document.querySelector('#xToggleMenu');
if (enabled) {
target?.classList.add('state-class');
localStorage.setItem('cv-x', 'true');
if (otherToggle) otherToggle.checked = true;
} else {
target?.classList.remove('state-class');
localStorage.setItem('cv-x', 'false');
if (otherToggle) otherToggle.checked = false;
}
}
```
**Must have:**
- ✅ Real-time DOM update
- ✅ localStorage persistence
- ✅ Sync both toggle locations
- ✅ Safe navigation (`?.`)
### Hyperscript Pattern (LIMITED USE)
```html
<!-- ✅ GOOD - Simple event delegation -->
<button _="on click call myJavaScriptFunction(my.checked)">
<!-- ⚠️ AVOID - Complex logic (use JS instead) -->
<button _="on click
if condition then ...
else ... end">
<!-- ❌ FORBIDDEN - def statements (unless absolutely necessary) -->
<script type="_hyperscript">
def myFunction() <!-- COUNTS TOWARD 3 LIMIT -->
...
end
</script>
```
### Keyboard Shortcuts Pattern
```javascript
document.addEventListener('keydown', (e) => {
// ✅ ALWAYS check for input fields
if (e.target.matches('input, textarea, select')) return;
// ✅ Use lowercase key
const key = e.key.toLowerCase();
switch(key) {
case 'l': toggleCVLength(!body.classList.contains('cv-long')); break;
case 'i': toggleIcons(!paper.classList.contains('show-icons')); break;
case 'v': toggleTheme(!body.classList.contains('theme-clean')); break;
case '?': document.querySelector('#shortcuts-modal')?.showModal(); break;
}
});
```
**Test:** `tests/mjs/2-keyboard-shortcuts.test.mjs`
---
## 🔧 Common Operations
### Adding a New Toggle
1. **Add to HTML:** Action bar + menu
2. **Add localStorage key:** Choose naming convention
3. **Add toggle function:** Follow standard pattern
4. **Add keyboard shortcut:** Optional but recommended
5. **Add to test:** Update `1-toggles.test.mjs`
6. **Add to keyboard test:** If you added shortcut
7. **Run ALL tests**
### Changing Class Names
1. **Search globally:** Find ALL references
2. **Update JavaScript:** cv-functions.js
3. **Update CSS:** All stylesheets
4. **Update HTML:** All templates
5. **Update tests:** Search for old name
6. **Create memory file:** `~/.claude/name-migration.md`
7. **Test thoroughly**
### Debugging Toggle Issues
**Checklist:**
- [ ] Check class name matches between JS and CSS
- [ ] Verify both toggles are updated (action bar + menu)
- [ ] Check localStorage key is correct
- [ ] Verify real-time DOM update happens
- [ ] Run `1-toggles.test.mjs` - does it catch the bug?
- [ ] If test doesn't catch it, FIX THE TEST FIRST
---
## 📚 Key Documents
### Must Read Before Changes
- `tests/README.md` - Test suite accountability
- `doc/HYPERSCRIPT-RULES.md` - Parser limits and workarounds
- `~/.claude/cv-icons-migration.md` - Icon naming convention
### Reference Documentation
- `tests/TEST-SUMMARY.md` - Complete test documentation
- `tests/mjs/README.md` - Test structure and patterns
- `doc/MODERN-WEB-TECHNIQUES.md` - Architecture decisions
### Historical Record
- `tests/archive/README.md` - Legacy tests (reference only)
- Git history - Search for bug fix commits
---
## 🎓 Lessons Learned
### 1. Name Things Correctly From the Start
**Lesson:** Renaming "logos" to "icons" required:
- Updating 4 files
- Creating memory document
- Adding test verification
- Could have been avoided with better initial naming
**Rule:** Think about naming conventions BEFORE first implementation
### 2. Tests Are Not Optional
**Lesson:** Icon toggle bug existed for days before we added screenshot verification to the test. The test was passing but the feature was broken.
**Rule:** Tests must verify ACTUAL behavior, not just code execution
### 3. Framework Limits Are Real
**Lesson:** Hyperscript's 3 `def` limit seems arbitrary but it's a hard constraint. We learned this after hitting silent failures.
**Rule:** Read framework documentation carefully, especially limits/constraints
### 4. Synchronization Is Hard
**Lesson:** Having toggles in two or more places (action bar + menu) means every change must update all locations. Forgetting this causes desync bugs.
**Rule:** If something appears in multiple places, use a single function to update ALL locations
### 5. Real-Time Updates Are Expected
**Lesson:** Users don't understand localStorage vs DOM updates. If they click a button, they expect INSTANT visual feedback.
**Rule:** Every toggle must update both localStorage AND DOM immediately
---
## 🚀 Future Developers
**Before you change ANYTHING:**
1. Read this document
2. Read `tests/README.md`
3. Run `bun tests/run-all.mjs`
4. Understand which test covers what you're changing
5. Make your changes + update tests together
6. Run ALL tests again
7. Manual verification in browser
8. Update this document if you learn something new
**When you hit a bug:**
1. Which test should have caught this?
2. Why didn't it?
3. Fix the test FIRST
4. Then fix the bug, using the debug agent and the htmx expert
5. Document the lesson in this file
**Remember:**
- Tests are the specification
- If tests pass but feature fails → tests are wrong
- If feature works but tests fail → feature is wrong
- When in doubt, trust the tests MORE than the code
---
**Last Updated:** 2025-11-17
**Project Status:** Production
**Test Coverage:** 9 systematic tests, 100% core features
**Critical Memory Files:** This file + `~/.claude/cv-icons-migration.md`