Comprehensive memory document capturing: - ✅ Non-negotiable rules (icon naming, hyperscript limits, toggle sync) - ✅ Historical bugs and fixes (icon toggle, parser crash, desync) - ✅ Architecture decisions (HTMX+Hyperscript, Bun, file organization) - ✅ Standard patterns (toggles, keyboard shortcuts, hyperscript usage) - ✅ Development workflow (test-first, regression tests) - ✅ Common operations (adding toggles, debugging) - ✅ Lessons learned (naming, testing, framework limits) This document is the second most important after tests/README.md Read before making ANY changes to the project
13 KiB
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"
// ✅ 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 (CRITICAL)
Maximum 3 def statements total across ALL files
Hyperscript 0.9.14 has a hard parser limit:
- ✅ Max 3
defstatements across entire application - ✅ Count includes ALL
<script type="_hyperscript">blocks - ✅ Count includes ALL inline
_="def ..."attributes
Solution: Move complex logic to JavaScript functions
// ✅ 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 (CRITICAL)
Action bar and menu toggles MUST stay synchronized
Every toggle exists in TWO places:
- Action bar (desktop) -
#lengthToggle,#iconToggle,#themeToggle - Hamburger menu (mobile) -
#lengthToggleMenu,#iconToggleMenu,#themeToggleMenu
Required behavior:
- ✅ 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
// ✅ 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;
}
}
Test that enforces this: tests/mjs/1-toggles.test.mjs
4. Real-Time Rendering (CRITICAL)
ALL UI changes MUST happen without page refresh
// ✅ CORRECT - Immediate DOM update
paper.classList.add('show-icons'); // CSS change happens instantly
// ❌ WRONG - Requires refresh
localStorage.setItem('cv-icons', 'true'); // Only storage, no visual change
Why: Users expect instant feedback. Any delay or refresh requirement feels broken.
Test that enforces this: tests/mjs/1-toggles.test.mjs (with screenshot verification)
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
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:
bun tests/run-all.mjs
Reference: tests/README.md, tests/TEST-SUMMARY.md
📋 Architecture Decisions
Tech Stack
Runtime & Framework:
- ✅ Bun (JavaScript runtime)
- ✅ Hono (Web framework)
- ✅ HTMX (Hypermedia)
- ✅ Hyperscript 0.9.14 (Event handling - LIMITED USE)
Why HTMX + Hyperscript:
- Server-driven UI (hypermedia pattern)
- Minimal JavaScript
- Progressive enhancement
- Real-time updates via SSE
Why Bun:
- Fast runtime
- Built-in TypeScript
- Native test runner
- Single tool for everything
File Organization
cv/
├── server.ts # Hono server
├── static/
│ ├── js/
│ │ └── cv-functions.js # Global functions (toggles, keyboard shortcuts)
│ └── css/
│ └── styles.css
├── templates/
│ ├── index.html # Main template
│ └── partials/
│ └── navigation/
│ ├── view-controls.html # Action bar toggles
│ └── hamburger-menu.html # Mobile menu
└── tests/
└── mjs/ # Systematic test suite
Critical files:
static/js/cv-functions.js- All global toggle/keyboard functionstemplates/partials/navigation/view-controls.html- Action bar togglestemplates/partials/navigation/hamburger-menu.html- Mobile menu toggles
🐛 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 in1-toggles.test.mjsMemory:~/.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
- Read relevant test: Understand what's being tested
- Run the test: See current behavior
- Make changes: Code + test updates together
- Run test again: Verify it passes
- Run ALL tests:
bun tests/run-all.mjs - Manual verification: Browser stays open - check it yourself
- Commit: With clear description
When Adding a Feature
- Write test FIRST (test what you want to build)
- Implement feature
- Test passes (feature works)
- Update documentation (TEST-SUMMARY.md)
- Commit both (code + test together)
When Fixing a Bug
- Write regression test (reproduces the bug)
- Test FAILS (proves bug exists)
- Fix the bug
- Test PASSES (proves fix works)
- Commit both (fix + test together)
📝 Key Patterns
Toggle Pattern (Standard)
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)
<!-- ✅ 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
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
- Add to HTML: Action bar + menu
- Add localStorage key: Choose naming convention
- Add toggle function: Follow standard pattern
- Add keyboard shortcut: Optional but recommended
- Add to test: Update
1-toggles.test.mjs - Add to keyboard test: If you added shortcut
- Run ALL tests
Changing Class Names
- Search globally: Find ALL references
- Update JavaScript: cv-functions.js
- Update CSS: All stylesheets
- Update HTML: All templates
- Update tests: Search for old name
- Create memory file:
~/.claude/name-migration.md - 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 accountabilityHYPERSCRIPT-RULES.md- Parser limits and workarounds~/.claude/cv-icons-migration.md- Icon naming convention
Reference Documentation
tests/TEST-SUMMARY.md- Complete test documentationtests/mjs/README.md- Test structure and patternsMODERN-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 places (action bar + menu) means every change must update both. 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:
- Read this document
- Read
tests/README.md - Run
bun tests/run-all.mjs - Understand which test covers what you're changing
- Make your changes + update tests together
- Run ALL tests again
- Manual verification in browser
- Update this document if you learn something new
When you hit a bug:
- Which test should have caught this?
- Why didn't it?
- Fix the test FIRST
- Then fix the bug
- 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: 8 systematic tests, 100% core features
Critical Memory Files: This file + ~/.claude/cv-icons-migration.md