Skip to content

Lwazi-M/Personal-Portfolio

Repository files navigation

3D Interactive Portfolio 🚀

A high-performance, immersive portfolio built with React, Three.js (Fiber), and Tailwind CSS.

This project represents a complete architectural overhaul from a static HTML website to a scalable Single Page Application (SPA). It features physics-based 3D interactions, cinema-quality page transitions, and a serverless contact engine.


📖 The Engineering Journey: Static HTML to Modern React

The "Before" State (The Monolith)

Originally, this portfolio was built using vanilla HTML, CSS, and JavaScript. While functional, it suffered from scalability issues common in static sites:

  • Monolithic Files: index.html was 500+ lines long. Adding a project meant copy-pasting 30 lines of HTML code manually.
  • Global CSS Chaos: Styles were global, leading to naming conflicts where changing a .card class would break layouts in unrelated sections.
  • Imperative DOM Manipulation: JavaScript had to manually query selectors (document.querySelector) to handle basic interactions like mobile menus.

The "After" State (React Architecture)

I re-engineered the site as a data-driven React application. This shift solved the maintenance nightmare and improved User Experience (UX) significantly.

🆚 Architecture Comparison

Feature Old Version (HTML/CSS) New Version (React Architecture) Engineering Value
Data Management Hardcoded HTML blocks. Copy-paste to add projects. Data-Driven (projects.js). Single source of truth. Scalability: Add a new project by adding one JSON object. The UI renders automatically.
State Manual DOM manipulation. Declarative State (useState). Reliability: React guarantees UI sync with state. No "desynchronized" interface bugs.
Routing Multiple .html files with repeated navbars. Client-Side Routing (react-router-dom). Performance: True SPA. No full page reloads. Instant transitions.
UX & Motion Basic CSS :hover. Jarring page jumps. Lifecycle Animations. Polish: Components animate out (slide down) before unmounting, impossible with static CSS.
Contact mailto: link (relied on user's email client). Integrated Form (Formspree). Lead Gen: Serverless backend handles emails directly in-app.

🛠️ Technical Implementation Details

1. The "Overlay" Strategy (3D vs. UI Separation)

To ensure 60fps performance, I separated the 3D physics engine from the DOM interface.

  • Background Layer (z-index: 0): Runs the heavy react-three-fiber physics simulation (Lanyard).
  • Foreground Layer (z-index: 10): A lightweight Overlay.jsx component that handles all user interactions (scrolling, clicking, forms).

Benefit: Complex UI interactions never block the WebGL render loop.

2. The Animation Engine (Exit Transitions)

React Router unmounts components instantly, making "exit" animations difficult. I engineered a delay system to solve this.

The Logic:

  1. User clicks "Back".
  2. State changes: setIsExiting(true).
  3. CSS Animation slideDownFade plays (0.5s).
  4. setTimeout waits 500ms, then triggers Maps('/').
/* The Exit Animation */
@keyframes slideDownFade {
  from { transform: translateY(0); opacity: 1; }
  to { transform: translateY(100vh); opacity: 0; }[Portfolio Development Journey - Complete README.pdf](https://github.com/user-attachments/files/24270382/Portfolio.Development.Journey.-.Complete.README.pdf)

}

3. Serverless Contact Form

I replaced the unreliable mailto: link with a fully styled form connected to the Formspree API.

Async/Await: Uses fetch() to post data without reloading the page.

Validation: Prevents submission of empty fields.

Feedback Loop: The UI updates through three distinct states: Idle -> Submitting -> Success.

4. The "KK Edition" Interactive Button

The submit button uses SVG geometry morphing to provide visual feedback, implemented purely in CSS/React (no heavy GSAP libraries).

Morphing: Transitions from a width: 190px rectangle to a width: 60px circle.

Spinner: Uses stroke-dasharray offset animation to create a spinning loader.

Stability: Utilizes transform-box: fill-box to ensure the spinner rotates around its own center, eliminating SVG wobble.

📂 Project Structure A clean, modular file structure separating logic, data, and presentation.

src/
├── assets/             # Static images (optimized WebP)
├── components/
│   ├── Lanyard.jsx     # 3D Physics Simulation (R3F)
│   ├── Overlay.jsx     # Main UI (Nav, Hero, Contact Form)
│   ├── ProjectCard.jsx # Reusable Card Component
│   └── Loader.jsx      # Suspense Fallback
├── data/
│   └── projects.js     # Single Source of Truth for Project Data
├── pages/
│   └── ProjectPage.jsx # Dynamic Detail Page (Routing target)
├── App.jsx             # Routes & Layout Logic
├── App.css             # Scoped Keyframe Animations
└── main.jsx            # Entry Point

💬 The Technical Interview Story

"I originally built this portfolio with static HTML and CSS, but I hit a wall with scalability—adding a new project meant manually updating code in five different files.

I re-architected it as a React Single Page Application. I moved all data into a JSON structure so the UI renders dynamically. The biggest engineering challenge was the page transitions. Since React unmounts components instantly, I had to implement a custom lifecycle hook using setTimeout to allow the 'Slide Down' animation to finish before the route changed.

I also optimized the performance by separating the 3D WebGL layer from the UI layer, ensuring that the physics simulation doesn't cause input lag on the contact form."

  • Setup & Installation
  1. Clone the repository Terminal: git clone [https://github.com/yourusername/portfolio.git](https://github.com/yourusername/portfolio.git)

  2. Install Dependencies Terminal: npm install

  3. Run Development Server Terminal: npm run dev

  4. Build for Production Terminal: npm run build

About

My Personal Portfolio

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published