154 lines
6.4 KiB
HTML
154 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>🌐 My Services Hub</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://cdn.jsdelivr.net/npm/tailwindcss@4.1.4/index.min.css"
|
|
/>
|
|
<style>
|
|
body {
|
|
background: linear-gradient(135deg, #0f2027, #203a43, #2c5364);
|
|
background-size: 400% 400%;
|
|
animation: gradientShift 15s ease infinite;
|
|
}
|
|
|
|
@keyframes gradientShift {
|
|
0% {
|
|
background-position: 0% 50%;
|
|
}
|
|
50% {
|
|
background-position: 100% 50%;
|
|
}
|
|
100% {
|
|
background-position: 0% 50%;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="min-h-screen text-white font-sans tracking-wide">
|
|
<main class="flex flex-col items-center px-6 py-10 space-y-24">
|
|
<!-- Header -->
|
|
<header class="text-center space-y-4">
|
|
<h1 class="text-5xl font-bold">🌐 My Network Services</h1>
|
|
<p class="text-gray-300 text-lg">
|
|
All services hosted under the same IP, organized for your convenience 💡
|
|
</p>
|
|
</header>
|
|
|
|
<!-- Services Section -->
|
|
<section class="w-full max-w-7xl">
|
|
<h2 class="text-3xl font-semibold mb-6">🛎️ Hosted Services</h2>
|
|
<div
|
|
id="service-grid"
|
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8"
|
|
></div>
|
|
</section>
|
|
|
|
<!-- External Links Section -->
|
|
<section class="w-full max-w-4xl border-t border-white/20 pt-12">
|
|
<h2 class="text-3xl font-semibold mb-6">📎 External Resources</h2>
|
|
<div id="external-links" class="grid grid-cols-1 sm:grid-cols-2 gap-6"></div>
|
|
</section>
|
|
|
|
<!-- Footer -->
|
|
<footer class="text-gray-400 text-sm text-center pt-8 border-t border-white/10 w-full">
|
|
© 2024-2025 Xiaomai. All services self-hosted 🧠💻<br />
|
|
Powered by TailwindCSS · Script-enhanced · Inspired by Productivity ⚙️
|
|
</footer>
|
|
</main>
|
|
|
|
<script>
|
|
const hostIP = window.location.hostname;
|
|
|
|
const services = [
|
|
{ port: 81, name: "🏠 Personal Homepage", desc: "Work in progress. Stay tuned!", tags: ["Web"] },
|
|
{ port: 40069, name: "☁ Nextcloud", desc: "Self-hosted cloud storage", secured: true, tags: ["Cloud", "Storage"] },
|
|
{ port: 1957, name: "🌦️ Malaysia Weather Radar", desc: "Historical weather radar visualization", tags: ["Data", "Weather"] },
|
|
{ port: 1025, name: "🎮 Kenney's Assets", desc: "Open game art & asset collection", tags: ["Assets", "Games"] },
|
|
{ port: 1031, name: "🌐 Itch io PCK dl", desc: "Download Godot pck files from itch.io", tags: ["Games", "Tools"] },
|
|
{ port: 3000, name: "📁 Gitea", desc: "Self-hosted Git service", tags: ["Code", "Git"] },
|
|
{ port: 5230, name: "📝 Memos", desc: "Lightweight self-hosted note-taking", tags: ["Notes", "Productivity"] },
|
|
{ port: 10001, name: "📄 Stirling PDF", desc: "Powerful locally hosted web based PDF manipulation tool", tags: ["Tools", "PDF"] },
|
|
{ port: 40178, name: "📊 JSON Hero", desc: "Visual JSON explorer", tags: ["Tools", "JSON"] },
|
|
{ port: 24680, name: "🛠️ 1Panel Dashboard", desc: "Unified server management panel", tags: ["Admin", "Dashboard"] },
|
|
];
|
|
|
|
const externalLinks = [
|
|
{ name: "🔗 GitHub", desc: "Code repositories and projects", url: "https://github.com/kingsmai" },
|
|
{ name: "📘 Blog", desc: "Personal dev blog and updates", url: "https://kingsmai.github.io" },
|
|
{ name: "💬 Discord Server", desc: "Join the dev chat room", url: "https://discord.gg/sJcv7ZM" },
|
|
];
|
|
|
|
const container = document.getElementById("service-grid");
|
|
const extContainer = document.getElementById("external-links");
|
|
|
|
async function checkStatus(service) {
|
|
try {
|
|
await fetch(`${service.secured ? "https" : "http"}://${hostIP}:${service.port}`, {
|
|
method: "HEAD",
|
|
mode: "no-cors",
|
|
});
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
(async () => {
|
|
for (const service of services) {
|
|
const online = await checkStatus(service);
|
|
|
|
const card = document.createElement("a");
|
|
card.href = `${service.secured ? "https" : "http"}://${hostIP}:${service.port}`;
|
|
card.target = "_blank";
|
|
card.rel = "noopener noreferrer";
|
|
card.className =
|
|
"rounded-xl overflow-hidden p-6 backdrop-blur-md bg-white/10 hover:bg-white/20 transition duration-300 border border-white/20 shadow-xl transform hover:scale-[1.03]";
|
|
|
|
card.innerHTML = `
|
|
<div class="flex flex-col h-full">
|
|
<h2 class="text-2xl font-bold mb-2">${service.name}</h2>
|
|
<p class="text-gray-300 flex-grow">${service.desc}</p>
|
|
<div class="mt-4 flex justify-between items-center text-sm">
|
|
<div class="text-gray-400">Port: ${service.port}</div>
|
|
<div class="${online ? "bg-green-600" : "bg-red-600"} text-white px-2 py-1 rounded-full text-xs">
|
|
${online ? "🟢 Online" : "🔴 Offline"}
|
|
</div>
|
|
</div>
|
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
${service.tags
|
|
.map(
|
|
(tag) =>
|
|
`<span class="bg-blue-800 text-white text-xs px-2 py-1 rounded-full">${tag}</span>`
|
|
)
|
|
.join("")}
|
|
</div>
|
|
</div>
|
|
`;
|
|
container.appendChild(card);
|
|
}
|
|
})();
|
|
|
|
for (const link of externalLinks) {
|
|
const card = document.createElement("a");
|
|
card.href = link.url;
|
|
card.target = "_blank";
|
|
card.rel = "noopener noreferrer";
|
|
card.className =
|
|
"rounded-lg border border-white/20 backdrop-blur-md bg-white/10 hover:bg-white/20 transition p-5 shadow-lg flex flex-col";
|
|
|
|
card.innerHTML = `
|
|
<h3 class="text-xl font-semibold mb-1">${link.name}</h3>
|
|
<p class="text-gray-300 text-sm">${link.desc}</p>
|
|
`;
|
|
|
|
extContainer.appendChild(card);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|