Skip to content

Commit 9583100

Browse files
committed
feat(v2-03): implement Infrastructure page, full sitemap, polished 404 (Phase A)
- Infrastructure page: Hero (banner), platform overview, cluster specs table, collapsible node inventory (7 nodes), collapsible VM inventory (9 VMs), architecture highlights grid, data pipeline, governance section, CTA - NodeInventoryTable and VMInventoryTable components - Full sitemap.xml with all 12 public routes - Polished 404 page with suggested links and legacy URL note - robots.txt excludes /styleguide Phase A complete. Phase B (cutover) requires explicit user approval.
1 parent 6b12d63 commit 9583100

File tree

5 files changed

+261
-10
lines changed

5 files changed

+261
-10
lines changed

site-v2/public/sitemap.xml

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,75 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3-
<url><loc>https://radioastronomy.io/</loc></url>
3+
<url>
4+
<loc>https://radioastronomy.io/</loc>
5+
<lastmod>2026-04-18</lastmod>
6+
<changefreq>weekly</changefreq>
7+
<priority>1.0</priority>
8+
</url>
9+
<url>
10+
<loc>https://radioastronomy.io/about</loc>
11+
<lastmod>2026-04-18</lastmod>
12+
<changefreq>monthly</changefreq>
13+
<priority>0.8</priority>
14+
</url>
15+
<url>
16+
<loc>https://radioastronomy.io/research</loc>
17+
<lastmod>2026-04-18</lastmod>
18+
<changefreq>weekly</changefreq>
19+
<priority>0.9</priority>
20+
</url>
21+
<url>
22+
<loc>https://radioastronomy.io/infrastructure</loc>
23+
<lastmod>2026-04-18</lastmod>
24+
<changefreq>monthly</changefreq>
25+
<priority>0.7</priority>
26+
</url>
27+
<url>
28+
<loc>https://radioastronomy.io/sponsors</loc>
29+
<lastmod>2026-04-18</lastmod>
30+
<changefreq>monthly</changefreq>
31+
<priority>0.7</priority>
32+
</url>
33+
<url>
34+
<loc>https://radioastronomy.io/projects/desi-cosmic-void-galaxies</loc>
35+
<lastmod>2026-04-18</lastmod>
36+
<changefreq>weekly</changefreq>
37+
<priority>0.8</priority>
38+
</url>
39+
<url>
40+
<loc>https://radioastronomy.io/projects/desi-quasar-outflows</loc>
41+
<lastmod>2026-04-18</lastmod>
42+
<changefreq>monthly</changefreq>
43+
<priority>0.7</priority>
44+
</url>
45+
<url>
46+
<loc>https://radioastronomy.io/projects/desi-qso-anomaly-detection</loc>
47+
<lastmod>2026-04-18</lastmod>
48+
<changefreq>monthly</changefreq>
49+
<priority>0.7</priority>
50+
</url>
51+
<url>
52+
<loc>https://radioastronomy.io/projects/rbh1-validation</loc>
53+
<lastmod>2026-04-18</lastmod>
54+
<changefreq>monthly</changefreq>
55+
<priority>0.7</priority>
56+
</url>
57+
<url>
58+
<loc>https://radioastronomy.io/projects/desi-lsst-transient-anomalies</loc>
59+
<lastmod>2026-04-18</lastmod>
60+
<changefreq>monthly</changefreq>
61+
<priority>0.6</priority>
62+
</url>
63+
<url>
64+
<loc>https://radioastronomy.io/projects/cosmos-web-anomalies</loc>
65+
<lastmod>2026-04-18</lastmod>
66+
<changefreq>monthly</changefreq>
67+
<priority>0.6</priority>
68+
</url>
69+
<url>
70+
<loc>https://radioastronomy.io/projects/proxmox-astronomy-lab</loc>
71+
<lastmod>2026-04-18</lastmod>
72+
<changefreq>monthly</changefreq>
73+
<priority>0.7</priority>
74+
</url>
475
</urlset>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
interface Props {
3+
rows: { node: string; cpu: string; cores: string; ram: string; role: string }[];
4+
}
5+
6+
const { rows } = Astro.props;
7+
---
8+
9+
<div class="overflow-x-auto">
10+
<table class="w-full text-left border-collapse">
11+
<thead>
12+
<tr class="border-b-2 border-brand-navy dark:border-dark-text">
13+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">Node</th>
14+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">CPU</th>
15+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">Cores</th>
16+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">RAM</th>
17+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">Role</th>
18+
</tr>
19+
</thead>
20+
<tbody>
21+
{rows.map((row) => (
22+
<tr class="border-b border-brand-grid dark:border-dark-surface hover:bg-brand-grid/20 dark:hover:bg-dark-surface/50 transition-colors">
23+
<td class="py-3 px-4 font-medium">{row.node}</td>
24+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.cpu}</td>
25+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.cores}</td>
26+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.ram}</td>
27+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.role}</td>
28+
</tr>
29+
))}
30+
</tbody>
31+
</table>
32+
</div>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
interface Props {
3+
rows: { vm: string; vcpu: string; ram: string; purpose: string }[];
4+
}
5+
6+
const { rows } = Astro.props;
7+
---
8+
9+
<div class="overflow-x-auto">
10+
<table class="w-full text-left border-collapse">
11+
<thead>
12+
<tr class="border-b-2 border-brand-navy dark:border-dark-text">
13+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">VM</th>
14+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">vCPU</th>
15+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">RAM</th>
16+
<th class="py-3 px-4 font-semibold text-sm uppercase tracking-wider text-brand-gray dark:text-gray-400">Purpose</th>
17+
</tr>
18+
</thead>
19+
<tbody>
20+
{rows.map((row) => (
21+
<tr class="border-b border-brand-grid dark:border-dark-surface hover:bg-brand-grid/20 dark:hover:bg-dark-surface/50 transition-colors">
22+
<td class="py-3 px-4 font-medium font-mono text-sm">{row.vm}</td>
23+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.vcpu}</td>
24+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.ram}</td>
25+
<td class="py-3 px-4 text-sm text-brand-gray dark:text-gray-400">{row.purpose}</td>
26+
</tr>
27+
))}
28+
</tbody>
29+
</table>
30+
</div>

