Skip to content

Commit e526407

Browse files
committed
Perf/a11y/SEO: defer MailerLite & SupportFast, YouTube thumbnail, CSP, fix srcset, remove banner
1 parent dd34b6f commit e526407

6 files changed

Lines changed: 195 additions & 117 deletions

File tree

index.html

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<link rel="apple-touch-icon" href="/logo.webp">
3131
<link rel="manifest" href="/manifest.json">
3232
<link rel="canonical" href="https://hellenicdev.github.io">
33+
<link rel="preload" as="image" href="/logo.webp" fetchpriority="high">
3334
<link rel="preconnect" href="https://www.googletagmanager.com">
3435
<link rel="preconnect" href="https://cdn.supportfast.ai">
3536
<link rel="preconnect" href="https://www.youtube.com">
@@ -166,7 +167,6 @@
166167
}]
167168
</script>
168169

169-
<script defer id="supportfast-script" src="https://cdn.supportfast.ai/chatbot.js" data-chatbot-id="bot-09dcew6lcq"></script>
170170
<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" data-cbid="06e4a97f-2c34-41ed-8ab6-d53b581ff080" type="text/javascript" async></script>
171171

172172
<title>HellenicDev – Programming Projects, Tools & Experiments</title>
@@ -185,9 +185,6 @@
185185
h4,.subtitle{text-align:center;max-width:800px;font-weight:400;color:#ccc;margin:10px auto}
186186
h2{text-align:center;display:inline-block;margin:40px auto 20px;border-bottom:3px solid #19336e;padding-bottom:5px}
187187
h2.left-align{display:block;margin-left:0;border-bottom:3px solid #19336e;padding-bottom:5px}
188-
.sticky-banner{position:sticky;top:0;z-index:500;background:#19336e;color:#dbe4ff;text-align:center;padding:10px 40px 10px 16px;font-size:.82rem;line-height:1.5;margin-bottom:1.5rem;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.3)}
189-
.banner-link{color:#38bdf8;text-decoration:none;font-weight:600;white-space:nowrap}
190-
.close-banner{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:0;border:0;color:#dbe4ff;font-size:1.1rem;cursor:pointer;padding:10px 12px;opacity:.7;line-height:1;min-width:44px;min-height:44px;display:flex;align-items:center;justify-content:center}
191188
.footer{text-align:center;padding:20px;font-size:14px;color:#999}
192189
iframe{display:block;width:100%;max-width:100%}
193190
:focus-visible{outline:2px solid #38bdf8;outline-offset:2px}
@@ -204,7 +201,7 @@
204201
.project-extra-wrapper{grid-column:1/-1;overflow:hidden;max-height:0}
205202
.project-extra-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:1.5rem}
206203
.project-extra{opacity:0;transform:translateY(36px)}
207-
@media(max-width:768px){body{padding:1rem}h1{font-size:2rem}h2{font-size:1.5rem}#menuButton{font-size:18px;padding:3px 6px}#sideMenu{width:200px;padding-top:50px}.sticky-banner{font-size:.75rem;padding:8px 36px 8px 12px}.game-list{grid-template-columns:1fr;gap:1rem}}
204+
@media(max-width:768px){body{padding:1rem}h1{font-size:2rem}h2{font-size:1.5rem}#menuButton{font-size:18px;padding:3px 6px}#sideMenu{width:200px;padding-top:50px}.game-list{grid-template-columns:1fr;gap:1rem}}
208205
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
209206
</style>
210207
<link rel="stylesheet" href="/style.min.css" media="print" onload="this.media='all';this.onload=null">
@@ -242,8 +239,6 @@
242239
alt="HellenicDev logo"
243240
fetchpriority="high"
244241
decoding="async"
245-
srcset="logo.webp 150w, logo.webp 300w"
246-
sizes="(max-width: 768px) 150px, 150px"
247242
>
248243

249244
<!-- ANNIVERSARY -->
@@ -252,11 +247,6 @@
252247
</p>
253248
</header>
254249
<main id="main-content">
255-
<div class="sticky-banner" id="stickyBanner" role="alert">
256-
<strong>⏸️ Service Update:</strong> Uptime monitoring paused to manage free-tier usage.
257-
<a href="#updates" class="banner-link">Details</a>
258-
<button class="close-banner" onclick="this.parentElement.remove()" aria-label="Dismiss banner"></button>
259-
</div>
260250
<section id="about">
261251
<h1 class="left-align">HellenicDev</h1>
262252
<p class="left-align subtitle">Hello! My name is Panos, AKA HellenicDev. I'm passionate about programming and love exploring different languages and technologies. I've created several projects so far—and many more are on the way! You can find a few of them listed below. Enjoy!</p>
@@ -520,10 +510,16 @@ <h2 class="left-align">What’s Coming Next</h2>
520510
</section>
521511
<br>
522512
<!-- reCAPTCHA-Protected Google Form -->
523-
<div id="latest-upload" class="responsive-iframe">
513+
<div id="latest-upload">
524514
<h2 class="left-align"> My Latest Upload:</h2>
525-
526-
<iframe width="560" height="315" src="https://www.youtube.com/embed/99FexhxsXx8?si=EECWLqH3sD-nJGhr" title="YouTube video player" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen class="yt-iframe"></iframe>
515+
<div class="responsive-iframe">
516+
<div id="ytPlayer" class="yt-placeholder" role="button" tabindex="0" aria-label="Play latest YouTube video">
517+
<img src="https://img.youtube.com/vi/99FexhxsXx8/hqdefault.jpg" alt="YouTube video thumbnail" width="560" height="315" loading="lazy" class="yt-thumb">
518+
<div class="yt-play-btn" aria-hidden="true">
519+
<svg viewBox="0 0 68 48" width="68" height="48"><path d="M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55c-2.93.78-4.63 3.26-5.42 6.19C.13 12.21 0 24 0 24s.13 11.79 1.55 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.87 35.79 68 24 68 24s-.13-11.79-1.55-16.26z" fill="red"/><path d="M45 24L27 14v20" fill="white"/></svg>
520+
</div>
521+
</div>
522+
</div>
527523
</div>
528524
<br><br><br><br>
529525
<div id="help-form" class="content-visibility-auto">
@@ -579,12 +575,7 @@ <h2 class="left-align">Contact Me</h2>
579575
<div id="newsletter" class="content-visibility-auto">
580576
<h2 class="left-align"> Newsletter </h2>
581577
<!-- START OF NEWSLETTER -->
582-
<style media="print" onload="this.media='all'">
583-
@import url("https://assets.mlcdn.com/fonts.css?version=1762785");
584-
</style>
585-
<link rel="stylesheet" href="/mailerlite.css" media="print" onload="this.media='all'">
586-
587-
<noscript><link rel="stylesheet" href="/mailerlite.css"></noscript>
578+
<noscript><link rel="stylesheet" href="/mailerlite.css"></noscript>
588579

589580
<div id="mlb2-33394663" class="ml-form-embedContainer ml-subscribe-form ml-subscribe-form-33394663">
590581
<div class="ml-form-align-center ">
@@ -716,7 +707,6 @@ <h4>Thank you!</h4>
716707
</div>
717708
</div>
718709

719-
<script defer src="https://groot.mailerlite.com/js/w/webforms.min.js?v176e10baa5e7ed80d35ae235be3d5024" type="text/javascript"></script>
720710
<!-- END OF NEWSLETTER -->
721711
</div>
722712
<div id="updates" class="left-align content-visibility-auto">
@@ -730,15 +720,11 @@ <h2 class="left-align"> HellenicDev Updates: </h2>
730720
🎧 A fresh UI experience has been developed.
731721
</p>
732722

733-
<p class="announcement">
734-
🚀 <strong>HellenicDev</strong> now has <a href="https://stats.uptimerobot.com/RrsSLtEzbk" target="_blank" class="link" > Uptime tracking</a>
723+
<p class="announcement">
724+
🚀 <strong>HellenicDev</strong> now has <a href="https://stats.uptimerobot.com/RrsSLtEzbk" target="_blank" class="link" > Uptime tracking</a>
735725
</p>
736726

737-
<p class="announcement">
738-
📡 <strong>Uptime monitoring paused</strong> to conserve Render free-tier instance hours (750 hrs/month limit). The system was checking services every 120–240s, accelerating quota usage. Status updates remain available in <strong>#uptime</strong>. Evaluating solutions for better reliability.
739-
</p>
740-
741-
<p class="announcement">
727+
<p class="announcement">
742728
🚀 <strong>HellenicDev</strong> now has <a href="https://hellenicdev.printify.me" target="_blank" class="link" > Merch!</a>
743729
</p>
744730

netlify.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
X-Frame-Options = "DENY"
1212
Referrer-Policy = "strict-origin-when-cross-origin"
1313
Permissions-Policy = "camera=(), microphone=(), geolocation=()"
14+
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; frame-src 'self' https:; connect-src 'self' https:"
1415

1516
[[headers]]
1617
for = "/assets/*"

script.js

Lines changed: 114 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,83 @@ if (utmSource) {
4949

5050

5151
// =====================
52-
// MailerLite (safe load)
53-
// =====================
54-
(function(w,d,e,u,f,l,n){
55-
w[f] = w[f] || function(){ (w[f].q = w[f].q || []).push(arguments); };
56-
l = d.createElement(e);
57-
l.async = 1;
58-
l.src = u;
59-
n = d.getElementsByTagName(e)[0];
60-
n.parentNode.insertBefore(l,n);
61-
})(window,document,'script','https://assets.mailerlite.com/js/universal.js','ml');
62-
63-
// Call only if available
64-
setTimeout(() => {
65-
if (typeof ml === "function") {
66-
ml('account', '1922622');
52+
// MailerLite (deferred loading via IntersectionObserver)
53+
// =====================
54+
(function() {
55+
function loadMailerLite() {
56+
// Load MailerLite fonts CSS
57+
var fontsLink = document.createElement('link');
58+
fontsLink.rel = 'stylesheet';
59+
fontsLink.href = 'https://assets.mlcdn.com/fonts.css?version=1762785';
60+
fontsLink.media = 'print';
61+
fontsLink.onload = function() { this.media = 'all'; };
62+
document.head.appendChild(fontsLink);
63+
64+
// Load mailerlite.css
65+
var mlCSS = document.createElement('link');
66+
mlCSS.rel = 'stylesheet';
67+
mlCSS.href = '/mailerlite.css';
68+
document.head.appendChild(mlCSS);
69+
70+
// Load MailerLite universal.js
71+
(function(w,d,e,u,f,l,n){
72+
w[f] = w[f] || function(){ (w[f].q = w[f].q || []).push(arguments); };
73+
l = d.createElement(e);
74+
l.async = 1;
75+
l.src = u;
76+
n = d.getElementsByTagName(e)[0];
77+
n.parentNode.insertBefore(l,n);
78+
})(window,document,'script','https://assets.mailerlite.com/js/universal.js','ml');
79+
80+
setTimeout(() => {
81+
if (typeof ml === "function") {
82+
ml('account', '1922622');
83+
}
84+
}, 1000);
85+
86+
// Load webforms.min.js
87+
var mlWebforms = document.createElement('script');
88+
mlWebforms.src = 'https://groot.mailerlite.com/js/w/webforms.min.js?v176e10baa5e7ed80d35ae235be3d5024';
89+
mlWebforms.defer = true;
90+
document.body.appendChild(mlWebforms);
6791
}
68-
}, 1000);
92+
93+
var newsletterSection = document.getElementById('newsletter');
94+
if (newsletterSection && 'IntersectionObserver' in window) {
95+
var observer = new IntersectionObserver(function(entries) {
96+
entries.forEach(function(entry) {
97+
if (entry.isIntersecting) {
98+
loadMailerLite();
99+
observer.disconnect();
100+
}
101+
});
102+
}, { rootMargin: '200px' });
103+
observer.observe(newsletterSection);
104+
} else {
105+
loadMailerLite();
106+
}
107+
})();
108+
109+
110+
// =====================
111+
// SupportFast chatbot (deferred to idle)
112+
// =====================
113+
(function() {
114+
function loadSupportFast() {
115+
var s = document.createElement('script');
116+
s.id = 'supportfast-script';
117+
s.src = 'https://cdn.supportfast.ai/chatbot.js';
118+
s.setAttribute('data-chatbot-id', 'bot-09dcew6lcq');
119+
s.defer = true;
120+
document.body.appendChild(s);
121+
}
122+
123+
if ('requestIdleCallback' in window) {
124+
requestIdleCallback(loadSupportFast, { timeout: 5000 });
125+
} else {
126+
setTimeout(loadSupportFast, 5000);
127+
}
128+
})();
69129

70130

71131
// =====================
@@ -100,7 +160,6 @@ window.addEventListener("load", () => {
100160
popup.style.display = 'block';
101161
popup.setAttribute('aria-hidden', 'false');
102162
closeBtn.focus();
103-
// trap focus inside popup
104163
popup.addEventListener('keydown', trapFocus);
105164
}
106165

@@ -211,6 +270,43 @@ function showThankYou() {
211270
}
212271

213272

273+
// =====================
274+
// Banner close button
275+
// =====================
276+
document.addEventListener('DOMContentLoaded', function() {
277+
var banner = document.getElementById('stickyBanner');
278+
if (banner) {
279+
var closeBtn = banner.querySelector('.close-banner');
280+
if (closeBtn) {
281+
closeBtn.addEventListener('click', function() {
282+
banner.remove();
283+
});
284+
}
285+
}
286+
});
287+
288+
289+
// =====================
290+
// YouTube click-to-load
291+
// =====================
292+
(function() {
293+
var ytPlayer = document.getElementById('ytPlayer');
294+
if (!ytPlayer) return;
295+
296+
function loadYouTube() {
297+
this.innerHTML = '<iframe width="560" height="315" src="https://www.youtube.com/embed/99FexhxsXx8?autoplay=1&si=EECWLqH3sD-nJGhr" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen class="yt-iframe"></iframe>';
298+
}
299+
300+
ytPlayer.addEventListener('click', loadYouTube);
301+
ytPlayer.addEventListener('keydown', function(e) {
302+
if (e.key === 'Enter' || e.key === ' ') {
303+
e.preventDefault();
304+
loadYouTube.call(this);
305+
}
306+
});
307+
})();
308+
309+
214310
// =====================
215311
// Navigation menu (safe)
216312
// =====================
@@ -246,4 +342,4 @@ if (menuButton && sideMenu) {
246342
toggleMenu();
247343
}
248344
});
249-
}
345+
}

0 commit comments

Comments
 (0)