2026-07-04 22:53:10 +00:00
---
import BaseLayout from "../layouts/BaseLayout.astro";
import Breadcrumbs from "../components/Breadcrumbs.astro";
import Icon from "../components/Icon.astro";
import { SITE } from "../lib/blog-data.js";
---
<BaseLayout
title={`Contact - ${SITE.name}`}
description={`Get in touch with ${SITE.name}.`}
canonical="/contact"
>
<div class="mx-auto max-w-3xl px-5 py-12">
<Breadcrumbs items={[{ label: "Home", to: "/" }, { label: "Contact" }]} />
<header class="mt-6">
<div class="text-xs font-medium uppercase tracking-[0.2em] text-primary">Contact</div>
<h1 class="mt-2 font-serif text-5xl font-semibold tracking-tight">Say hello.</h1>
<p class="mt-4 max-w-xl text-muted-foreground">
2026-07-04 23:13:55 +00:00
A tip, a correction, or a question. We read everything and reply to most of it.
2026-07-04 22:53:10 +00:00
</p>
</header>
<div class="mt-12 grid gap-12 lg:grid-cols-[1fr_240px]">
<form data-contact-form class="space-y-5">
<div>
<label for="name" class="text-xs font-medium uppercase tracking-wider text-muted-foreground">Name</label>
<input id="name" required class="mt-2 w-full border-0 border-b border-input bg-transparent py-2 text-base outline-none focus:border-primary" />
</div>
<div>
<label for="email" class="text-xs font-medium uppercase tracking-wider text-muted-foreground">Email</label>
<input id="email" type="email" required class="mt-2 w-full border-0 border-b border-input bg-transparent py-2 text-base outline-none focus:border-primary" />
</div>
<div>
<label for="message" class="text-xs font-medium uppercase tracking-wider text-muted-foreground">Message</label>
<textarea id="message" required rows="6" class="mt-2 w-full border-0 border-b border-input bg-transparent py-2 text-base outline-none focus:border-primary"></textarea>
</div>
<div aria-hidden="true" style="position:absolute;left:-9999px;height:0;overflow:hidden">
<label>Website<input id="website" name="website" tabindex="-1" autocomplete="off" /></label>
</div>
<button type="submit" class="rounded-md bg-foreground px-6 py-2.5 text-sm font-medium text-background hover:opacity-90">
Send
</button>
<p data-contact-sent class="text-sm text-primary" role="status" hidden>Thanks — we'll be in touch.</p>
</form>
<aside class="space-y-6 border-l border-border pl-8 lg:block">
<div>
<div class="text-xs font-medium uppercase tracking-wider text-muted-foreground">Elsewhere</div>
<ul class="mt-3 space-y-3 text-sm">
2026-07-04 23:13:55 +00:00
<li><a href="https://x.com/" class="flex items-center gap-2 hover:text-primary"><Icon name="twitter" class="h-3.5 w-3.5" /> @yourhandle</a></li>
2026-07-04 22:53:10 +00:00
<li><a href="/rss.xml" class="flex items-center gap-2 hover:text-primary"><Icon name="rss" class="h-3.5 w-3.5" /> RSS feed</a></li>
</ul>
</div>
<div>
2026-07-04 23:13:55 +00:00
<div class="text-xs font-medium uppercase tracking-wider text-muted-foreground">Tips</div>
2026-07-04 22:53:10 +00:00
<p class="mt-2 text-sm text-muted-foreground">Know a new opening or an underrated spot? Send it our way — we factor reader tips into our guides and news roundups.</p>
</div>
</aside>
</div>
</div>
</BaseLayout>
<script>
const contactForm = document.querySelector("[data-contact-form]");
const sent = document.querySelector("[data-contact-sent]");
contactForm?.addEventListener("submit", async (event) => {
event.preventDefault();
const btn = contactForm.querySelector("button[type=submit]");
const payload = {
name: document.getElementById("name").value.trim(),
email: document.getElementById("email").value.trim(),
message: document.getElementById("message").value.trim(),
website: document.getElementById("website")?.value || "",
};
if (btn) {
btn.disabled = true;
btn.textContent = "Sending…";
}
try {
const r = await fetch("/contact-submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (!r.ok) throw new Error((await r.json()).error || "Something went wrong. Please try again.");
contactForm.reset();
if (sent) sent.hidden = false;
} catch (err) {
alert(err.message);
} finally {
if (btn) {
btn.disabled = false;
btn.textContent = "Send";
}
}
});
</script>