site-v2/src/pages/404.astro

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@ import PageLayout from '../layouts/PageLayout.astro';
33
import Container from '../components/Container.astro';
44
---
55

6-
<PageLayout>
6+
<PageLayout title="Page Not Found | RadioAstronomy.io">
77
<Container>
8-
<div class="py-20 text-center">
9-
<h1 class="text-4xl font-bold mb-4">Page not found</h1>
10-
<p class="text-brand-gray dark:text-gray-400 mb-8">The page you're looking for doesn't exist.</p>
11-
<a href="/" class="inline-flex items-center px-6 py-3 bg-brand-steel text-white font-semibold rounded-lg hover:bg-brand-steel/90 transition-colors">
12-
Back to Home
13-
</a>
8+
<div class="py-24 text-center">
9+
<p class="text-6xl font-bold text-brand-steel mb-4">404</p>
10+
<h1 class="text-3xl font-bold mb-4">Page not found</h1>
11+
<p class="text-brand-gray dark:text-gray-400 mb-2 max-w-lg mx-auto">The page you're looking for doesn't exist or has been moved.</p>
12+
<p class="text-sm text-brand-gray dark:text-gray-400 mb-8 max-w-lg mx-auto">If you followed a link from the previous site layout, the content may have moved to a new URL.</p>
13+
<div class="flex flex-wrap justify-center gap-4">
14+
<a href="/" class="inline-flex items-center px-6 py-3 bg-brand-steel text-white font-semibold rounded-lg hover:bg-brand-steel/90 transition-colors">Home</a>
15+
<a href="/research" class="inline-flex items-center px-6 py-3 border-2 border-brand-navy dark:border-dark-text font-semibold rounded-lg hover:bg-brand-navy hover:text-white dark:hover:bg-dark-text dark:hover:text-dark-bg transition-colors">Research</a>
16+
<a href="/projects/desi-cosmic-void-galaxies" class="inline-flex items-center px-6 py-3 border-2 border-brand-navy dark:border-dark-text font-semibold rounded-lg hover:bg-brand-navy hover:text-white dark:hover:bg-dark-text dark:hover:text-dark-bg transition-colors">Projects</a>
17+
</div>
1418
</div>
1519
</Container>
1620
</PageLayout>
Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,124 @@
11
---
22
import PageLayout from '../layouts/PageLayout.astro';
33
import Container from '../components/Container.astro';
4+
import Hero from '../components/Hero.astro';
5+
import AccordionItem from '../components/AccordionItem.astro';
6+
import NodeInventoryTable from '../components/NodeInventoryTable.astro';
7+
import VMInventoryTable from '../components/VMInventoryTable.astro';
8+
import Button from '../components/Button.astro';
9+
10+
const nodeRows = [
11+
{ node: 'node01', cpu: 'i9-12900H', cores: '20', ram: '96 GB', role: 'Compute (K8s)' },
12+
{ node: 'node02', cpu: 'i5-12600H', cores: '16', ram: '96 GB', role: 'Light compute + storage' },
13+
{ node: 'node03', cpu: 'i9-12900H', cores: '20', ram: '96 GB', role: 'Compute (K8s)' },
14+
{ node: 'node04', cpu: 'i9-12900H', cores: '20', ram: '96 GB', role: 'Compute (K8s)' },
15+
{ node: 'node05', cpu: 'i5-12600H', cores: '16', ram: '96 GB', role: 'Light compute + storage' },
16+
{ node: 'node06', cpu: 'i9-13900H', cores: '20', ram: '96 GB', role: 'Heavy compute (databases)' },
17+
{ node: 'node07', cpu: 'AMD 5950X', cores: '32', ram: '128 GB', role: 'GPU compute' },
18+
];
19+
20+
const vmRows = [
21+
{ vm: 'radio-k8s01', vcpu: '12', ram: '48G', purpose: 'Kubernetes primary' },
22+
{ vm: 'radio-k8s02', vcpu: '12', ram: '48G', purpose: 'Kubernetes worker' },
23+
{ vm: 'radio-k8s03', vcpu: '12', ram: '48G', purpose: 'Kubernetes worker' },
24+
{ vm: 'radio-gpu01', vcpu: '12', ram: '48G', purpose: 'GPU worker (A4000)' },
25+
{ vm: 'radio-pgsql01', vcpu: '8', ram: '32G', purpose: 'Research PostgreSQL' },
26+
{ vm: 'radio-pgsql02', vcpu: '4', ram: '16G', purpose: 'Application PostgreSQL' },
27+
{ vm: 'radio-neo4j01', vcpu: '6', ram: '24G', purpose: 'Graph database' },
28+
{ vm: 'radio-fs02', vcpu: '4', ram: '6G', purpose: 'SMB file server' },
29+
{ vm: 'radio-agents01', vcpu: '8', ram: '32G', purpose: 'AI agents, monitoring' },
30+
];
431
---
532

