← back to Stayclaim
src/app/map/page.tsx
60 lines
import type { Metadata } from 'next';
import { searchListings, getAllFilmingPins } from '@/lib/db';
import { BreadcrumbArchive } from '@/components/BreadcrumbArchive';
import { type MapPin } from '@/components/InteractiveMapMount';
import { MapWithLayers } from './MapWithLayers';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
export const metadata: Metadata = {
title: 'Map',
description: 'Every public address in the archive on a single interactive map. Toggle the filming layer to see what was shot where.',
alternates: { canonical: '/map' },
};
export default async function MapPage() {
const [listings, filming] = await Promise.all([
searchListings({ limit: 500 }),
getAllFilmingPins(),
]);
const archivePins: MapPin[] = listings
.filter(l => l.latitude != null && l.longitude != null)
.map(l => ({
slug: l.slug,
title: l.title,
subtitle: l.city ?? undefined,
lat: Number(l.latitude),
lng: Number(l.longitude),
}))
.filter(p =>
Number.isFinite(p.lat) &&
Number.isFinite(p.lng) &&
Math.abs(p.lat) <= 90 &&
Math.abs(p.lng) <= 180 &&
!(p.lat === 0 && p.lng === 0)
);
return (
<>
<div className="max-w-7xl mx-auto px-6 pt-6">
<BreadcrumbArchive items={[{ label: 'Archive', href: '/' }, { label: 'Map' }]} />
</div>
<header className="max-w-7xl mx-auto px-6 py-8">
<p className="text-xs uppercase tracking-[0.15em] text-ink/50 mb-2">Map</p>
<h1 className="font-display text-5xl md:text-6xl text-ink tracking-[-0.02em] leading-[1.02]">
Every address. Every shot.
</h1>
<p className="mt-3 font-mono text-[11px] text-ink/45">
{archivePins.length} archive pins · {filming.length} filmed locations · click any pin to open its record
</p>
</header>
<div className="max-w-7xl mx-auto px-6 pb-12">
<MapWithLayers archivePins={archivePins} filmingPins={filming} />
</div>
</>
);
}