generateMetadata

Metadata From Data

Product pages need a title and description from the database. Export an async generateMetadata that receives the same params as the page:

// app/products/[id]/page.tsx
import type { Metadata } from 'next';
import { getProduct } from '@/lib/products'; // wrapped in cache(), so the page reuses the result

type Props = { params: Promise<{ id: string }> };

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { id } = await params;
  const product = await getProduct(Number(id));
  if (!product) return { title: 'Product not found' };

  return {
    title: product.name,
    description: product.description.slice(0, 155),
    alternates: { canonical: '/products/' + product.id },
    openGraph: { images: [{ url: product.imageUrl, width: 800, height: 800 }] },
  };
}

Good Descriptions

Example

Search engines show about 150–160 characters. Cut at a word boundary and add an ellipsis:

function metaDescription(text: string, max = 155): string {
  const clean = text.replace(/\s+/g, ' ').trim();
  if (clean.length <= max) return clean;
  const cut = clean.slice(0, max - 1);
  return cut.slice(0, cut.lastIndexOf(' ')).replace(/[.,;:]+$/, '') + '…';
}

const desc = 'Redmi Note 14 5G with a 6.67-inch 120Hz AMOLED display,   MediaTek Dimensity 7025 Ultra processor, 50MP Sony camera, 5110mAh battery and 45W fast charging. Includes 2 years of OS updates.';
const out = metaDescription(desc);
console.log(out);
console.log(out.length, 'characters');
console.log(metaDescription('Short and sweet.'));

Output

Redmi Note 14 5G with a 6.67-inch 120Hz AMOLED display, MediaTek Dimensity 7025 Ultra processor, 50MP Sony camera, 5110mAh battery and 45W fast charging…
153 characters
Short and sweet.