From 30808071fdea70428f1720735e5483193a54a115 Mon Sep 17 00:00:00 2001 From: "Aryan Singh K." <70511529+aryansk@users.noreply.github.com> Date: Sat, 15 Aug 2026 17:12:39 +0530 Subject: [PATCH 1/2] feat: emit JSON-LD Place structured data on city pages (#120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each place on a city page now gets a schema.org JSON-LD block using a specific subtype where one genuinely fits (Library, GovernmentOffice, Airport) and Place otherwise. Only real dataset fields are emitted: name, address, geo with latitude/longitude, and a deep link to the place's map pin. geo is omitted entirely when coordinates are missing or unusable, and address when absent — no placeholders, so the structured data can never misrepresent the page. Closes #120 --- src/app/city/[slug]/page.tsx | 10 ++++ src/lib/jsonld.test.ts | 112 +++++++++++++++++++++++++++++++++++ src/lib/jsonld.ts | 63 ++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 src/lib/jsonld.test.ts create mode 100644 src/lib/jsonld.ts diff --git a/src/app/city/[slug]/page.tsx b/src/app/city/[slug]/page.tsx index 41cae43..fcb75a9 100644 --- a/src/app/city/[slug]/page.tsx +++ b/src/app/city/[slug]/page.tsx @@ -8,6 +8,7 @@ import { placesByType, } from "@/lib/city-pages"; import { getPlaces } from "@/lib/places"; +import { placeJsonLdScript } from "@/lib/jsonld"; import { humanizeCity, PLACE_TYPE_LABELS } from "@/lib/types"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; @@ -64,6 +65,15 @@ export default async function CityPage({ params }: CityPageProps) { return ( + {page.places.map((place) => ( + ` can never terminate the + * block early and inject markup. + */ +export function placeJsonLdScript(place: Place): string { + return JSON.stringify(placeJsonLd(place)).replace(/ Date: Sat, 15 Aug 2026 18:04:47 +0530 Subject: [PATCH 2/2] test: fix TS2352 in jsonld.test.ts by casting via unknown --- src/lib/jsonld.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/jsonld.test.ts b/src/lib/jsonld.test.ts index b4a82d8..21ceed9 100644 --- a/src/lib/jsonld.test.ts +++ b/src/lib/jsonld.test.ts @@ -70,9 +70,9 @@ describe("placeJsonLd", () => { }); it("omits geo when coordinates are missing instead of emitting nulls", () => { - const withoutLat = { ...place(), lat: undefined } as Place; + const withoutLat = ({ ...place(), lat: undefined } as unknown) as Place; expect(placeJsonLd(withoutLat)).not.toHaveProperty("geo"); - const withoutLng = { ...place(), lng: undefined } as Place; + const withoutLng = ({ ...place(), lng: undefined } as unknown) as Place; expect(placeJsonLd(withoutLng)).not.toHaveProperty("geo"); });