6-
<PageLayout title="Infrastructure | RadioAstronomy.io">
33+
<PageLayout
34+
title="Infrastructure | RadioAstronomy.io"
35+
description="The Proxmox Astronomy Lab is a seven-node Proxmox cluster with 144 cores, 704 GB RAM, 26 TB NVMe, and RTX A4000 GPU compute. Enterprise-grade infrastructure for independent astronomical research."
36+
ogImage="/images/og/infrastructure.png"
37+
>
38+
<Hero
39+
variant="banner"
40+
title="Research Platform"
41+
subtitle="Enterprise-grade astronomical computing on a seven-node Proxmox cluster"
42+
backgroundImage="/images/heroes/infrastructure.png"
43+
/>
44+
745
<Container>
8-
<h1 class="text-4xl font-bold py-20 text-center">Coming soon</h1>
46+
<section class="py-16 max-w-3xl mx-auto">
47+
<h2 class="text-2xl font-bold mb-6">Platform Overview</h2>
48+
<p class="text-brand-gray dark:text-gray-400 leading-relaxed">The Proxmox Astronomy Lab is a production-scale computing platform built on a seven-node Proxmox VE cluster with hybrid RKE2 Kubernetes and strategic VM architecture. We're demonstrating that sophisticated astronomical computing doesn't require institutional resources, just deliberate engineering and open-science principles.</p>
49+
</section>
50+
51+
<section class="py-16">
52+
<h2 class="text-2xl font-bold text-center mb-10">Cluster Specifications</h2>
53+
<div class="max-w-2xl mx-auto overflow-x-auto">
54+
<table class="w-full text-left border-collapse">
55+
<tbody>
56+
<tr class="border-b border-brand-grid dark:border-dark-surface"><td class="py-3 px-4 font-semibold">Nodes</td><td class="py-3 px-4">7</td></tr>
57+
<tr class="border-b border-brand-grid dark:border-dark-surface"><td class="py-3 px-4 font-semibold">Total Cores</td><td class="py-3 px-4">144</td></tr>
58+
<tr class="border-b border-brand-grid dark:border-dark-surface"><td class="py-3 px-4 font-semibold">Total RAM</td><td class="py-3 px-4">704 GB</td></tr>
59+
<tr class="border-b border-brand-grid dark:border-dark-surface"><td class="py-3 px-4 font-semibold">Total NVMe</td><td class="py-3 px-4">26 TB</td></tr>
60+
<tr class="border-b border-brand-grid dark:border-dark-surface"><td class="py-3 px-4 font-semibold">Network Fabric</td><td class="py-3 px-4">10G LACP per node</td></tr>
61+
<tr class="border-b border-brand-grid dark:border-dark-surface"><td class="py-3 px-4 font-semibold">GPU</td><td class="py-3 px-4">RTX A4000 16GB</td></tr>
62+
</tbody>
63+
</table>
64+
</div>
65+
</section>
66+
67+
<section class="py-16 space-y-4">
68+
<h2 class="text-2xl font-bold text-center mb-10">Node Inventory</h2>
69+
<AccordionItem title="Node details (7 nodes)">
70+
<NodeInventoryTable rows={nodeRows} />
71+
</AccordionItem>
72+
</section>
73+
74+
<section class="py-16 space-y-4">
75+
<h2 class="text-2xl font-bold text-center mb-10">VM Inventory</h2>
76+
<AccordionItem title="VM details (9 VMs)">
77+
<VMInventoryTable rows={vmRows} />
78+
</AccordionItem>
79+
</section>
80+
81+
<section class="py-16">
82+
<h2 class="text-2xl font-bold text-center mb-10">Architecture Highlights</h2>
83+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-3xl mx-auto">
84+
<div class="p-6 rounded-xl bg-white dark:bg-dark-surface border border-brand-grid dark:border-brand-navy">
85+
<h3 class="font-semibold mb-2">Hybrid K8s + VM</h3>
86+
<p class="text-sm text-brand-gray dark:text-gray-400">RKE2 for dynamic ML workloads, strategic VMs for databases and services that don't benefit from orchestration</p>
87+
</div>
88+
<div class="p-6 rounded-xl bg-white dark:bg-dark-surface border border-brand-grid dark:border-brand-navy">
89+
<h3 class="font-semibold mb-2">PostgreSQL as materialization engine</h3>
90+
<p class="text-sm text-brand-gray dark:text-gray-400">Catalog joins and derived computations happen in PostgreSQL, results export to Parquet for distribution</p>
91+
</div>
92+
<div class="p-6 rounded-xl bg-white dark:bg-dark-surface border border-brand-grid dark:border-brand-navy">
93+
<h3 class="font-semibold mb-2">GPU compute</h3>
94+
<p class="text-sm text-brand-gray dark:text-gray-400">RTX A4000 (16 GB VRAM) for ML training and inference workloads</p>
95+
</div>
96+
<div class="p-6 rounded-xl bg-white dark:bg-dark-surface border border-brand-grid dark:border-brand-navy">
97+
<h3 class="font-semibold mb-2">10G networking</h3>
98+
<p class="text-sm text-brand-gray dark:text-gray-400">2x10G LACP per node for high-bandwidth data movement between compute and storage</p>
99+
</div>
100+
</div>
101+
</section>
102+
103+
<section class="py-16 max-w-3xl mx-auto">
104+
<h2 class="text-2xl font-bold mb-6">Data Pipeline</h2>
105+
<p class="text-brand-gray dark:text-gray-400 leading-relaxed">PostgreSQL serves as the materialization engine where VAC joins and derived computations occur. Final ARD products are exported to Parquet for distribution and analysis. The pipeline manages approximately 32 GB of catalog data in PostgreSQL and 108 GB of spectral tiles in Parquet format.</p>
106+
</section>
107+
108+
<section class="py-16 max-w-3xl mx-auto">
109+
<h2 class="text-2xl font-bold mb-6">Governance and Operational Practices</h2>
110+
<p class="text-brand-gray dark:text-gray-400 leading-relaxed mb-4">Operationally, the cluster is managed under the same discipline the org applies to its research: documented, reproducible, and publicly reviewable. Specifics:</p>
111+
<ul class="space-y-3 text-brand-gray dark:text-gray-400">
112+
<li><strong>Security baseline</strong> — working toward CIS Controls v8.1 Implementation Group 1 alignment, with documentation rewrites in progress</li>
113+
<li><strong>AI governance</strong> — model cards track intended use, data sources, evaluation results, and known limitations for the AI systems used across the org. NIST AI RMF alignment is tracked against the CIS-RAM method</li>
114+
<li><strong>Published templates</strong> — governance templates are maintained in the <a href="https://github.com/vintagedon/nist-ai-rmf-cookbook" target="_blank" rel="noopener" class="text-brand-steel hover:underline">NIST AI RMF Cookbook</a> for other small research orgs to adapt</li>
115+
<li><strong>Automation</strong> — Ansible-managed configuration, version-controlled infrastructure, passwordless-sudo fleet operations via a dedicated <code class="font-mono text-sm bg-brand-grid/50 dark:bg-dark-surface px-1 rounded">ansible01</code> identity</li>
116+
</ul>
117+
<p class="text-brand-gray dark:text-gray-400 leading-relaxed mt-4">None of this is certification; it's operational practice applied voluntarily at volunteer-organization scale.</p>
118+
</section>
119+
120+
<div class="py-16 text-center">
121+
<Button label="View Platform Repository" href="/projects/proxmox-astronomy-lab" variant="primary" />
122+
</div>
9123
</Container>
10124
</PageLayout>

0 commit comments

Comments
 (0)