بنقرة واحدة
frontend-nextjs-seo
Implementing SEO for Next.js applications
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Implementing SEO for Next.js applications
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | frontend-nextjs-seo |
| description | Implementing SEO for Next.js applications |
Scope: Metadata API, Open Graph, structured data (JSON-LD), sitemaps, robots.txt Lines: ~280 Last Updated: 2025-10-18
Activate this skill when:
On-page SEO:
Technical SEO:
// app/page.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Home - My Website',
description: 'Welcome to my website. Discover amazing products and services.',
keywords: ['product', 'service', 'website'],
authors: [{ name: 'John Doe', url: 'https://example.com/authors/john' }],
creator: 'John Doe',
publisher: 'My Company',
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
alternates: {
canonical: 'https://example.com',
languages: {
'en-US': 'https://example.com',
'es-ES': 'https://example.com/es',
},
},
};
export default function HomePage() {
return <h1>Home Page</h1>;
}
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
interface Props {
params: { slug: string };
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
// Fetch post data
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
authors: [{ name: post.author.name }],
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
authors: [post.author.name],
images: [
{
url: post.coverImage,
width: 1200,
height: 630,
alt: post.title,
},
],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
};
}
export default function BlogPostPage({ params }: Props) {
return <article>...</article>;
}
// app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: {
default: 'My Website',
template: '%s | My Website', // Page title will be "About | My Website"
},
description: 'Default description',
};
// app/about/page.tsx
export const metadata: Metadata = {
title: 'About', // Becomes "About | My Website"
};
// app/layout.tsx
import type { Viewport } from 'next';
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
maximumScale: 1,
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
{ media: '(prefers-color-scheme: dark)', color: '#000000' },
],
};
// app/page.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Product Name',
description: 'Product description',
openGraph: {
type: 'website',
url: 'https://example.com',
title: 'Product Name',
description: 'Product description',
siteName: 'My Website',
locale: 'en_US',
images: [
{
url: 'https://example.com/og-image.jpg',
width: 1200,
height: 630,
alt: 'Product preview',
type: 'image/jpeg',
},
],
},
};
export const metadata: Metadata = {
twitter: {
card: 'summary_large_image', // or 'summary', 'app', 'player'
site: '@mywebsite',
creator: '@johndoe',
title: 'Product Name',
description: 'Product description',
images: ['https://example.com/twitter-image.jpg'],
},
};
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const post = await getPost(params.slug);
return {
openGraph: {
type: 'article',
url: `https://example.com/blog/${params.slug}`,
title: post.title,
description: post.excerpt,
publishedTime: post.publishedAt,
modifiedTime: post.updatedAt,
authors: [post.author.name],
section: post.category,
tags: post.tags,
images: [
{
url: post.coverImage,
width: 1200,
height: 630,
},
],
},
};
}
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
const organizationSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'My Company',
url: 'https://example.com',
logo: 'https://example.com/logo.png',
sameAs: [
'https://twitter.com/mycompany',
'https://facebook.com/mycompany',
'https://linkedin.com/company/mycompany',
],
contactPoint: {
'@type': 'ContactPoint',
telephone: '+1-555-1234',
contactType: 'Customer Service',
email: 'support@example.com',
},
};
return (
<html>
<head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema) }}
/>
</head>
<body>{children}</body>
</html>
);
}
// app/blog/[slug]/page.tsx
export default async function BlogPostPage({ params }: Props) {
const post = await getPost(params.slug);
const articleSchema = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
description: post.excerpt,
image: post.coverImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: {
'@type': 'Person',
name: post.author.name,
url: post.author.url,
},
publisher: {
'@type': 'Organization',
name: 'My Website',
logo: {
'@type': 'ImageObject',
url: 'https://example.com/logo.png',
},
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': `https://example.com/blog/${params.slug}`,
},
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema) }}
/>
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
</>
);
}
// app/products/[id]/page.tsx
export default async function ProductPage({ params }: Props) {
const product = await getProduct(params.id);
const productSchema = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
description: product.description,
image: product.images,
sku: product.sku,
brand: {
'@type': 'Brand',
name: product.brand,
},
offers: {
'@type': 'Offer',
url: `https://example.com/products/${params.id}`,
priceCurrency: 'USD',
price: product.price,
availability: product.inStock
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
priceValidUntil: '2025-12-31',
},
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: product.rating,
reviewCount: product.reviewCount,
},
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(productSchema) }}
/>
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
</div>
</>
);
}
// app/blog/[category]/[slug]/page.tsx
const breadcrumbSchema = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: [
{
'@type': 'ListItem',
position: 1,
name: 'Home',
item: 'https://example.com',
},
{
'@type': 'ListItem',
position: 2,
name: 'Blog',
item: 'https://example.com/blog',
},
{
'@type': 'ListItem',
position: 3,
name: category,
item: `https://example.com/blog/${category}`,
},
{
'@type': 'ListItem',
position: 4,
name: post.title,
item: `https://example.com/blog/${category}/${slug}`,
},
],
};
// app/sitemap.ts
import { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://example.com',
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
{
url: 'https://example.com/about',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: 'https://example.com/blog',
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.9,
},
];
}
// app/sitemap.ts
import { MetadataRoute } from 'next';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
// Fetch dynamic content
const posts = await getPosts();
const products = await getProducts();
const postUrls = posts.map((post) => ({
url: `https://example.com/blog/${post.slug}`,
lastModified: post.updatedAt,
changeFrequency: 'weekly' as const,
priority: 0.7,
}));
const productUrls = products.map((product) => ({
url: `https://example.com/products/${product.id}`,
lastModified: product.updatedAt,
changeFrequency: 'daily' as const,
priority: 0.8,
}));
return [
{
url: 'https://example.com',
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
...postUrls,
...productUrls,
];
}
// app/sitemap.ts (index sitemap)
import { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://example.com/sitemap/posts.xml',
},
{
url: 'https://example.com/sitemap/products.xml',
},
];
}
// app/sitemap/posts/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getPosts();
return posts.map((post) => ({
url: `https://example.com/blog/${post.slug}`,
lastModified: post.updatedAt,
}));
}
// app/robots.ts
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: ['/api/', '/admin/', '/private/'],
},
sitemap: 'https://example.com/sitemap.xml',
};
}
// app/robots.ts
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
const isProduction = process.env.NODE_ENV === 'production';
return {
rules: {
userAgent: '*',
allow: isProduction ? '/' : [],
disallow: isProduction ? ['/api/', '/admin/'] : ['/'],
},
sitemap: isProduction ? 'https://example.com/sitemap.xml' : undefined,
};
}
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
export async function generateMetadata({ params }: Props): Promise<Metadata> {
return {
alternates: {
canonical: `https://example.com/blog/${params.slug}`,
},
};
}
// If content exists at multiple URLs, point to primary
export const metadata: Metadata = {
alternates: {
canonical: 'https://example.com/primary-url',
},
};
✅ Good:
https://example.com/blog/how-to-optimize-images
https://example.com/products/laptops/macbook-pro-2024
❌ Bad:
https://example.com/blog?id=12345
https://example.com/p/1a2b3c
Guidelines:
[ ] Title (50-60 characters)
[ ] Description (150-160 characters)
[ ] Open Graph tags (og:title, og:description, og:image)
[ ] Twitter Card tags
[ ] Canonical URL
[ ] Robots meta tag
[ ] Structured data (JSON-LD)
[ ] Sitemap.xml
[ ] Robots.txt
[ ] Alt text for images
[ ] Heading hierarchy (H1 → H6)
export const metadata: Metadata = {
title: 'Page Title',
description: 'Page description',
openGraph: {
title: 'Page Title',
description: 'Page description',
images: ['/og-image.jpg'],
},
twitter: {
card: 'summary_large_image',
title: 'Page Title',
description: 'Page description',
images: ['/twitter-image.jpg'],
},
alternates: {
canonical: 'https://example.com/page',
},
};
Organization - Company info
Article - Blog posts
Product - E-commerce products
BreadcrumbList - Navigation breadcrumbs
FAQPage - FAQ pages
LocalBusiness - Local business info
Recipe - Recipe content
Review - Product/service reviews
Event - Event listings
VideoObject - Video content
Google Tools:
Third-party Tools:
❌ Missing title/description: Search engines generate own (poor quality) ✅ Always provide custom metadata
❌ Duplicate content: Multiple URLs with same content ✅ Use canonical URLs
❌ Blocking crawlers: robots.txt blocks important pages ✅ Only block admin/API routes
❌ Missing structured data: Reduced search visibility ✅ Implement JSON-LD for content types
❌ Poor URL structure: Non-descriptive, parameter-heavy URLs ✅ Use clean, keyword-rich URLs
This skill includes comprehensive Level 3 resources in skills/frontend/nextjs-seo/resources/:
REFERENCE.md (~1000 lines): Comprehensive reference guide covering:
Located in resources/scripts/:
check_seo.py - SEO tag validation tool
./check_seo.py <url> [--json] [--output file.json]generate_sitemap.py - Next.js sitemap generator
./generate_sitemap.py [--app-dir ./app] [--base-url https://example.com] [--output public/sitemap.xml]test_metadata.js - Metadata validation utility
./test_metadata.js <path-to-page> [--json] [--params id=123]Located in resources/examples/typescript/:
app-router-metadata.tsx - Complete metadata examples
dynamic-og-images.tsx - Dynamic OG image generation
structured-data.ts - JSON-LD schema examples
sitemap.ts - Sitemap generation patterns
robots.ts - robots.txt patterns
All scripts are executable with --help flags and support --json output for automation.
nextjs-app-router.md - Metadata API, generateMetadatafrontend-performance.md - Core Web Vitals (affects SEO)web-accessibility.md - Semantic HTML, alt textLast Updated: 2025-10-27 Format Version: 1.0 (Atomic)
Index of Build Systems Skills
Coordination patterns for distributed dataflow systems including barriers, epochs, and distributed snapshots
Windowing, sessionization, time-series aggregation, and late data handling for streaming systems
Comprehensive guide to GNU Debugger (GDB) for debugging C/C++/Rust programs. Covers breakpoints, stack traces, variable inspection, TUI mode, .gdbinit customization, Python scripting, remote debugging, and core file analysis.
Paxos consensus algorithm including Basic Paxos, Multi-Paxos, roles, phases, and practical implementations
Gossip protocols for disseminating information, failure detection, and eventual consistency in large-scale distributed systems