Files
cv-site/PROJECT-MEMORY.md
T
juanatsap 8b6620f93b docs: add PROJECT-MEMORY.md - critical developer knowledge
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
2025-11-17 13:51:17 +00:00

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 def statements 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:

  1. Action bar (desktop) - #lengthToggle, #iconToggle, #themeToggle
  2. 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 functions
  • templates/partials/navigation/view-controls.html - Action bar toggles
  • templates/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 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)

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

  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
  • 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
  • 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 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:

  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
  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: 8 systematic tests, 100% core features Critical Memory Files: This file + ~/.claude/cv-icons-migration.md