class CustomProjects extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = `

Featured Projects

Some of my recent work

Mooshieblob.com Project
Featured

mooshieblob.com

My fun alias profile showcasing my AI projects and online persona, featuring interactive demos, creative experiments, and real-time AI integrations.

Nuxt.js Tailwind CSS Cloudflare AI Vercel
Cloud Dashboard Project
Enterprise

Cloud Dashboard

A comprehensive cloud infrastructure monitoring dashboard with real-time metrics, intelligent alerts, automated scaling controls, and predictive analytics.

React TypeScript AWS Terraform Grafana Prometheus
E-Commerce Platform Project
SaaS

E-Commerce Platform

A full-stack e-commerce solution with headless CMS, seamless payment integration, real-time inventory management, and global multi-region deployment.

Next.js Stripe PostgreSQL Redis Docker GraphQL
DevOps Pipeline Project
Infrastructure

DevOps Pipeline

Automated CI/CD pipeline solution with self-hosted runners, comprehensive security scanning, automated testing, and multi-environment deployments.

GitHub Actions Kubernetes Helm ArgoCD SonarQube
`; } initScrollNavigation() { const scrollContainer = this.shadowRoot.getElementById('projects-scroll'); const prevBtn = this.shadowRoot.getElementById('prev-btn'); const nextBtn = this.shadowRoot.getElementById('next-btn'); const dotsContainer = this.shadowRoot.getElementById('dots-container'); const projects = scrollContainer.querySelectorAll('.project-container'); // Create dots projects.forEach((_, index) => { const dot = document.createElement('div'); dot.classList.add('dot'); if (index === 0) dot.classList.add('active'); dot.addEventListener('click', () => { projects[index].scrollIntoView({ behavior: 'smooth', inline: 'center' }); }); dotsContainer.appendChild(dot); }); // Update active dot on scroll const updateDots = () => { const scrollLeft = scrollContainer.scrollLeft; const containerWidth = scrollContainer.offsetWidth; projects.forEach((project, index) => { const projectLeft = project.offsetLeft; const projectWidth = project.offsetWidth; if (scrollLeft >= projectLeft - containerWidth / 2 && scrollLeft < projectLeft + projectWidth - containerWidth / 2) { dotsContainer.querySelectorAll('.dot').forEach(dot => dot.classList.remove('active')); dotsContainer.querySelectorAll('.dot')[index]?.classList.add('active'); } }); }; scrollContainer.addEventListener('scroll', updateDots); // Navigation buttons prevBtn.addEventListener('click', () => { const scrollAmount = scrollContainer.offsetWidth * 0.9; scrollContainer.scrollBy({ left: -scrollAmount, behavior: 'smooth' }); }); nextBtn.addEventListener('click', () => { const scrollAmount = scrollContainer.offsetWidth * 0.9; scrollContainer.scrollBy({ left: scrollAmount, behavior: 'smooth' }); }); // Touch/drag support for mobile let isDown = false; let startX; let scrollLeft; scrollContainer.addEventListener('mousedown', (e) => { isDown = true; startX = e.pageX - scrollContainer.offsetLeft; scrollLeft = scrollContainer.scrollLeft; }); scrollContainer.addEventListener('mouseleave', () => isDown = false); scrollContainer.addEventListener('mouseup', () => isDown = false); scrollContainer.addEventListener('mousemove', (e) => { if (!isDown) return; e.preventDefault(); const x = e.pageX - scrollContainer.offsetLeft; const walk = (x - startX) * 2; scrollContainer.scrollLeft = scrollLeft - walk; }); } } customElements.define('custom-projects', CustomProjects);