added contact page

This commit is contained in:
2026-05-14 17:06:27 +02:00
parent b0f2634346
commit 0102c89d81
6 changed files with 290 additions and 5 deletions
+116
View File
@@ -0,0 +1,116 @@
---
import Layout from '../layouts/Layout.astro';
interface ContactLink {
kind: string;
label: string;
value: string;
}
interface SiteConfig {
contact_intro?: string;
contact_links?: ContactLink[];
}
const API_URL = process.env.PUBLIC_API_URL || 'http://localhost:3000';
let siteConfig: SiteConfig = {};
let error = '';
try {
const res = await fetch(`${API_URL}/api/config`);
if (res.ok) {
siteConfig = await res.json();
} else {
error = 'Failed to load contact details.';
}
} catch (e) {
error = `Could not connect to backend: ${e instanceof Error ? e.message : String(e)}`;
console.error(error);
}
const links: ContactLink[] = siteConfig.contact_links ?? [];
const intro = siteConfig.contact_intro ?? '';
function hrefFor(link: ContactLink): string {
const v = link.value.trim();
if (link.kind === 'email') {
return v.startsWith('mailto:') ? v : `mailto:${v}`;
}
return v;
}
function isExternal(link: ContactLink): boolean {
return link.kind !== 'email';
}
const KIND_LABEL: Record<string, string> = {
email: 'Email',
mastodon: 'Mastodon',
bluesky: 'Bluesky',
github: 'GitHub',
instagram: 'Instagram',
url: 'Link',
};
---
<Layout title="Contact" description="Get in touch.">
<section class="max-w-2xl mx-auto">
<div class="mb-10 md:mb-14">
<div class="font-display italic text-[var(--subtext0)] text-xs tracking-[0.3em] uppercase mb-4">Correspondence</div>
<h1 class="font-display italic font-semibold text-[var(--text)] text-5xl md:text-6xl leading-[0.95] tracking-tight mb-6">
Get in touch
</h1>
{intro && (
<p class="font-sans text-lg text-[var(--subtext1)] leading-relaxed whitespace-pre-line">
{intro}
</p>
)}
</div>
{error && (
<div class="glass p-6 text-center mb-8 border-[var(--red)]/40">
<p class="font-display italic text-[var(--red)]">{error}</p>
</div>
)}
{links.length === 0 && !error && (
<div class="glass p-10 text-center">
<p class="font-display italic text-[var(--subtext0)] text-lg">
No contact channels listed yet.
</p>
</div>
)}
{links.length > 0 && (
<ul class="space-y-3">
{links.map((link) => (
<li>
<a
href={hrefFor(link)}
{...(isExternal(link) ? { target: '_blank', rel: 'noopener noreferrer me' } : {})}
class="group flex items-baseline justify-between gap-4 px-5 py-4 border border-[var(--surface2)]/60 hover:border-[var(--mauve)]/60 transition-colors"
style="border-radius: 1px"
>
<div class="min-w-0">
<div class="font-display italic text-xs uppercase tracking-[0.25em] text-[var(--subtext0)] mb-1">
{KIND_LABEL[link.kind] ?? link.kind}
</div>
<div class="font-display italic text-xl md:text-2xl text-[var(--text)] group-hover:text-[var(--mauve)] transition-colors truncate">
{link.label}
</div>
</div>
<div class="font-mono text-xs text-[var(--subtext0)] hidden md:block truncate max-w-[40%]" title={link.value}>
{link.value}
</div>
</a>
</li>
))}
</ul>
)}
<div class="section-rule mt-16">
<span class="ornament">✦</span>
</div>
</section>
</Layout>