SuperAPI AI Directory

seo-metadata

Frontend & websites

View repository

Updated 10-15 23:58

About this skill

Complete Guide to SEO Metadata

1. Metadata Structure

What every page must do

// 每个 page.tsx 顶部
import type { Metadata } from 'next'
import { getSiteConfig } from '@/lib/site'
import { generateSiteMetadata } from '@/lib/seo'   // 来自共享包

const site = getSiteConfig()

export const metadata: Metadata = generateSiteMetadata(site, { pageTitle: 'Page Title — Brand Name (2026)', pageDescription: 'Description text 150-155 characters, containing the target keyword.', canonicalPath: '/page-path', robots: { index: true, follow: true }, // Append keywords (not required, but helps with long-tail) keywords: [...(site.keywords || []), 'Additional long-tail keyword 1', 'Additional long-tail keyword 2'], })


### Metadata 规则

| 项 | 规则 |
|---|---|
| **pageTitle** | 含品牌名 `MECCHA CHAMELEON`,不拼错。格式:`主题 — 子主题` (em dash,前后空格) |
| **pageDescription** | **150-155 字符**。一段完整的描述,含 2-3 个目标关键词。不要截断、不要清单 |
| **canonicalPath** | 必填。从 `/` 开始,如 `/platforms`。空字符串 `''` 表示首页 |
| **robots** | 内容页 `{ index: true, follow: true }`,法律页 `{ index: false, follow: false }` |
| **keywords** | 只在 `/platforms`、`/buy`、`/requirements` 等需要大量长尾词覆盖的页面追加 |

### 首页(根 page.tsx)

首页也需要单独的 `metadata` 导出——不要只依赖 layout.tsx 默认值。

```tsx
import { generateSiteMetadata } from '@/lib/seo'

const site = getSiteConfig()

export const metadata: Metadata = generateSiteMetadata(site, {
  pageTitle: 'Paint Yourself Invisible | Hide-and-Seek Party Game (2026)',
  pageDescription: 'MECCHA CHAMELEON is a creative hide-and-seek party game on Steam (PC). Paint to blend in. $5.99, Very Positive, 2-10 players. Tips, requirements, and guide.',
  canonicalPath: '',
  robots: { index: true, follow: true },
})

Legal pages (privacy, tos, disclaimer)

Must use generateSiteMetadata, do not hand-write a raw Metadata object. Otherwise it will be missing the canonical URL, OG, and Twitter Card.

import { getSiteConfig } from '@/lib/site'
import { generateSiteMetadata } from '@/lib/seo'

const site = getSiteConfig()

export const metadata: Metadata = generateSiteMetadata(site, {
  pageTitle: 'Privacy Policy',
  pageDescription: 'Privacy policy for MECCHA CHAMELEON guide. Data collection, cookies, and your rights.',
  canonicalPath: '/privacy',
  robots: { index: false, follow: false },
})

layout.tsx root configuration

export const metadata: Metadata = generateSiteMetadata(site, {
  pageTitle: 'Paint Yourself Invisible | Hide-and-Seek Party Game (2026)',
})

2. Title & Description Quality Check

Title Format

✅ MECCHA CHAMELEON Platforms — PS5, Mac, Mobile & PC Support (2026)
❌ MECCA CHAMELEON Platforms —PS5, Mac, Mobile & PC Support (2026)
❌ MECCHA CHAMELEON Platforms —PS5...   // em dash 后缺空格

Rules:

  • Brand name spelled correctly (MECCHA not MECCA)
  • em dash(—) with one space before and after
  • Append (2026) year
  • Length 50-65 characters

Description Length

Status Character count
✅ Ideal 150-155
⚠️ Acceptable 145-160
❌ Too long >165 (Google will truncate)
❌ Too short <100 (wastes exposure opportunity)

Trimming techniques:

原本: "MECCHA CHAMELEON tips and tricks —best camouflage techniques ranked S to B, Seeker search strategies, common beginner mistakes, and how to find hidden players. Master both roles with pro strategies."  (168 chars)
裁剪: "MECCHA CHAMELEON tips and tricks — ranked camouflage techniques S to B, Seeker strategies, beginner mistakes, and how to find hidden players. Master both roles."  (152 chars)

Key: delete redundant adverbs, merge similar items, remove unnecessary modifiers.

3. JSON-LD Structured Data

Page -> Schema Mapping Table

Page type JSON-LD Schema Required fields
Homepage VideoGame + WebSite aggregateRating, offers, operatingSystem
Reviews Review + VideoGame reviewRating, itemReviewed, aggregateRating
FAQ FAQPage(multiple Question/Answer entries) At least 5 Q&A pairs
Buying guide Product + Offer offers.price, offers.availability
Platform/need/mode VideoGame aggregateRating, offers, operatingSystem
All content pages BreadcrumbList via generateBreadcrumbJsonLd auto-generated

VideoGame JSON-LD Complete Version

Don't only write name + url + description。aggregateRating and offers are the most important—they trigger star ratings and price tags in search results.

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify({
      '@context': 'https://schema.org',
      '@type': 'VideoGame',
      name: data.name,
      url: 'https://meccha-chameleon.info/classes',
      description: '页面描述',
      operatingSystem: 'Windows 10/11 64-bit',
      applicationCategory: 'GameApplication',
      aggregateRating: {
        '@type': 'AggregateRating',
        ratingValue: data.rating,        // 4.3
        bestRating: data.ratingMax,       // 5
        ratingCount: data.ratingCount,    // 16348
      },
      offers: {
        '@type': 'Offer',
        price: '5.99',
        priceCurrency: 'USD',
        availability: 'https://schema.org/InStock',
        url: data.steamUrl,
      },
    }),
  }}
/>

FAQPage JSON-LD

Content pages are accordion <details>, JSON-LD needsall Q&A pairs:

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify({
      '@context': 'https://schema.org',
      '@type': 'FAQPage',
      mainEntity: data.faqs.map((faq) => ({
        '@type': 'Question',
        name: faq.q,
        acceptedAnswer: {
          '@type': 'Answer',
          text: faq.a,    // 纯文本,不要含 HTML 标签
        },
      })),
    }),
  }}
/>

Note: acceptedAnswer.text do not include <a> tags or HTML. Schema parsers prefer plain text.

4. Sitemap & Robots

sitemap.ts

export default function sitemap(): MetadataRoute.Sitemap {
  const site = getSiteConfig()
  const baseUrl = `https://${site.domain}`

  const mainPages = ['', '/guide', '/review', '/faq', '/classes', '/tier', '/items', '/platforms', '/buy', '/requirements']
  const legalPages = ['/privacy', '/tos', '/disclaimer']

  const entries: MetadataRoute.Sitemap = [
    ...mainPages.map(path => ({
      url: `${baseUrl}${path}`,
      changeFrequency: (path === '' ? 'weekly' : 'monthly') as 'weekly' | 'monthly',
      priority: path === '' ? 1.0 : 0.8,
    })),
    ...legalPages.map(path => ({
      url: `${baseUrl}${path}`,
      changeFrequency: 'monthly' as const,
      priority: 0.3,
    })),
  ]

  return entries
}

Principles:

  • Homepage priority 1.0, content pages 0.8, legal pages 0.3
  • /jump(redirect intermediate pages) are not added to the sitemap
  • When adding new pages, update in sync mainPages array

robots.ts

export default function robots(): MetadataRoute.Robots {
  const site = getSiteConfig()
  return {
    rules: {
      userAgent: '*',
      allow: '/',
      disallow: ['/jump', '/api/'],
    },
    sitemap: `https://${site.domain}/sitemap.xml`,
  }
}

5. Internal Link Network

Link Density Requirements

Page type Minimum number of outbound links (pointing to other pages within the site)
Homepage At least 5
Guide-type pages At least 3 (pointing to other guide pages)
Buying/platform/need pages At least 3
FAQ At least 6 (covering all content pages)
Legal pages 1-2 is enough

Guide page cross-linking pattern

Each guide page (guide/classes/items/tier) adds a navigation bar before the bottom CTA:

<section className="section" style={{ padding: '2rem 0' }}>
  <div className="container">
    <div style={{ maxWidth: '800px', margin: '0 auto' }} className="reveal">
      <p style={{ textAlign: 'center' }}>
        <strong>Related guides:</strong>{' '}
        <a href="/guide">Beginner's Guide</a> —
        <a href="/classes">Game Modes</a> —
        <a href="/items">Camouflage Guide</a>
      </p>
    </div>
  </div>
</section>

FAQ internal links

In the FAQ's a answer text, embed links pointing to the corresponding detailed pages:

"MECCHA CHAMELEON is currently available exclusively on PC via Steam. See our <a href="/platforms">Platform Availability Guide</a> for full breakdown."

Six, Keyword-driven page planning

Find content gaps from search data

From CSV exported from Google Search Console / keyword tools, extract:

  1. High search volume + 0 coverage → need to create new pages
  2. High growth (↑%) + low coverage → need to strengthen existing pages

Example priority matrix:

Keyword Search volume Growth Action
ps5, mac, mobile 20+ 20%+ Create /platforms
steam key 5+ 30%+ Create /buy
cloud save error 1+ 160%+ Strengthen /requirements
tips, how to play Consistent Stable Already covered ✅

Seven, Low-priority but worthwhile tasks

Item Description
OG image Each page uses a separate OG image (at least a different title overlay). Currently there is only one capsule.jpg
favicon At least favicon.svg + apple-touch-icon.png. Consider the PWA's icon-192x192.png
Number of fonts At most 3 Google Font families. More than 5 affects LCP
hreflang If multiple languages are supported, in alternates add hreflang tags
WebP/AVIF Use WebP format for images instead of JPEG to reduce transfer size