feat(hub): landing page with product cards (hides empty products)
This commit is contained in:
184
src/pages/index.astro
Normal file
184
src/pages/index.astro
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
---
|
||||||
|
import { getCollection } from 'astro:content';
|
||||||
|
import '~/styles/anhh-tokens.css';
|
||||||
|
import '@fontsource-variable/inter';
|
||||||
|
|
||||||
|
interface Product {
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
blurb: string;
|
||||||
|
href: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardcoded product metadata. Adding a new product = adding to this map.
|
||||||
|
const PRODUCT_META: Record<string, { title: string; blurb: string; firstSection: string }> = {
|
||||||
|
whp: {
|
||||||
|
title: 'WHP',
|
||||||
|
blurb: 'Our hosting control panel. Add domains, create sites, manage email, set up backups.',
|
||||||
|
firstSection: 'getting-started/welcome',
|
||||||
|
},
|
||||||
|
wordpress: {
|
||||||
|
title: 'WordPress',
|
||||||
|
blurb: 'Tips and tricks for getting the most out of WordPress on WHP.',
|
||||||
|
firstSection: 'index',
|
||||||
|
},
|
||||||
|
'email-clients': {
|
||||||
|
title: 'Email clients',
|
||||||
|
blurb: 'Configure Outlook, Apple Mail, Thunderbird, and mobile clients.',
|
||||||
|
firstSection: 'index',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const docs = await getCollection('docs');
|
||||||
|
|
||||||
|
// Group articles by top-level product folder
|
||||||
|
const byProduct = new Map<string, number>();
|
||||||
|
for (const entry of docs) {
|
||||||
|
const product = entry.id.split('/')[0];
|
||||||
|
byProduct.set(product, (byProduct.get(product) ?? 0) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const visibleProducts: Product[] = Array.from(byProduct.entries())
|
||||||
|
.filter(([slug]) => PRODUCT_META[slug] !== undefined)
|
||||||
|
.filter(([, count]) => count > 0)
|
||||||
|
.map(([slug, count]) => ({
|
||||||
|
slug,
|
||||||
|
title: PRODUCT_META[slug].title,
|
||||||
|
blurb: PRODUCT_META[slug].blurb,
|
||||||
|
href: `/${slug}/${PRODUCT_META[slug].firstSection}/`,
|
||||||
|
count,
|
||||||
|
}))
|
||||||
|
.sort((a, b) => a.title.localeCompare(b.title));
|
||||||
|
---
|
||||||
|
|
||||||
|
<html lang="en" data-theme="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
<title>An Honest Host Knowledge Base</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Customer documentation for WHP and other An Honest Host services."
|
||||||
|
/>
|
||||||
|
<link rel="canonical" href="https://kb.anhonesthost.com/" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background: var(--anhh-bg, #0a1628);
|
||||||
|
color: var(--anhh-text-primary, #f0f4ff);
|
||||||
|
font-family: 'Inter Variable', 'Inter', system-ui, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
header,
|
||||||
|
footer {
|
||||||
|
padding: 1.5rem 2rem;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
border-bottom: 1px solid var(--anhh-border-color, #334155);
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
border-top: 1px solid var(--anhh-border-color, #334155);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--anhh-text-secondary, #94a3b8);
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 64rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
.lede {
|
||||||
|
color: var(--anhh-text-secondary, #94a3b8);
|
||||||
|
font-size: 1.125rem;
|
||||||
|
margin: 0 0 3rem;
|
||||||
|
}
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
a.card {
|
||||||
|
display: block;
|
||||||
|
background: var(--anhh-bg-surface, #1e293b);
|
||||||
|
border: 1px solid var(--anhh-border-color, #334155);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
transition:
|
||||||
|
border-color 120ms ease,
|
||||||
|
transform 120ms ease;
|
||||||
|
}
|
||||||
|
a.card:hover,
|
||||||
|
a.card:focus {
|
||||||
|
border-color: var(--anhh-accent, #00d4aa);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
a.card h2 {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--anhh-accent, #00d4aa);
|
||||||
|
}
|
||||||
|
a.card p {
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
color: var(--anhh-text-secondary, #94a3b8);
|
||||||
|
}
|
||||||
|
a.card .count {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--anhh-text-muted, #64748b);
|
||||||
|
}
|
||||||
|
.empty {
|
||||||
|
background: var(--anhh-bg-surface, #1e293b);
|
||||||
|
border: 1px dashed var(--anhh-border-color, #334155);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
padding: 2rem;
|
||||||
|
color: var(--anhh-text-muted, #64748b);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
footer a {
|
||||||
|
color: var(--anhh-accent, #00d4aa);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header><strong>An Honest Host</strong> · Knowledge Base</header>
|
||||||
|
<main>
|
||||||
|
<h1>Knowledge Base</h1>
|
||||||
|
<p class="lede">Pick a product to get started.</p>
|
||||||
|
|
||||||
|
{
|
||||||
|
visibleProducts.length === 0 ? (
|
||||||
|
<div class="empty">No documentation has been published yet.</div>
|
||||||
|
) : (
|
||||||
|
<div class="grid">
|
||||||
|
{visibleProducts.map((p) => (
|
||||||
|
<a class="card" href={p.href}>
|
||||||
|
<h2>{p.title}</h2>
|
||||||
|
<p>{p.blurb}</p>
|
||||||
|
<span class="count">
|
||||||
|
{p.count} {p.count === 1 ? 'article' : 'articles'}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
Need help?{' '}
|
||||||
|
<a href="https://secure.anhonesthost.com/submitticket.php">Open a support ticket</a>. ·{' '}
|
||||||
|
<a href="https://repo.anhonesthost.net/cloud-hosting-platform/kb-anhonesthost">Repo on Gitea</a>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user