← back to Stayclaim
src/app/promote/page.tsx
78 lines
import Link from 'next/link';
import type { Metadata } from 'next';
import { searchListings } from '@/lib/db';
import { BreadcrumbArchive } from '@/components/BreadcrumbArchive';
import { NodeCard } from '@/components/NodeCard';
import { FREE_FOREVER } from '@/lib/flags';
import { RetiredFeatureNotice } from '@/components/RetiredFeatureNotice';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
export const metadata: Metadata = {
robots: { index: false, follow: false },
};
const SLUG_RE = /^[a-z0-9-]+$/i;
const isHttpUrl = (u: unknown): u is string =>
typeof u === 'string' && /^https?:\/\//i.test(u.trim());
export default async function PromoteIndex() {
if (FREE_FOREVER) {
return (
<RetiredFeatureNotice
title="Promotion has been retired"
/>
);
}
let recent: Awaited<ReturnType<typeof searchListings>> = [];
try {
recent = await searchListings({ limit: 6 });
} catch {
recent = [];
}
return (
<>
<div className="max-w-6xl mx-auto px-6 pt-6">
<BreadcrumbArchive items={[{ label: 'Archive', href: '/' }, { label: 'Promote a listing' }]} />
</div>
<header className="max-w-6xl mx-auto px-6 py-12 border-b border-ink/10">
<p className="text-xs uppercase tracking-[0.15em] text-ink/50 mb-2">Sponsored placements</p>
<h1 className="font-display text-5xl md:text-6xl text-ink tracking-[-0.02em] leading-[1.02] max-w-4xl">
Put your current listing on top of the record.
</h1>
<p className="mt-4 font-display italic text-xl text-ink/70 max-w-prose">
Walled off from editorial. Logo of source (Zillow / Redfin / Airbnb). $29/mo flat.
</p>
</header>
<section className="max-w-6xl mx-auto px-6 py-10">
<h2 className="font-display text-3xl text-ink tracking-[-0.01em] mb-6">
Pick the address you’re promoting
</h2>
<p className="text-sm text-ink/60 mb-8 max-w-prose leading-relaxed">
Choose an existing record. We’ll verify ownership or agent representation before the placement goes
live. If your address isn’t in the archive yet, <Link href="/browse" className="underline-offset-2 hover:underline text-coral">submit it first</Link>.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
{recent
.filter(l => typeof l.slug === 'string' && SLUG_RE.test(l.slug))
.map(l => (
<NodeCard
key={l.id}
kind="address"
href={`/promote/${encodeURIComponent(l.slug)}`}
title={l.title}
subtitle={l.address_line1 ?? l.city ?? undefined}
imageUrl={isHttpUrl(l.hero_image) ? l.hero_image : undefined}
eyebrow="Promote this address"
/>
))}
</div>
</section>
</>
);
}