486 lines
15 KiB
HTML
486 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>River Rooks | Command Center</title>
|
|
<style>
|
|
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=Inter:wght@400;500;700&family=JetBrains+Mono:wght@400;500;700&display=swap');
|
|
|
|
:root {
|
|
--bg-canvas: #0d0f12;
|
|
--bg-surface: #121417;
|
|
--bg-elevated: #1c1f26;
|
|
--border-color: #2b303b;
|
|
--text-primary: #e0e6f0;
|
|
--text-muted: #8a95a5;
|
|
--accent-cyan: #00f0ff;
|
|
--accent-green: #00e676;
|
|
--accent-amber: #ffb700;
|
|
}
|
|
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
body {
|
|
background-color: var(--bg-canvas);
|
|
color: var(--text-primary);
|
|
font-family: 'Inter', sans-serif;
|
|
line-height: 1.6;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* Command Center Top Navigation Header */
|
|
.app-header {
|
|
background-color: var(--bg-surface);
|
|
border-bottom: 1px solid var(--border-color);
|
|
padding: 0 16px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
height: 48px;
|
|
}
|
|
|
|
.brand-title {
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.95rem;
|
|
font-weight: 700;
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.status-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
background-color: var(--accent-cyan);
|
|
}
|
|
|
|
/* Zed-Style Editor Tabs */
|
|
.nav-tabs {
|
|
display: flex;
|
|
gap: 2px;
|
|
height: 100%;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.tab-btn {
|
|
background-color: var(--bg-canvas);
|
|
border: 1px solid var(--border-color);
|
|
border-bottom: none;
|
|
color: var(--text-muted);
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.82rem;
|
|
padding: 8px 16px;
|
|
cursor: pointer;
|
|
border-top-left-radius: 4px;
|
|
border-top-right-radius: 4px;
|
|
transition: none; /* Instant snap */
|
|
}
|
|
|
|
.tab-btn:hover {
|
|
color: var(--text-primary);
|
|
background-color: var(--bg-elevated);
|
|
}
|
|
|
|
.tab-btn.active {
|
|
background-color: var(--bg-surface);
|
|
color: var(--accent-cyan);
|
|
border-top: 2px solid var(--accent-cyan);
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Main Container */
|
|
.container {
|
|
max-width: 900px;
|
|
width: 100%;
|
|
margin: 32px auto;
|
|
padding: 0 20px;
|
|
flex: 1;
|
|
}
|
|
|
|
.tab-pane {
|
|
display: none;
|
|
}
|
|
|
|
.tab-pane.active {
|
|
display: block;
|
|
}
|
|
|
|
/* Panel Component */
|
|
.panel {
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
background-color: var(--bg-surface);
|
|
overflow: hidden;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.panel-header {
|
|
background-color: var(--bg-canvas);
|
|
border-bottom: 1px solid var(--border-color);
|
|
padding: 10px 16px;
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.85rem;
|
|
font-weight: 700;
|
|
color: var(--text-muted);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.panel-body {
|
|
padding: 20px;
|
|
}
|
|
|
|
/* Services Grid (Tab 1) */
|
|
.services-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
gap: 16px;
|
|
}
|
|
|
|
.service-box {
|
|
border: 1px solid var(--border-color);
|
|
background-color: var(--bg-canvas);
|
|
padding: 14px;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.service-box:hover {
|
|
border-color: var(--accent-cyan);
|
|
}
|
|
|
|
.service-title {
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-weight: 700;
|
|
font-size: 0.92rem;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.service-title a {
|
|
color: var(--text-primary);
|
|
text-decoration: none;
|
|
transition: none;
|
|
}
|
|
|
|
.service-title a:hover {
|
|
color: var(--accent-cyan);
|
|
}
|
|
|
|
.badge-status {
|
|
font-size: 0.75rem;
|
|
padding: 2px 6px;
|
|
border-radius: 2px;
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
}
|
|
|
|
.badge-online { background-color: rgba(0, 230, 118, 0.15); color: var(--accent-green); }
|
|
.badge-internal { background-color: rgba(255, 183, 0, 0.15); color: var(--accent-amber); }
|
|
|
|
.service-desc {
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.service-stats {
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.75rem;
|
|
color: var(--text-muted);
|
|
border-top: 1px solid var(--border-color);
|
|
padding-top: 8px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
/* Blog Archive Table (Tab 2) */
|
|
.blog-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.blog-table th {
|
|
text-align: left;
|
|
border-bottom: 1px solid var(--border-color);
|
|
padding: 10px;
|
|
color: var(--text-muted);
|
|
font-size: 0.78rem;
|
|
}
|
|
|
|
.blog-table td {
|
|
padding: 12px 10px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
.blog-table tr:hover td {
|
|
background-color: var(--bg-canvas);
|
|
}
|
|
|
|
.post-link {
|
|
color: var(--text-primary);
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
transition: none;
|
|
}
|
|
|
|
.post-link:hover {
|
|
color: var(--accent-cyan);
|
|
}
|
|
|
|
.tag-badge {
|
|
color: var(--text-muted);
|
|
font-size: 0.78rem;
|
|
}
|
|
|
|
/* Resume Config Document (Tab 3) */
|
|
.conf-block {
|
|
background-color: var(--bg-canvas);
|
|
border: 1px solid var(--border-color);
|
|
padding: 16px;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 0.85rem;
|
|
border-radius: 4px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.conf-key { color: var(--accent-cyan); }
|
|
.conf-val { color: var(--text-primary); }
|
|
.conf-comment { color: var(--text-muted); }
|
|
|
|
.btn-action {
|
|
background-color: var(--bg-elevated);
|
|
border: 1px solid var(--border-color);
|
|
color: var(--text-primary);
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.85rem;
|
|
padding: 8px 16px;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
transition: none;
|
|
}
|
|
|
|
.btn-action:hover {
|
|
background-color: var(--accent-cyan);
|
|
color: var(--bg-canvas);
|
|
}
|
|
|
|
/* Footer */
|
|
.cmd-footer {
|
|
border-top: 1px solid var(--border-color);
|
|
background-color: var(--bg-surface);
|
|
padding: 12px 20px;
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
font-size: 0.8rem;
|
|
color: var(--text-muted);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Top App Bar & Zed-style Tabs -->
|
|
<header class="app-header">
|
|
<div class="brand-title">
|
|
<span class="status-dot"></span>
|
|
RIVER ROOKS // COMMAND CENTER
|
|
</div>
|
|
|
|
<nav class="nav-tabs">
|
|
<button class="tab-btn active" onclick="switchTab('services')">[1] ~/services</button>
|
|
<button class="tab-btn" onclick="switchTab('blog')">[2] ~/blog</button>
|
|
<button class="tab-btn" onclick="switchTab('resume')">[3] ~/resume</button>
|
|
</nav>
|
|
</header>
|
|
|
|
<!-- Main Container -->
|
|
<main class="container">
|
|
|
|
<!-- Tab 1: Homelab & Public Services Directory -->
|
|
<div id="tab-services" class="tab-pane active">
|
|
<div class="panel">
|
|
<div class="panel-header">
|
|
<span>/etc/services.d/manifest.json</span>
|
|
<span>4 SERVICES OPERATIONAL</span>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="services-grid">
|
|
|
|
<div class="service-box">
|
|
<div class="service-title">
|
|
<a href="https://grafana.local" target="_blank">grafana.homelab</a>
|
|
<span class="badge-status badge-online">ONLINE</span>
|
|
</div>
|
|
<p class="service-desc">Real-time metrics, Prometheus scraping, & homelab telemetry dashboards.</p>
|
|
<div class="service-stats">
|
|
<span>PING: 4ms</span>
|
|
<span>TRAEFIK HTTPS</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-box">
|
|
<div class="service-title">
|
|
<a href="https://vault.local" target="_blank">vault.homelab</a>
|
|
<span class="badge-status badge-online">ONLINE</span>
|
|
</div>
|
|
<p class="service-desc">HashiCorp Vault secret storage, certificate authority, & mTLS renewal.</p>
|
|
<div class="service-stats">
|
|
<span>PING: 2ms</span>
|
|
<span>SEALED: FALSE</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-box">
|
|
<div class="service-title">
|
|
<a href="https://nextcloud.local" target="_blank">cloud.homelab</a>
|
|
<span class="badge-status badge-online">ONLINE</span>
|
|
</div>
|
|
<p class="service-desc">Encrypted private cloud file storage & automated system backup target.</p>
|
|
<div class="service-stats">
|
|
<span>PING: 6ms</span>
|
|
<span>STORAGE: 1.2TB</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-box">
|
|
<div class="service-title">
|
|
<a href="https://wireguard.local" target="_blank">wireguard.homelab</a>
|
|
<span class="badge-status badge-internal">INTERNAL</span>
|
|
</div>
|
|
<p class="service-desc">WireGuard mesh VPN gateway connecting cloud VPS instances to homelab node.</p>
|
|
<div class="service-stats">
|
|
<span>PING: 12ms</span>
|
|
<span>PEERS: 6 ACTIVE</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 2: Technical Notes & Blog Archive -->
|
|
<div id="tab-blog" class="tab-pane">
|
|
<div class="panel">
|
|
<div class="panel-header">
|
|
<span>/var/log/articles.index</span>
|
|
<span>POST COUNT: 4</span>
|
|
</div>
|
|
<div class="panel-body" style="padding: 0;">
|
|
<table class="blog-table">
|
|
<thead>
|
|
<tr>
|
|
<th>DATE</th>
|
|
<th>TITLE</th>
|
|
<th>TAGS</th>
|
|
<th>READ TIME</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>2026-08-02</td>
|
|
<td><a href="#" class="post-link">Hardening Traefik Ingress with HashiCorp Vault mTLS</a></td>
|
|
<td><span class="tag-badge">[#homelab] [#traefik]</span></td>
|
|
<td>8 min</td>
|
|
</tr>
|
|
<tr>
|
|
<td>2026-07-18</td>
|
|
<td><a href="#" class="post-link">DEFCON CTF Qualifier: Memory Corruption & Heap Exploitation</a></td>
|
|
<td><span class="tag-badge">[#ctf] [#binary]</span></td>
|
|
<td>14 min</td>
|
|
</tr>
|
|
<tr>
|
|
<td>2026-06-29</td>
|
|
<td><a href="#" class="post-link">Custom Linux Kernel Compilation for BPF Network Tracing</a></td>
|
|
<td><span class="tag-badge">[#linux] [#ebpf]</span></td>
|
|
<td>11 min</td>
|
|
</tr>
|
|
<tr>
|
|
<td>2026-05-14</td>
|
|
<td><a href="#" class="post-link">Minimalist Dotfiles & Hyprland Keybindings Optimization</a></td>
|
|
<td><span class="tag-badge">[#hyprland] [#dots]</span></td>
|
|
<td>5 min</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 3: Resume & Engineering Profile -->
|
|
<div id="tab-resume" class="tab-pane">
|
|
<div class="panel">
|
|
<div class="panel-header">
|
|
<span>/etc/river_rooks.conf</span>
|
|
<span>POSIX SPECIFICATION</span>
|
|
</div>
|
|
<div class="panel-body">
|
|
|
|
<div class="conf-block">
|
|
<span class="conf-comment"># Identity & System Purpose</span><br>
|
|
<span class="conf-key">AUTHOR</span> = <span class="conf-val">"River Rooks"</span><br>
|
|
<span class="conf-key">ROLE</span> = <span class="conf-val">"Systems Architect & Cybersecurity Researcher"</span><br>
|
|
<span class="conf-key">AFFILIATION</span> = <span class="conf-val">"University of Alabama College of Engineering"</span><br><br>
|
|
|
|
<span class="conf-comment"># Active Skillset Matrix</span><br>
|
|
<span class="conf-key">DOMAINS</span> = [<span class="conf-val">"Network Forensics"</span>, <span class="conf-val">"Self-Hosted Infrastructure"</span>, <span class="conf-val">"Linux Kernel Hardening"</span>]<br>
|
|
<span class="conf-key">LANGUAGES</span> = [<span class="conf-val">"POSIX sh"</span>, <span class="conf-val">"Python"</span>, <span class="conf-val">"C"</span>, <span class="conf-val">"Lua"</span>]<br>
|
|
<span class="conf-key">TOOLS</span> = [<span class="conf-val">"Docker"</span>, <span class="conf-val">"Traefik"</span>, <span class="conf-val">"WireGuard"</span>, <span class="conf-val">"Neovim"</span>, <span class="conf-val">"Arch Linux"</span>]
|
|
</div>
|
|
|
|
<p style="font-size: 0.92rem; margin-bottom: 16px;">
|
|
Focused on building resilient, zero-trust network architectures and low-noise self-hosted environments.
|
|
Proven CTF participant and open-source dotfiles maintainer.
|
|
</p>
|
|
|
|
<div style="display: flex; gap: 12px;">
|
|
<a href="#" class="btn-action">Download Resume (.PDF)</a>
|
|
<a href="#" class="btn-action">Fetch PGP Key</a>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</main>
|
|
|
|
<!-- Command Center Footer -->
|
|
<footer class="cmd-footer">
|
|
<div>Keyboard Navigation: Press <kbd>1</kbd>, <kbd>2</kbd>, or <kbd>3</kbd> to switch tabs</div>
|
|
<div>Ghostty / Zed Terminal Interface</div>
|
|
</footer>
|
|
|
|
<script>
|
|
function switchTab(tabId) {
|
|
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
|
|
document.querySelectorAll('.tab-pane').forEach(pane => pane.classList.remove('active'));
|
|
|
|
if (tabId === 'services') {
|
|
document.querySelectorAll('.tab-btn')[0].classList.add('active');
|
|
document.getElementById('tab-services').classList.add('active');
|
|
} else if (tabId === 'blog') {
|
|
document.querySelectorAll('.tab-btn')[1].classList.add('active');
|
|
document.getElementById('tab-blog').classList.add('active');
|
|
} else if (tabId === 'resume') {
|
|
document.querySelectorAll('.tab-btn')[2].classList.add('active');
|
|
document.getElementById('tab-resume').classList.add('active');
|
|
}
|
|
}
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.key === '1') switchTab('services');
|
|
if (e.key === '2') switchTab('blog');
|
|
if (e.key === '3') switchTab('resume');
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|