JavaScript Modules Documentation
Last Updated: October 8, 2025 Purpose: External JavaScript modules for brandonjplambert portfolio site Architecture: Modular, single-responsibility, zero dependencies
Overview
This directory contains JavaScript modules extracted from inline code as part of the October 8, 2025 technical debt reduction (Plan B). All modules follow clean code principles: separation of concerns, single responsibility, and DRY (Don’t Repeat Yourself).
Migration History:
- Before: 516 lines of inline JavaScript scattered across HTML files
- After: 4 focused modules totaling 516 lines (organized, testable, reusable)
- Reduction in HTML: ai-projects.html 994 → 167 lines (-83%)
Module Index
1. projects-filter.js (117 lines)
Purpose: Category filtering and navigation for AI projects page
Responsibilities:
- Filter projects by category (All, Educational, Creative, Infrastructure)
- Generate dynamic project list menu from visible projects
- Handle smooth scroll navigation to specific projects
- Apply highlight animation on project click
Key Functions:
filterProjects(category)- Filter and show/hide project cardsupdateProjectList()- Regenerate sidebar navigation menuscrollToProject(slug)- Smooth scroll to project with highlight
Usage:
<script src="/assets/js/projects-filter.js"></script>
Dependencies: None (vanilla JavaScript)
2. project-modal.js (113 lines)
Purpose: Development history modal rendering and interactions
Responsibilities:
- Render full-screen modal with project development timeline
- Display timeline phases (specification, pseudocode, architecture, etc.)
- Generate stats grid (lines of code, commits, technologies)
- Handle modal open/close interactions
Key Functions:
openModal(projectSlug)- Open modal for specific projectcloseModal()- Close modal and cleanuprenderTimeline(phases)- Generate timeline HTMLrenderStats(stats)- Generate stats grid HTML
Data Structure:
projectHistories = {
'project-slug': {
phases: [ /* timeline data */ ],
stats: { /* metrics */ },
transformations: [ /* before/after */ ]
}
}
Usage:
<button onclick="openModal('describe_it')">View History</button>
<script src="/assets/js/project-modal.js"></script>
Dependencies:
- Requires
projectHistoriesobject (generated inline via Liquid templates)
3. tech-tooltips.js (115 lines)
Purpose: Technology badge tooltip creation and positioning
Responsibilities:
- Create tooltips with full technology names and descriptions
- Position tooltips intelligently (avoid screen edges)
- Handle both mouse hover and touch interactions
- Auto-hide on scroll or click outside
Key Functions:
initTooltips()- Initialize all tech badges with tooltipsshowTooltip(badge, content)- Display tooltip with positioninghideTooltip(tooltip)- Hide and cleanup tooltippositionTooltip(badge, tooltip)- Smart positioning logic
Technology Data:
<span class="tech-badge" data-tech="nextjs">
Next.js|React framework for production
</span>
Usage:
<script src="/assets/js/tech-tooltips.js"></script>
Dependencies: None (vanilla JavaScript)
4. site-navigation.js (171 lines)
Purpose: Global navigation, mobile menu, and language switching
Responsibilities:
- Header scroll effects (show/hide on scroll)
- Mobile menu toggle/close functionality
- Language switcher (EN ↔ ES) with data-driven path mapping
- Language button active state management
- Responsive navigation display updates
Key Functions:
initNavigation(config)- Main initialization with configurationtoggleMobileMenu()- Open/close mobile overlayswitchLanguage(lang)- Change language with path mappinghandleScroll()- Header visibility on scroll
Configuration Structure:
const navConfig = {
currentLang: 'en', // From Liquid: page.lang
baseUrl: '', // From Liquid: site.baseurl
pathMap: {
toSpanish: { '/work/': '/es/trabajo/', ... },
toEnglish: { '/es/trabajo/': '/work/', ... }
}
};
Usage:
<script src="/assets/js/site-navigation.js"></script>
<script>
initNavigation({
currentLang: 'en',
baseUrl: '',
pathMap: { /* ... */ }
});
</script>
Dependencies:
- Requires configuration object (generated inline via Liquid templates)
- Uses ARIA attributes for accessibility
Architecture Principles
1. Single Responsibility Principle
Each module has ONE clear purpose:
projects-filter.js→ Filtering onlyproject-modal.js→ Modal rendering onlytech-tooltips.js→ Tooltip behavior onlysite-navigation.js→ Navigation & language switching only
2. Separation of Concerns
- HTML: Content and structure
- CSS: Presentation (in
_sass/files) - JavaScript: Behavior (these modules)
- Liquid: Server-side data generation
3. Zero Dependencies
All modules use vanilla JavaScript:
- No jQuery
- No external libraries
- No npm packages required
- Pure DOM manipulation
4. Progressive Enhancement
Modules check for required elements before initialization:
if (document.querySelector('.project-card')) {
// Initialize only if elements exist
}
5. IIFE Pattern for Encapsulation
Modules use Immediately Invoked Function Expressions to avoid global scope pollution:
(function() {
'use strict';
// Module code here
})();
Integration with Jekyll/Liquid
Server-Side Data Injection
Some modules require data generated by Jekyll:
projects-filter.js & tech-tooltips.js:
- No server-side data needed
- Pure client-side functionality
project-modal.js:
- Requires
projectHistoriesobject - Generated inline in HTML via Liquid loops
- Contains development history for all projects
site-navigation.js:
- Requires configuration object with
pathMap currentLangfrompage.langbaseUrlfromsite.baseurl
Loading Order
- Modules loaded at end of
<body>(non-blocking) - Inline initialization scripts run after modules load
- DOM-ready checks prevent race conditions
Browser Compatibility
Tested Browsers:
- ✅ Chrome 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ Edge 90+
JavaScript Features Used:
- ES6 arrow functions
const/letdeclarations- Template literals
- Array methods (forEach, filter, map)
- querySelector/querySelectorAll
- addEventListener
- classList API
- ARIA attributes
Fallbacks: None required (modern browsers only)
Performance Considerations
Module Size
projects-filter.js: 117 lines (~4.2 KB)
project-modal.js: 113 lines (~4.5 KB)
tech-tooltips.js: 115 lines (~4.1 KB)
site-navigation.js: 171 lines (~6.8 KB)
Total: 516 lines (~19.6 KB unminified)
Caching Strategy
- Modules cached by browser (static assets)
- HTML changes don’t require re-downloading JS
- Faster subsequent page loads
Loading Performance
- Before: 60KB inline (blocking render)
- After: 12KB HTML + 20KB JS modules (async, cacheable)
- Improvement: Better Core Web Vitals (LCP, FID)
Code Quality
- Zero console.logs in production modules
- All syntax validated before deployment
- Clean, readable code for maintainability
Testing
Manual Testing Checklist
- Project filtering works (all categories)
- History modals open/close correctly
- Technology tooltips appear on hover/touch
- Mobile menu opens/closes smoothly
- Language switching EN ↔ ES functional
- Navigation responsive on mobile
- Zero console errors in browser
- Works on iOS Safari
- Works on Android Chrome
Future: Automated Testing
Recommended: Add Jest for unit testing
// Example test
describe('projects-filter', () => {
test('filters projects by category', () => {
filterProjects('Educational');
// Assert only educational projects visible
});
});
Maintenance
Adding New Modules
- Create new
.jsfile in this directory - Follow IIFE pattern for encapsulation
- Use strict mode:
'use strict'; - Add DOM-ready checks
- Document in this README
- Test in multiple browsers
- Commit with clear message
Modifying Existing Modules
- Read module code and comments
- Make focused changes (single responsibility)
- Test functionality after changes
- Remove any console.logs before commit
- Update this README if API changes
- Commit with explanation of change
Debugging
- Open browser DevTools Console
- Check for JavaScript errors
- Use debugger statements or breakpoints
- Verify DOM elements exist
- Check ARIA attributes in inspector
Known Limitations
Inline Initialization Required
Some modules need server-side data from Liquid templates, requiring ~20 lines of inline initialization in HTML. This is an acceptable trade-off for Jekyll’s constraints.
No Build Pipeline
Currently no minification or bundling:
- Modules served unminified
- No source maps generated
- No code splitting
Future Improvement: Add esbuild or Webpack for production optimization
No Automated Tests
Manual testing required after changes. High priority for future: add Jest test framework.
Future Enhancements
Short-term (Next Month)
- Add JSDoc comments to all functions
- Create test suite with Jest
- Minify modules for production
- Add source maps for debugging
Medium-term (Next Quarter)
- Migrate to ES6 modules (
import/export) - Add build pipeline (esbuild)
- Implement code splitting
- Add error tracking (Sentry)
Long-term (Next Year)
- Consider framework (React/Vue/Svelte)
- TypeScript migration for type safety
- Component library abstraction
- Advanced performance optimizations
Troubleshooting
“Function not defined” errors
- Check script load order in HTML
- Verify
<script>tags are at end of<body> - Confirm module file path is correct
Tooltips not appearing
- Check for CSS conflicts in
_sass/_components.scss -
Verify data-techattribute format: “namedescription” - Inspect tooltip positioning logic for screen edge issues
Language switching doesn’t work
- Verify
pathMapconfiguration in inline script - Check browser localStorage for
preferredLanguage - Ensure both EN and ES pages exist at mapped paths
Mobile menu not opening
- Check ARIA attributes (
aria-expanded,aria-controls) - Verify mobile overlay CSS in
_sass/_layout.scss - Test on actual mobile device (not just browser DevTools)
Contact & Support
Project: Brandon JP Lambert Portfolio Repository: https://github.com/bjpl/bjpl.github.io Issues: Report via GitHub Issues Last Refactored: October 8, 2025 (Plan B technical debt reduction)
References
Related Documentation:
/docs/portfolio-review/03-technical-implementation.md- Technical review/daily_reports/2025-10-08.md- Plan B execution report/CLAUDE.md- Known Issues section (technical debt status)
Commits:
3af9e27- Extract JavaScript to modules (Oct 8, 2025)9f759f7- Extract CSS from ai-projects.html (Oct 8, 2025)79db8c4- Navigation deduplication & language switcher (Oct 8, 2025)
Generated as part of October 8, 2025 documentation updates.