feat(seo): add metadata, sitemap, robots, JSON-LD, dynamic OG image
- Centralize brand/keyword config in lib/site.ts (slogan, 22 keywords). - Root layout: metadataBase, title template, OG/Twitter defaults, robots rules. - Per-page metadata: home, trips list (filter-aware), trip detail, profile (noindex). - Layout wrappers add metadata to client-component pages: login, register, create-trip. - Trip detail: generateMetadata + JSON-LD Event + BreadcrumbList (price, availability, rating). - Home page: JSON-LD Organization + WebSite + SearchAction (sitelink search). - app/sitemap.ts: dynamic sitemap pulling OPEN/FULL trips from Prisma. - app/robots.ts: disallow /api/, /profile, /create-trip; references sitemap. - app/trips/[id]/opengraph-image.tsx: dynamic 1200x630 OG image per trip with cover photo, title, mountain, date, price, brand badge. - Seeder: switch trip images from local SVG placeholders to real Unsplash CDN URLs. - Drop 18 obsolete seed SVGs from public/images/seed/. New env: NEXT_PUBLIC_SITE_URL (defaults to localhost:3000) — set to prod domain on deploy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+43
-18
@@ -107,6 +107,31 @@ async function main() {
|
||||
const utc = (y: number, m0: number, d: number, h = 12, min = 0) =>
|
||||
new Date(Date.UTC(y, m0, d, h, min, 0, 0));
|
||||
|
||||
// Unsplash mountain photos (URL CDN publik, gratis, stabil).
|
||||
// Slug ID di komentar = id di unsplash.com/photos/{slug} buat ditelusuri ulang.
|
||||
const img = (id: string) =>
|
||||
`https://images.unsplash.com/photo-${id}?w=1200&q=80&auto=format&fit=crop`;
|
||||
const MOUNTAIN_PHOTOS = {
|
||||
papandayan1: img("1554629947-334ff61d85dc"), // xfngap_DToE
|
||||
papandayan2: img("1464822759023-fed622ff2c3b"), // Bkci_8qcdvQ
|
||||
papandayan3: img("1454496522488-7a8e488e8606"), // 9wg5jCEPBsw
|
||||
ciremai1: img("1480497490787-505ec076689f"), // 6bKxagnIDtk
|
||||
ciremai2: img("1483728642387-6c3bdd6c93e5"), // YFFGkE3y4F8
|
||||
ciremai3: img("1502085671122-2d218cd434e6"), // NNmiv6zcFvk
|
||||
gede1: img("1478059299873-f047d8c5fe1a"), // DXQB5D1njMY
|
||||
gede2: img("1519681393784-d120267933ba"), // z8ct_Q3oCqM
|
||||
gede3: img("1501785888041-af3ef285b470"), // T7K4aEPoGGk
|
||||
gede4: img("1540979388789-6cee28a1cdc9"), // eUFfY6cwjSU
|
||||
tangkuban1: img("1506905925346-21bda4d32df4"), // 1527pjeb6jg
|
||||
tangkuban2: img("1490682143684-14369e18dce8"), // 8c6eS43iq1o
|
||||
malabar1: img("1494548162494-384bba4ab999"), // xP_AGmeEa6s
|
||||
malabar2: img("1500964757637-c85e8a162699"), // twukN12EN7c
|
||||
malabar3: img("1549880181-56a44cf4a9a5"), // ePpaQC2c1xA
|
||||
guntur1: img("1558883493-8b86ff880fec"), // vaG8rOJLDHo
|
||||
guntur2: img("1554629947-334ff61d85dc"), // reuse — xfngap_DToE
|
||||
guntur3: img("1464822759023-fed622ff2c3b"), // reuse — Bkci_8qcdvQ
|
||||
} as const;
|
||||
|
||||
// --- Trip 1: Papandayan (by Dede Inoen) — 2 hari ---
|
||||
const trip1 = await prisma.trip.create({
|
||||
data: {
|
||||
@@ -144,9 +169,9 @@ Minggu
|
||||
organizerId: dede.id,
|
||||
images: {
|
||||
create: [
|
||||
{ url: "/images/seed/papandayan-1.svg", caption: "Kawah Papandayan", order: 0 },
|
||||
{ url: "/images/seed/papandayan-2.svg", caption: "Track menuju puncak", order: 1 },
|
||||
{ url: "/images/seed/papandayan-3.svg", caption: "Camping ground Pondok Salada", order: 2 },
|
||||
{ url: MOUNTAIN_PHOTOS.papandayan1, caption: "Kawah Papandayan", order: 0 },
|
||||
{ url: MOUNTAIN_PHOTOS.papandayan2, caption: "Track menuju puncak", order: 1 },
|
||||
{ url: MOUNTAIN_PHOTOS.papandayan3, caption: "Camping ground Pondok Salada", order: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -175,9 +200,9 @@ Itinerary:
|
||||
organizerId: panji.id,
|
||||
images: {
|
||||
create: [
|
||||
{ url: "/images/seed/ciremai-1.svg", caption: "Puncak Ciremai 3.078 mdpl", order: 0 },
|
||||
{ url: "/images/seed/ciremai-2.svg", caption: "Jalur pendakian via Apuy", order: 1 },
|
||||
{ url: "/images/seed/ciremai-3.svg", caption: "Sunrise dari puncak", order: 2 },
|
||||
{ url: MOUNTAIN_PHOTOS.ciremai1, caption: "Puncak Ciremai 3.078 mdpl", order: 0 },
|
||||
{ url: MOUNTAIN_PHOTOS.ciremai2, caption: "Jalur pendakian via Apuy", order: 1 },
|
||||
{ url: MOUNTAIN_PHOTOS.ciremai3, caption: "Sunrise dari puncak", order: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -204,10 +229,10 @@ Start malam, summit saat sunrise. View epic dijamin!`,
|
||||
organizerId: fiersa.id,
|
||||
images: {
|
||||
create: [
|
||||
{ url: "/images/seed/gede-1.svg", caption: "Puncak Gunung Gede", order: 0 },
|
||||
{ url: "/images/seed/gede-2.svg", caption: "Surya Kencana padang edelweis", order: 1 },
|
||||
{ url: "/images/seed/gede-3.svg", caption: "Blue lake / Danau Biru", order: 2 },
|
||||
{ url: "/images/seed/gede-4.svg", caption: "Night hike track Cibodas", order: 3 },
|
||||
{ url: MOUNTAIN_PHOTOS.gede1, caption: "Puncak Gunung Gede", order: 0 },
|
||||
{ url: MOUNTAIN_PHOTOS.gede2, caption: "Surya Kencana padang edelweis", order: 1 },
|
||||
{ url: MOUNTAIN_PHOTOS.gede3, caption: "Blue lake / Danau Biru", order: 2 },
|
||||
{ url: MOUNTAIN_PHOTOS.gede4, caption: "Night hike track Cibodas", order: 3 },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -234,8 +259,8 @@ Explore Kawah Ratu, Kawah Domas, foto-foto, terus makan sate maranggi!`,
|
||||
organizerId: dede.id,
|
||||
images: {
|
||||
create: [
|
||||
{ url: "/images/seed/tangkuban-1.svg", caption: "Kawah Ratu", order: 0 },
|
||||
{ url: "/images/seed/tangkuban-2.svg", caption: "Kawah Domas", order: 1 },
|
||||
{ url: MOUNTAIN_PHOTOS.tangkuban1, caption: "Kawah Ratu", order: 0 },
|
||||
{ url: MOUNTAIN_PHOTOS.tangkuban2, caption: "Kawah Domas", order: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -262,9 +287,9 @@ Trip ringan, 3-4 jam naik. Cocok buat yang mau healing malam-malam.`,
|
||||
organizerId: fiersa.id,
|
||||
images: {
|
||||
create: [
|
||||
{ url: "/images/seed/malabar-1.svg", caption: "Puncak Malabar malam hari", order: 0 },
|
||||
{ url: "/images/seed/malabar-2.svg", caption: "View Bandung dari atas", order: 1 },
|
||||
{ url: "/images/seed/malabar-3.svg", caption: "Track pendakian", order: 2 },
|
||||
{ url: MOUNTAIN_PHOTOS.malabar1, caption: "Puncak Malabar malam hari", order: 0 },
|
||||
{ url: MOUNTAIN_PHOTOS.malabar2, caption: "View Bandung dari atas", order: 1 },
|
||||
{ url: MOUNTAIN_PHOTOS.malabar3, caption: "Track pendakian", order: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -291,9 +316,9 @@ Buat yang suka challenge. Pemandangan kawah aktif dari dekat!`,
|
||||
organizerId: panji.id,
|
||||
images: {
|
||||
create: [
|
||||
{ url: "/images/seed/guntur-1.svg", caption: "Kawah aktif Gunung Guntur", order: 0 },
|
||||
{ url: "/images/seed/guntur-2.svg", caption: "Jalur berbatu menuju puncak", order: 1 },
|
||||
{ url: "/images/seed/guntur-3.svg", caption: "View dari puncak", order: 2 },
|
||||
{ url: MOUNTAIN_PHOTOS.guntur1, caption: "Kawah aktif Gunung Guntur", order: 0 },
|
||||
{ url: MOUNTAIN_PHOTOS.guntur2, caption: "Jalur berbatu menuju puncak", order: 1 },
|
||||
{ url: MOUNTAIN_PHOTOS.guntur3, caption: "View dari puncak", order: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user