- Add marketing copy and project description for AlpenQueue - Extract CSS to separate styles.css file - Add live job counter updating every 10 seconds - Include screenshot placeholder section - Add GitHub link for code access - Remove old service status indicators
65 lines
2.3 KiB
HTML
65 lines
2.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Portfolio</title>
|
|
<link rel="stylesheet" href="styles.css">
|
|
</head>
|
|
<body>
|
|
<h1>Mountain-Built Tools for Real Problems</h1>
|
|
|
|
<div class="intro">
|
|
Linux Developer crafting resilient, self-hosted solutions from the Austrian Alps.
|
|
</div>
|
|
|
|
<div class="project">
|
|
<div class="project-name">AlpenQueue</div>
|
|
<p>A lightweight task queue-scrapes, processes, calls back-runs on a five-euro Hetzner box. Used it this morning to pull competitor prices.</p>
|
|
<p>The CLI? One command, drops jobs in. Built with Go, Docker-ready, open-source.</p>
|
|
<p>Want it? Just ask.</p>
|
|
</div>
|
|
|
|
<div class="demo">
|
|
<!-- Add your screenshot here: <img src="screenshot.png" alt="Live scraper demo"> -->
|
|
<div class="demo-placeholder">
|
|
Screenshot placeholder - add screenshot.png to project
|
|
</div>
|
|
<div class="demo-caption">Live demo: monitoring 42 jobs a minute</div>
|
|
</div>
|
|
|
|
<div class="jobs">
|
|
Processing <span class="jobs-count" id="job-count">42</span> jobs/minute
|
|
</div>
|
|
|
|
<div class="stack">
|
|
Go for the backend, net/http for the API, SQLite for data, goquery for scraping, Docker to package it, self-hosted on Hetzner.
|
|
</div>
|
|
|
|
<div class="link">
|
|
<a href="https://github.com/yourusername/alpenqueue">Get the code</a>
|
|
</div>
|
|
|
|
<script>
|
|
async function updateJobCount() {
|
|
try {
|
|
// Replace with your actual endpoint
|
|
// const response = await fetch('/api/jobs/rate');
|
|
// const data = await response.json();
|
|
// document.getElementById('job-count').innerHTML = data.jobsPerMinute;
|
|
|
|
// Simulated job count - random between 38-46
|
|
const count = Math.floor(Math.random() * 9) + 38;
|
|
document.getElementById('job-count').innerHTML = count;
|
|
} catch (error) {
|
|
console.error('Failed to fetch job count:', error);
|
|
}
|
|
}
|
|
|
|
// Update on load and every 10 seconds
|
|
updateJobCount();
|
|
setInterval(updateJobCount, 10000);
|
|
</script>
|
|
</body>
|
|
</html>
|