seo-2025-patterns

Purpose: Implement 2025 SEO best practices for Next.js applications to maximize search visibility and organic traffic.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "seo-2025-patterns" with this command: npx skills add vanman2024/ai-dev-marketplace/vanman2024-ai-dev-marketplace-seo-2025-patterns

SEO 2025 Patterns

Purpose: Implement 2025 SEO best practices for Next.js applications to maximize search visibility and organic traffic.

Activation Triggers:

  • Optimizing pages for search engines

  • Implementing metadata and Open Graph

  • Adding Schema.org structured data

  • Improving Core Web Vitals

  • E-E-A-T signal implementation

  • Sitemap and robots.txt setup

  • Meta description optimization

Key Resources:

  • scripts/seo-audit.sh

  • Comprehensive SEO audit script

  • scripts/validate-schema.sh

  • Validate JSON-LD structured data

  • templates/metadata-patterns.tsx

  • Next.js Metadata API patterns

  • templates/schema-components.tsx

  • JSON-LD schema components

  • examples/complete-seo-setup.md

  • Full SEO implementation example

2025 SEO Landscape

Key Changes from 2024

  • INP Replaces FID - Interaction to Next Paint is now a Core Web Vital

  • AI Content Guidelines - Google rewards helpful AI content with human oversight

  • E-E-A-T Enhanced - "Experience" added as first factor

  • Passage Ranking - Google indexes specific passages

  • Video SEO - Video snippets dominate SERPs

  • Zero-Click Optimization - Featured snippets and AI Overviews

Core Web Vitals Targets (2025)

Metric Target What It Measures

LCP < 2.5s Largest Contentful Paint

INP < 200ms Interaction to Next Paint

CLS < 0.1 Cumulative Layout Shift

Next.js Metadata API

Basic Metadata Configuration

// app/layout.tsx import type { Metadata } from 'next'

export const metadata: Metadata = { metadataBase: new URL('https://example.com'), title: { default: 'Site Name - Main Tagline', template: '%s | Site Name', }, description: 'Your site description for search engines (150-160 characters)', keywords: ['keyword1', 'keyword2', 'keyword3'], authors: [{ name: 'Author Name', url: 'https://author.com' }], creator: 'Creator Name', publisher: 'Publisher Name', formatDetection: { email: false, address: false, telephone: false, }, }

Open Graph Configuration

export const metadata: Metadata = { openGraph: { type: 'website', locale: 'en_US', url: 'https://example.com', siteName: 'Site Name', title: 'Page Title for Social Sharing', description: 'Description for social media (150-200 chars)', images: [ { url: '/og-image.png', width: 1200, height: 630, alt: 'OG Image Alt Text', }, ], }, }

Twitter Card Configuration

export const metadata: Metadata = { twitter: { card: 'summary_large_image', site: '@sitehandle', creator: '@creatorhandle', title: 'Title for Twitter', description: 'Description for Twitter (150-200 chars)', images: ['/twitter-image.png'], }, }

Robots Configuration

export const metadata: Metadata = { robots: { index: true, follow: true, nocache: false, googleBot: { index: true, follow: true, 'max-video-preview': -1, 'max-image-preview': 'large', 'max-snippet': -1, }, }, }

Dynamic Metadata

// app/blog/[slug]/page.tsx import type { Metadata, ResolvingMetadata } from 'next'

type Props = { params: { slug: string } }

export async function generateMetadata( { params }: Props, parent: ResolvingMetadata ): Promise<Metadata> { const post = await getPost(params.slug)

return { title: post.title, description: post.excerpt, openGraph: { title: post.title, description: post.excerpt, type: 'article', publishedTime: post.publishedAt, modifiedTime: post.updatedAt, authors: [post.author.name], images: [ { url: post.coverImage, width: 1200, height: 630, alt: post.title, }, ], }, } }

Dynamic Sitemap

// app/sitemap.ts import { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> { const baseUrl = 'https://example.com'

// Static pages const staticPages: MetadataRoute.Sitemap = [ { url: baseUrl, lastModified: new Date(), changeFrequency: 'weekly', priority: 1, }, { url: ${baseUrl}/about, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8, }, { url: ${baseUrl}/pricing, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.9, }, ]

// Dynamic pages from database const posts = await getAllPosts() const postPages: MetadataRoute.Sitemap = posts.map((post) => ({ url: ${baseUrl}/blog/${post.slug}, lastModified: new Date(post.updatedAt), changeFrequency: 'weekly' as const, priority: 0.6, }))

return [...staticPages, ...postPages] }

Robots.txt

// app/robots.ts import { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots { const baseUrl = 'https://example.com'

