Skip to content

Commit 93a7442

Browse files
committed
Changes made
1 parent 5a0e897 commit 93a7442

File tree

10 files changed

+184
-136
lines changed

10 files changed

+184
-136
lines changed

.github/workflows/deploy.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,47 @@ jobs:
2626
- name: Create .nojekyll file 📄
2727
run: touch dist/.nojekyll
2828

29+
- name: Create MIME types configuration 📄
30+
run: |
31+
echo '# MIME types configuration
32+
*.jsx application/javascript
33+
*.js application/javascript
34+
' > dist/.htaccess
35+
36+
- name: Prepare for deployment
37+
run: |
38+
# Create an empty public directory in case it doesn't exist
39+
mkdir -p public
40+
# Copy all images to dist to ensure they're available
41+
cp -r public/* dist/ || true
42+
43+
# Create 404.html for GitHub Pages SPA routing
44+
cat > dist/404.html << 'EOL'
45+
<!DOCTYPE html>
46+
<html>
47+
<head>
48+
<meta charset="utf-8">
49+
<title>Hassan Shahzad | Portfolio</title>
50+
<script type="text/javascript">
51+
// Single Page Apps for GitHub Pages
52+
// MIT License
53+
// https://github.com/rafgraph/spa-github-pages
54+
var pathSegmentsToKeep = 1;
55+
var l = window.location;
56+
l.replace(
57+
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
58+
l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') + '/?/' +
59+
l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
60+
(l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
61+
l.hash
62+
);
63+
</script>
64+
</head>
65+
<body>
66+
</body>
67+
</html>
68+
EOL
69+
2970
- name: Deploy 🚀
3071
uses: JamesIves/github-pages-deploy-action@v4
3172
with:

index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>Hassan Shahzad | Portfolio</title>
8+
<!-- Preload critical JavaScript -->
9+
<link rel="modulepreload" href="./src/main.jsx" />
810
<!-- Script for handling client-side routing on GitHub Pages -->
911
<script type="text/javascript">
1012
// Single Page Apps for GitHub Pages

src/App.jsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useState, Suspense, lazy } from 'react';
22
import { BrowserRouter, Routes, Route } from 'react-router-dom';
33
import { ThemeProvider } from './theme/ThemeProvider';
44
import { AnimationProvider } from './context/AnimationContext';
5-
import { Box, Container } from '@mantine/core';
5+
import { Box } from '@mantine/core';
66

77
// Utilities
88
import browserDetection from './components/utils/browserDetection';
@@ -90,11 +90,12 @@ function App() {
9090
setLoading(false);
9191
}, 500);
9292
})
93-
.catch(() => {
93+
.catch((error) => {
94+
console.warn("Error during initial loading, continuing anyway:", error);
9495
// Continue anyway after a timeout
9596
setTimeout(() => {
9697
setLoading(false);
97-
}, 2000);
98+
}, 1000);
9899
});
99100

100101
// Performance optimizations based on device capabilities
@@ -105,6 +106,9 @@ function App() {
105106
applyPerformanceOptimizations(performanceMetrics);
106107
}, []);
107108

109+
// Determine basename for router based on GitHub Pages deployment
110+
const basename = window.location.hostname.includes('github.io') ? '/hxndev.github.io' : '';
111+
108112
return (
109113
<ThemeProvider>
110114
<style dangerouslySetInnerHTML={{ __html: inlineStyles }} />
@@ -114,7 +118,7 @@ function App() {
114118
<LoadingScreen progress={loadingProgress} isComplete={loadingProgress >= 100} />
115119
)}
116120

117-
<BrowserRouter>
121+
<BrowserRouter basename={basename}>
118122
<ParticleBackground particleCount={50} />
119123
<div
120124
style={{
@@ -143,10 +147,9 @@ function App() {
143147
>
144148
<Routes>
145149
<Route path="/" element={<Home />} />
146-
<Route path="/hxndev.github.io/" element={<Home />} />
147-
<Route path="/hxndev.github.io/projects" element={<Projects />} />
148-
<Route path="/hxndev.github.io/about" element={<About />} />
149-
<Route path="/hxndev.github.io/contact" element={<Contact />} />
150+
<Route path="/projects" element={<Projects />} />
151+
<Route path="/about" element={<About />} />
152+
<Route path="/contact" element={<Contact />} />
150153
</Routes>
151154
</Suspense>
152155
</PageTransition>
@@ -162,4 +165,4 @@ function App() {
162165
);
163166
}
164167

165-
export default App;
168+
export default App;

src/components/Header.jsx

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const Header = () => {
5050
}}
5151
>
5252
<Group justify="space-between" align="center">
53-
<Link to="/hxndev.github.io/" style={{ textDecoration: 'none' }}>
53+
<Link to="/" style={{ textDecoration: 'none' }}>
5454
<Title
5555
ref={titleRef}
5656
order={2}
@@ -69,10 +69,10 @@ const Header = () => {
6969

7070
<Group>
7171
{[
72-
{ path: '/hxndev.github.io/', label: 'Home' },
73-
{ path: '/hxndev.github.io/projects', label: 'Projects' },
74-
{ path: '/hxndev.github.io/about', label: 'About' },
75-
{ path: '/hxndev.github.io/contact', label: 'Contact' },
72+
{ path: '/', label: 'Home' },
73+
{ path: '/projects', label: 'Projects' },
74+
{ path: '/about', label: 'About' },
75+
{ path: '/contact', label: 'Contact' },
7676
].map((item, index) => (
7777
<Link key={item.path} to={item.path} style={{ textDecoration: 'none' }}>
7878
<Button
@@ -128,14 +128,4 @@ const Header = () => {
128128
);
129129
};
130130

131-
// Add a keyframe animation for the staggered entrance
132-
const style = document.createElement('style');
133-
style.textContent = `
134-
@keyframes fadeIn {
135-
from { opacity: 0; transform: translateY(-10px); }
136-
to { opacity: 1; transform: translateY(0); }
137-
}
138-
`;
139-
document.head.appendChild(style);
140-
141-
export default Header;
131+
export default Header;

src/components/home/HeroSection.jsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Title, Text, Container, Button, Group, Grid, Box } from '@mantine/core'
33
import { IconDownload, IconBrandGithub, IconArrowRight } from '@tabler/icons-react';
44
import { gsap } from 'gsap';
55
import { useColorScheme } from '../../theme/ThemeProvider';
6+
import { getImagePath } from '../../components/utils/imageUtils';
67

78
const HeroSection = () => {
89
const containerRef = useRef(null);
@@ -78,6 +79,10 @@ const HeroSection = () => {
7879
};
7980
}, []);
8081

82+
// Correctly format the profile image path
83+
const profileImagePath = getImagePath('images/profile.jpg');
84+
const resumePath = getImagePath('assets/hassan_resume.pdf');
85+
8186
return (
8287
<Box
8388
ref={containerRef}
@@ -146,7 +151,7 @@ const HeroSection = () => {
146151
<Group position="left" spacing="md" className="animate-item" ref={ctaRef}>
147152
<Button
148153
component="a"
149-
href="/hxndev.github.io/assets/hassan_resume.pdf"
154+
href={resumePath}
150155
size="lg"
151156
leftSection={<IconDownload size={20} />}
152157
radius="xl"
@@ -198,9 +203,12 @@ const HeroSection = () => {
198203
<div className="profile-container" ref={imageRef}>
199204
<div className="profile-image-wrapper">
200205
<img
201-
src="/hxndev.github.io/images/profile.jpg"
206+
src={profileImagePath}
202207
alt="Hassan Shahzad"
203208
className="profile-image"
209+
onError={(e) => {
210+
e.target.src = 'https://placehold.co/400x400/9B00FF/FFFFFF?text=Profile+Image';
211+
}}
204212
/>
205213
</div>
206214

@@ -346,4 +354,4 @@ const HeroSection = () => {
346354
);
347355
};
348356

349-
export default HeroSection;
357+
export default HeroSection;

src/components/projects/EnhancedProjectCard.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,4 @@ const EnhancedProjectCard = ({
301301
);
302302
};
303303

304-
export default EnhancedProjectCard;
304+
export default EnhancedProjectCard;

src/components/utils/assetPreloader.jsx

Lines changed: 75 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77
* @param {string} src - Image source URL
88
* @returns {Promise} - Promise that resolves when image is loaded
99
*/
10-
export const preloadImage = src => {
10+
export const preloadImage = (src) => {
1111
return new Promise((resolve, reject) => {
1212
const img = new Image();
1313
img.onload = () => resolve(img);
1414
img.onerror = reject;
15-
img.src = src;
15+
// Remove leading /hxndev.github.io/ from paths as they're causing issues with GitHub Pages
16+
if (src.startsWith('/hxndev.github.io/')) {
17+
img.src = src.substring('/hxndev.github.io/'.length);
18+
} else {
19+
img.src = src;
20+
}
1621
});
1722
};
1823

@@ -25,25 +30,26 @@ export const preloadImage = src => {
2530
export const preloadImages = (images, progressCallback = null) => {
2631
let loaded = 0;
2732
const total = images.length;
28-
33+
2934
return Promise.all(
30-
images.map(src =>
31-
preloadImage(src)
32-
.then(img => {
33-
loaded++;
34-
if (progressCallback) {
35-
progressCallback((loaded / total) * 100);
36-
}
37-
return img;
38-
})
39-
.catch(err => {
40-
console.warn(`Failed to preload image: ${src}`, err);
41-
loaded++;
42-
if (progressCallback) {
43-
progressCallback((loaded / total) * 100);
44-
}
45-
return null;
46-
})
35+
images.map(
36+
src =>
37+
preloadImage(src)
38+
.then(img => {
39+
loaded++;
40+
if (progressCallback) {
41+
progressCallback(loaded / total * 100);
42+
}
43+
return img;
44+
})
45+
.catch(err => {
46+
console.warn(`Failed to preload image: ${src}`, err);
47+
loaded++;
48+
if (progressCallback) {
49+
progressCallback(loaded / total * 100);
50+
}
51+
return null;
52+
})
4753
)
4854
);
4955
};
@@ -58,13 +64,10 @@ export const preloadFont = (fontFamily, src) => {
5864
return new Promise((resolve, reject) => {
5965
try {
6066
const font = new FontFace(fontFamily, `url(${src})`);
61-
font
62-
.load()
63-
.then(loadedFont => {
64-
document.fonts.add(loadedFont);
65-
resolve(loadedFont);
66-
})
67-
.catch(reject);
67+
font.load().then(loadedFont => {
68+
document.fonts.add(loadedFont);
69+
resolve(loadedFont);
70+
}).catch(reject);
6871
} catch (error) {
6972
reject(error);
7073
}
@@ -76,37 +79,38 @@ export const preloadFont = (fontFamily, src) => {
7679
* @returns {Array} Array of critical image URLs
7780
*/
7881
export const getCriticalImages = () => {
82+
// Use relative paths without the /hxndev.github.io/ prefix
7983
return [
8084
// Profile image
81-
'/hxndev.github.io/images/profile.jpg',
82-
85+
'images/profile.jpg',
86+
8387
// Project images for featured projects
84-
'/hxndev.github.io/images/projects/3d-solar-system.jpg',
85-
'/hxndev.github.io/images/projects/ai-chess.jpg',
86-
'/hxndev.github.io/images/projects/brilliant-pro.jpg',
87-
'/hxndev.github.io/images/projects/event-management.jpg',
88-
'/hxndev.github.io/images/projects/exam-scheduler.jpg',
89-
'/hxndev.github.io/images/projects/face-mesh.jpg',
90-
'/hxndev.github.io/images/projects/graphical-password.jpg',
91-
'/hxndev.github.io/images/projects/hawkseye.jpg',
92-
'/hxndev.github.io/images/projects/image-to-sketch.jpg',
93-
'/hxndev.github.io/images/projects/insta-profile.jpg',
94-
'/hxndev.github.io/images/projects/job-fit.jpg',
95-
'/hxndev.github.io/images/projects/password-cracker.jpg',
96-
'/hxndev.github.io/images/projects/phy-app.jpg',
97-
'/hxndev.github.io/images/projects/portfolio.jpg',
98-
'/hxndev.github.io/images/projects/pose-detection.jpg',
99-
'/hxndev.github.io/images/projects/qr-code.jpg',
100-
'/hxndev.github.io/images/projects/ripple-effect.jpg',
101-
'/hxndev.github.io/images/projects/rock-paper-scissors.jpg',
102-
'/hxndev.github.io/images/projects/simple-translator.jpg',
103-
'/hxndev.github.io/images/projects/vehicle-buy-sell.jpg',
104-
'/hxndev.github.io/images/projects/video-to-gif.jpg',
105-
'/hxndev.github.io/images/projects/virtual-drag-and-drop.jpg',
106-
'/hxndev.github.io/images/projects/virtual-mouse.jpg',
107-
88+
'images/projects/3d-solar-system.jpg',
89+
'images/projects/ai-chess.jpg',
90+
'images/projects/brilliant-pro.jpg',
91+
'images/projects/event-management.jpg',
92+
'images/projects/exam-scheduler.jpg',
93+
'images/projects/face-mesh.jpg',
94+
'images/projects/graphical-password.jpg',
95+
'images/projects/hawkseye.jpg',
96+
'images/projects/image-to-sketch.jpg',
97+
'images/projects/insta-profile.jpg',
98+
'images/projects/job-fit.jpg',
99+
'images/projects/password-cracker.jpg',
100+
'images/projects/phy-app.jpg',
101+
'images/projects/portfolio.jpg',
102+
'images/projects/pose-detection.jpg',
103+
'images/projects/qr-code.jpg',
104+
'images/projects/ripple-effect.jpg',
105+
'images/projects/rock-paper-scissors.jpg',
106+
'images/projects/simple-translator.jpg',
107+
'images/projects/vehicle-buy-sell.jpg',
108+
'images/projects/video-to-gif.jpg',
109+
'images/projects/virtual-drag-and-drop.jpg',
110+
'images/projects/virtual-mouse.jpg',
111+
108112
// Fallback images
109-
'https://placehold.co/600x400/9B00FF/FFFFFF?text=Image+Not+Found',
113+
'https://placehold.co/600x400/9B00FF/FFFFFF?text=Image+Not+Found'
110114
];
111115
};
112116

@@ -117,14 +121,27 @@ export const getCriticalImages = () => {
117121
*/
118122
export const preloadCriticalAssets = (progressCallback = null) => {
119123
const criticalImages = getCriticalImages();
120-
121-
return preloadImages(criticalImages, progressCallback);
124+
125+
// Add a delay before resolving to ensure the loading screen displays
126+
return new Promise((resolve) => {
127+
// First try to preload images
128+
preloadImages(criticalImages, progressCallback)
129+
.then(result => {
130+
// Even if some images fail to load, we still want to proceed
131+
setTimeout(() => resolve(result), 500);
132+
})
133+
.catch(error => {
134+
console.warn("Error preloading assets, but continuing anyway:", error);
135+
// Still resolve after a delay to ensure the app proceeds
136+
setTimeout(() => resolve([]), 500);
137+
});
138+
});
122139
};
123140

124141
export default {
125142
preloadImage,
126143
preloadImages,
127144
preloadFont,
128145
getCriticalImages,
129-
preloadCriticalAssets,
130-
};
146+
preloadCriticalAssets
147+
};

0 commit comments

Comments
 (0)