← back to Homesonspec
apps/web/src/app/[state]/[city]/page.tsx
46 lines
import Link from "next/link";
import { notFound } from "next/navigation";
import { prisma } from "@homesonspec/database";
import { fmtPrice } from "@homesonspec/shared-ui";
export const dynamic = "force-dynamic";
/** Minimal city/metro SEO landing — full editorial treatment deferred. */
export default async function CityLandingPage({
params,
}: {
params: Promise<{ state: string; city: string }>;
}) {
const { state, city } = await params;
const stateUpper = state.toUpperCase();
if (!/^[a-z]{2}$/i.test(state)) notFound();
const cityName = decodeURIComponent(city).replace(/-/g, " ");
const homes = await prisma.inventoryHome.findMany({
where: { state: stateUpper, city: { equals: cityName, mode: "insensitive" }, status: "PUBLISHED", isDemo: false },
include: { community: { select: { slug: true, name: true } }, builder: { select: { name: true } } },
orderBy: { publishedAt: "desc" },
take: 24,
});
if (homes.length === 0) notFound();
return (
<div className="mx-auto max-w-6xl px-4 py-8">
<h1 className="text-3xl font-bold">
New construction homes in {homes[0]!.city}, {stateUpper}
</h1>
<p className="mt-1 text-sm text-neutral-500">{homes.length} available demonstration homes</p>
<div className="mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{homes.map((home) => (
<Link key={home.id} href={`/homes/${home.id}`}
className="rounded-xl border border-neutral-200 p-4 shadow-sm hover:border-teal-400">
<div className="font-semibold">{fmtPrice(home.price === null ? null : Number(home.price))}</div>
<div className="text-sm text-neutral-600">{home.street}</div>
<div className="text-sm text-neutral-500">{home.community.name} · {home.builder.name}</div>
</Link>
))}
</div>
</div>
);
}