return { rules: [ { userAgent: '*', allow: '/', disallow: ['/api/', '/admin/', '/_next/', '/private/'], }, { userAgent: 'GPTBot', disallow: '/', // Block AI training crawlers if desired }, ], sitemap: ${baseUrl}/sitemap.xml, } }

Schema.org Structured Data

Organization Schema

// components/seo/OrganizationSchema.tsx export function OrganizationSchema() { const schema = { '@context': 'https://schema.org', '@type': 'Organization', name: 'Company Name', url: 'https://example.com', logo: 'https://example.com/logo.png', sameAs: [ 'https://twitter.com/company', 'https://linkedin.com/company/company', 'https://github.com/company', ], contactPoint: { '@type': 'ContactPoint', telephone: '+1-555-555-5555', contactType: 'customer service', availableLanguage: ['English'], }, }

return ( <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} /> ) }

Article Schema

// components/seo/ArticleSchema.tsx interface ArticleSchemaProps { title: string description: string image: string author: { name: string; url: string } publishedAt: string updatedAt: string url: string }

export function ArticleSchema(props: ArticleSchemaProps) { const schema = { '@context': 'https://schema.org', '@type': 'Article', headline: props.title, description: props.description, image: props.image, author: { '@type': 'Person', name: props.author.name, url: props.author.url, }, publisher: { '@type': 'Organization', name: 'Company Name', logo: { '@type': 'ImageObject', url: 'https://example.com/logo.png', }, }, datePublished: props.publishedAt, dateModified: props.updatedAt, mainEntityOfPage: { '@type': 'WebPage', '@id': props.url, }, }

return ( <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} /> ) }

FAQ Schema

// components/seo/FAQSchema.tsx interface FAQItem { question: string answer: string }

export function FAQSchema({ items }: { items: FAQItem[] }) { const schema = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: items.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer, }, })), }

return ( <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} /> ) }

Breadcrumb Schema

// components/seo/BreadcrumbSchema.tsx interface BreadcrumbItem { name: string url: string }

export function BreadcrumbSchema({ items }: { items: BreadcrumbItem[] }) { const schema = { '@context': 'https://schema.org', '@type': 'BreadcrumbList', itemListElement: items.map((item, index) => ({ '@type': 'ListItem', position: index + 1, name: item.name, item: item.url, })), }

return ( <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} /> ) }

Core Web Vitals Optimization

LCP Optimization

// Prioritize above-fold images import Image from 'next/image'

// Hero image with priority <Image src="/hero.jpg" alt="Hero description" width={1200} height={600} priority // Preloads image for LCP sizes="(max-width: 768px) 100vw, 1200px" />

Font Optimization

// app/layout.tsx import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'], display: 'swap', // Prevents CLS preload: true, variable: '--font-inter', })

export default function RootLayout({ children }) { return ( <html lang="en" className={inter.variable}> <body>{children}</body> </html> ) }

Script Optimization

import Script from 'next/script'

// Defer non-critical scripts <Script src="https://analytics.example.com/script.js" strategy="lazyOnload" // Load after page is interactive />

// Load immediately for critical scripts <Script src="https://critical.example.com/script.js" strategy="afterInteractive" />

E-E-A-T Signals

Author Information

// components/AuthorBio.tsx export function AuthorBio({ author }) { return ( <div className="flex items-center gap-4 p-4 bg-muted rounded-lg"> <Image src={author.avatar} alt={author.name} width={64} height={64} className="rounded-full" /> <div> <h3 className="font-semibold">{author.name}</h3> <p className="text-sm text-muted-foreground">{author.title}</p> <p className="text-sm">{author.bio}</p> <div className="flex gap-2 mt-2"> <a href={author.twitter}>Twitter</a> <a href={author.linkedin}>LinkedIn</a> </div> </div> </div> ) }

Trust Signals

  • Clear contact information

  • Privacy policy and terms of service

  • About page with company information

  • Author pages with credentials

  • Published and updated dates

  • HTTPS everywhere

SEO Audit Checklist

Run comprehensive SEO audit

./scripts/seo-audit.sh

Checks:

✓ All pages have unique titles

✓ All pages have meta descriptions

✓ Open Graph tags present

✓ Twitter cards configured

✓ Sitemap.xml exists and valid

✓ Robots.txt configured

✓ Schema markup valid

✓ Images have alt text

✓ Heading hierarchy correct

✓ Internal linking structure

Testing Tools

  • Google Search Console - Monitor indexing and search performance

  • PageSpeed Insights - Core Web Vitals measurement

  • Rich Results Test - Validate structured data

  • Mobile-Friendly Test - Mobile compatibility

  • Schema.org Validator - Validate JSON-LD

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

document-parsers

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

stt-integration

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

model-routing-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-email-templates

No summary provided by upstream source.

Repository SourceNeeds Review