diff --git a/app/wall/[handle]/page.tsx b/app/wall/[handle]/page.tsx new file mode 100644 index 000000000..3ae1bbf2c --- /dev/null +++ b/app/wall/[handle]/page.tsx @@ -0,0 +1,145 @@ +import type { Metadata } from 'next'; +import { notFound } from 'next/navigation'; +import { Suspense } from 'react'; + +import { GridTileImage } from 'components/grid/tile'; +import Footer from 'components/layout/footer'; +import { Gallery } from 'components/product/gallery'; +import { ProductDescription } from 'components/product/product-description'; +import { HIDDEN_PRODUCT_TAG } from 'lib/constants'; +import { getProduct, getProductRecommendations } from 'lib/shopify'; +import { Image } from 'lib/shopify/types'; +import Link from 'next/link'; + +export const runtime = 'edge'; + +export async function generateMetadata({ + params +}: { + params: { handle: string }; +}): Promise { + const product = await getProduct(params.handle); + + if (!product) return notFound(); + + const { url, width, height, altText: alt } = product.featuredImage || {}; + const hide = !product.tags.includes(HIDDEN_PRODUCT_TAG); + + return { + title: product.seo.title || product.title, + description: product.seo.description || product.description, + robots: { + index: hide, + follow: hide, + googleBot: { + index: hide, + follow: hide + } + }, + openGraph: url + ? { + images: [ + { + url, + width, + height, + alt + } + ] + } + : null + }; +} + +export default async function ProductPage({ params }: { params: { handle: string } }) { + const product = await getProduct(params.handle); + + if (!product) return notFound(); + + const productJsonLd = { + '@context': 'https://schema.org', + '@type': 'Product', + name: product.title, + description: product.description, + image: product.featuredImage.url, + offers: { + '@type': 'AggregateOffer', + availability: product.availableForSale + ? 'https://schema.org/InStock' + : 'https://schema.org/OutOfStock', + priceCurrency: product.priceRange.minVariantPrice.currencyCode, + highPrice: product.priceRange.maxVariantPrice.amount, + lowPrice: product.priceRange.minVariantPrice.amount + } + }; + + return ( + <> +