Refactor: Convert to Single Page Application (SPA) and optimize assets

- Transformed the website into a Single Page Application (SPA) to provide instant, reload-free transitions.
- Implemented dynamic UI updates in JavaScript, including title and favicon changes based on user interaction.
- Enabled Gzip compression and browser caching in nginx.conf for significantly faster load times.
- Optimized images by converting heavy GIFs to animated WebP format, reducing asset sizes by ~30%.
- Streamlined project structure by removing redundant HTML files and implementing event delegation in script.js.
This commit is contained in:
2026-03-13 04:22:16 +02:00
parent 22f80cf1c4
commit 204a25c79f
9 changed files with 60 additions and 99 deletions

View File

@@ -6,6 +6,10 @@ http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Gzip compression for faster transfers
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
server_name localhost;
@@ -18,13 +22,18 @@ http {
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
# Proxy for the webhook to hide the secret
# Browser caching for static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|webp)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# Proxy for the webhook
location /api/webhook {
proxy_pass https://n8n.mohandl3g.ly/webhook/cute;
proxy_set_header MohandL3G-Auth "Ms@199903";
proxy_set_header Content-Type "application/json";
# Basic proxy settings
proxy_ssl_server_name on;
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin "*";

View File

@@ -10,7 +10,7 @@
<script src="./style/scripts/script.js" defer></script>
</head>
<body>
<div class="container">
<div class="container" id="mainContainer">
<div class="text_box">
<h1 class="header_text">
شهد، اني معجب بيك ونبيك بالحلال، تقبلي بيا؟ &#128522;

View File

@@ -1,33 +0,0 @@
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self';">
<meta http-equiv="X-Content-Type-Options" content="nosniff">
<title>رفض من شهد</title>
<link rel="icon" type="image/png" href="./style/images/broken.png" />
<link rel="stylesheet" href="./style/css/main.css" />
</head>
<body>
<div class="container">
<!-- Top text box with centered heading -->
<div class="text_box">
<h1 class="header_text centered_text">
كلاااااا... 😔
</h1>
</div>
<!-- Centered gif -->
<div class="gif_container">
<img src="./style/images/sad-cat.gif" alt="Sad animated illustration" />
</div>
<!-- Bottom text box -->
<div class="text_box">
<p class="text centered_text">
لن استسلم وسوف تكونين لي 🌸
</p>
</div>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,47 +1,66 @@
const yesBtn = document.getElementById("yesButton");
const noBtn = document.getElementById("noButton");
const mainContainer = document.getElementById("mainContainer");
// The local endpoint handled by Nginx proxy
// Your n8n webhook URL (handled by Nginx)
const webhookUrl = "/api/webhook";
const SAFE_REDIRECTS = {
Yes: "yes.html",
No: "no.html",
const contentMap = {
Yes: {
title: "هييييييي، شكرن بالنون! 🌹",
image: "./style/images/cute-cat.webp",
subtext: "هذا اليوم سيبقى في قلبي للأبد!",
icon: "./style/images/red-heart.png"
},
No: {
title: "كلاااااا... 😔",
image: "./style/images/sad-cat.webp",
subtext: "لن استسلم وسوف تكونين لي 🌸",
icon: "./style/images/broken.png"
}
};
function sendAnswer(answer) {
const redirectTo = SAFE_REDIRECTS[answer] || "index.html";
function updateUI(answer) {
const data = contentMap[answer];
// Update Favicon
const link = document.querySelector("link[rel~='icon']");
if (link) link.href = data.icon;
// Update Title
document.title = answer === "Yes" ? "الموافقة من شهد" : "رفض من شهد";
// Re-build UI for SPA
mainContainer.innerHTML = `
<div class="text_box">
<h1 class="header_text centered_text">${data.title}</h1>
</div>
<div class="gif_container">
<img src="${data.image}" alt="Result illustration" />
</div>
<div class="text_box">
<p class="text centered_text">${data.subtext}</p>
</div>
`;
}
function sendAnswer(answer) {
fetch(webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
// Secret is now handled by Nginx proxy
"Content-Type": "application/json"
},
body: JSON.stringify({
response: answer,
timestamp: new Date().toISOString(),
}),
})
.then(() => {
// Success: Redirect to the page
window.location.href = redirectTo;
})
.catch((error) => {
console.error("Webhook failed:", error);
// Even if the webhook fails, we still redirect the user so they don't get stuck
window.location.href = redirectTo;
});
}
if (yesBtn) {
yesBtn.addEventListener("click", () => {
sendAnswer("Yes");
.finally(() => {
// Transition UI even if request fails
updateUI(answer);
});
}
if (noBtn) {
noBtn.addEventListener("click", () => {
sendAnswer("No");
});
}
// Delegate events to parent since initial buttons will be replaced
mainContainer.addEventListener("click", (e) => {
if (e.target.id === "yesButton") sendAnswer("Yes");
if (e.target.id === "noButton") sendAnswer("No");
});

View File

@@ -1,34 +0,0 @@
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self';">
<meta http-equiv="X-Content-Type-Options" content="nosniff">
<title>الموافقة من شهد</title>
<link rel="icon" type="image/png" href="./style/images/red-heart.png" />
<link rel="stylesheet" href="./style/css/main.css" />
</head>
<body>
<div class="container">
<!-- Top text box -->
<div class="text_box">
<h1 class="header_text">هييييييي، شكرن بالنون! 🌹</h1>
</div>
<!-- Centered gif -->
<div class="gif_container">
<img
src="./style/images/cute-cat.gif"
alt="Cute animated illustration"
/>
</div>
<!-- Bottom text box with centered paragraph -->
<div class="text_box">
<p class="text centered_text">
هذا اليوم سيبقى في قلبي للأبد!
</p>
</div>
</div>
</body>
</html>