Portfolio JavaScript Architecture
This directory contains the modular JavaScript architecture for the portfolio website, following the Single Responsibility Principle (SRP) and modern ES6 module patterns.
π Directory Structure
assets/js/
βββ main.js # Main entry point
βββ README.md # This documentation
βββ core/
β βββ PortfolioApp.js # Main application orchestrator
βββ utils/
β βββ ThemeManager.js # Theme switching & persistence
β βββ PerformanceMonitor.js # Performance monitoring
βββ effects/
β βββ ParticleSystem.js # Background particle animations
β βββ TypingAnimation.js # Typewriter text effects
βββ navigation/
β βββ NavigationEffects.js # Navbar scroll effects
β βββ MobileNavigation.js # Mobile menu functionality
β βββ SmoothScrolling.js # Smooth anchor link scrolling
βββ interactive/
β βββ InteractiveElements.js # Card tilt & button ripple effects
β βββ CursorEffects.js # Custom cursor effects
βββ animations/
βββ ScrollAnimations.js # Scroll-triggered animations
ποΈ Architecture Overview
Single Responsibility Principle (SRP)
Each class has a single, well-defined responsibility:
- ThemeManager: Handles theme switching and persistence
- PerformanceMonitor: Monitors and optimizes performance
- ParticleSystem: Manages background particle animations
- TypingAnimation: Handles typewriter text effects
- NavigationEffects: Manages navbar scroll effects
- MobileNavigation: Handles mobile menu functionality
- SmoothScrolling: Manages smooth anchor link scrolling
- InteractiveElements: Handles interactive UI effects
- CursorEffects: Manages custom cursor effects
- ScrollAnimations: Handles scroll-triggered animations
- PortfolioApp: Orchestrates all components
Event-Driven Communication
Components communicate through custom events rather than direct references:
themeChanged
: Dispatched when theme changesperformanceWarning
: Dispatched when performance issues detected
ES6 Modules
- Uses modern ES6 import/export syntax
- Each class is in its own file
- Clear dependency management
- Better tree-shaking and bundling support
π Usage
Main Entry Point
// main.js
import { PortfolioApp } from './core/PortfolioApp.js';
document.addEventListener('DOMContentLoaded', () => {
window.portfolioApp = new PortfolioApp();
});
Component Access
// Access any component through the main app
const themeManager = window.portfolioApp.getComponent('themeManager');
const particleSystem = window.portfolioApp.getComponent('particleSystem');
Adding New Components
- Create a new class file in the appropriate directory
- Export the class using ES6 export syntax
- Import and initialize in
PortfolioApp.js
- Add to the components Map
π§ Development
Adding a New Feature
- Create the component class in the appropriate directory
- Follow the naming convention:
PascalCase.js
- Export the class:
export class ComponentName
- Add to PortfolioApp: Import and initialize in the main app
- Document the component: Add to this README
Component Template
/**
* Component Name
* Brief description of responsibility
*/
export class ComponentName {
constructor() {
this.init();
}
init() {
// Initialize component
}
// Component methods
}
π Benefits
Maintainability
- Each component is focused and easy to understand
- Changes to one component donβt affect others
- Clear separation of concerns
Testability
- Each component can be tested independently
- Easy to mock dependencies
- Clear interfaces between components
Scalability
- Easy to add new features
- Components can be reused
- Clear architecture for team development
Performance
- Better tree-shaking
- Lazy loading support
- Optimized bundling
π οΈ Build Process
The modular structure supports modern build tools:
- Webpack: For bundling and optimization
- Rollup: For tree-shaking and ES6 modules
- Vite: For fast development and building
- Parcel: For zero-config bundling
π Debugging
Component Debugging
// Access component for debugging
console.log(window.portfolioApp.getComponent('themeManager'));
// Check if component exists
if (window.portfolioApp.getComponent('particleSystem')) {
console.log('Particle system is active');
}
Event Debugging
// Listen to custom events
document.addEventListener('themeChanged', (event) => {
console.log('Theme changed to:', event.detail.theme);
});
document.addEventListener('performanceWarning', (event) => {
console.log('Performance warning:', event.detail);
});
π Best Practices
- Single Responsibility: Each class should have one clear purpose
- Event-Driven: Use custom events for component communication
- Error Handling: Always handle potential errors gracefully
- Documentation: Document each componentβs purpose and usage
- Naming: Use clear, descriptive names for classes and methods
- Testing: Write tests for each component independently
π Migration from Monolithic
This modular structure replaces the previous monolithic main.js
file. Benefits:
- Before: 774 lines in a single file
- After: 11 focused modules with clear responsibilities
- Maintainability: Significantly improved
- Team Development: Multiple developers can work on different components
- Code Reuse: Components can be reused in other projects