From harness-claude
Define SEO metadata, Open Graph tags, and dynamic OG images using the Next.js Metadata API in App Router. Covers static metadata, async `generateMetadata`, title templates, metadataBase, opengraph-image.tsx, robots, and canonical URLs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:next-metadata-apiThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Define SEO metadata, Open Graph tags, and dynamic OG images with the Metadata API
Define SEO metadata, Open Graph tags, and dynamic OG images with the Metadata API
metadata constant from any layout.tsx or page.tsx for static metadata.generateMetadata({ params, searchParams }) function for dynamic metadata derived from route parameters or fetched data.title.template property in root layout.tsx to set a consistent title suffix — child pages set only the page-specific prefix.metadataBase in root metadata to resolve relative URLs in openGraph.images and twitter.images.opengraph-image.tsx in any route segment to generate a dynamic OG image with @vercel/og — no external service needed.robots, canonical, and alternates fields to control crawler behavior and avoid duplicate content.layout.tsx and page.tsx for the same route — define at the most specific level.// app/layout.tsx — root metadata with template and base URL
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: { default: 'My App', template: '%s | My App' },
description: 'The best app in the world',
openGraph: { type: 'website', locale: 'en_US', siteName: 'My App' },
};
// app/posts/[slug]/page.tsx — dynamic metadata
import type { Metadata } from 'next';
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const post = await fetchPost(params.slug);
return {
title: post.title, // becomes "Post Title | My App" via template
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [{ url: `/api/og?title=${encodeURIComponent(post.title)}`, width: 1200, height: 630 }],
},
};
}
// app/posts/[slug]/opengraph-image.tsx — dynamic OG image
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';
export default async function Image({ params }: { params: { slug: string } }) {
const post = await fetchPost(params.slug);
return new ImageResponse(<div style={{ fontSize: 48 }}>{post.title}</div>);
}
The Metadata API replaces <Head> from next/head in the App Router. It is declarative, type-safe, and tree-mergeable — parent layout metadata flows down to child pages, with child values winning on conflict.
title.template: The root layout sets title: { default: 'My App', template: '%s | My App' }. Every child page that sets title: 'Dashboard' automatically becomes 'Dashboard | My App'. Pages that do not set a title fall back to default.
metadataBase: Required when any metadata field uses a relative URL (especially openGraph.images). Without it, Next.js warns and relative URLs are not resolved correctly for social crawlers.
Dynamic OG images with opengraph-image.tsx: Place this file in any route segment directory. It exports an ImageResponse and runs on the Edge Runtime. Next.js automatically serves it at /{route}/opengraph-image and links it from the page's <meta> tags. No additional configuration needed.
Deduplication: Next.js merges metadata from all parent layouts. If a parent sets openGraph.images and a child does not, the parent's images are used. If the child sets openGraph.images, it replaces the parent's entirely — not merged.
Sitemap and robots: Create app/sitemap.ts (returns MetadataRoute.Sitemap) and app/robots.ts (returns MetadataRoute.Robots) for programmatic control of these files.
https://nextjs.org/docs/app/building-your-application/optimizing/metadata
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeSets page titles, Open Graph tags, canonical URLs, and JSON-LD structured data per page using useSeoMeta and useHead in Nuxt. Useful for implementing social previews, robots directives, and SSR-optimized metadata.
Adds Open Graph (OGP) and Twitter Card meta tags for social media link previews. Provides tag reference, image sizing guidelines, and required/optional tag documentation.
Generates Open Graph social media preview images by creating a screenshot-optimized page that matches the project's design system, captures it at 1200x630 with Playwright, and configures meta tags.