seo-meta-tags

Original🇺🇸 English
Translated

Comprehensive SEO and social metadata implementation for HTML, Next.js App Router, and Vite (React & Vue) projects. Use when: (1) Creating, editing, or reviewing meta tags, Open Graph, Twitter Cards, canonical/hreflang links, JSON-LD structured data, theme-color, or favicon/manifest config; (2) Working with html/index.html, nextjs/metadata.ts, nextjs/dynamic-metadata-example.tsx, vite/index.html, vite/SEO.tsx, or vite/SEO.vue; (3) Adding SEO to a new page or route; (4) Migrating from react-helmet, vue-meta, or next-seo; (5) Generating dynamic metadata for content-driven pages; (6) Auditing metadata for completeness or best-practice compliance.

1installs
Added on

NPX Install

npx skill4agent add jeremy0x/meta-tag-boilerplate seo-meta-tags

SEO Meta Tags

Boilerplate and component library for production-ready metadata across three framework targets.

Decision Tree

Determine the correct framework path first:
  1. Static HTML site or any-backend project — Read references/html.md
  2. Next.js 13+ App Router — Read references/nextjs.md
  3. Vite + React — Read references/vite.md, React section
  4. Vite + Vue 3 — Read references/vite.md, Vue section
  5. Multiple frameworks at once — Read all relevant reference files
Then determine action type:
  • Creating metadata from scratch? — Read matching reference → copy boilerplate → replace placeholders.
  • Updating existing metadata? — Load file → keep structure → change requested values → verify parity across tag families.
  • Auditing / reviewing metadata? — Run through Quality Gate below → report issues.
  • Migrating between frameworks? — Read source reference → read target reference → map fields.

Framework Selection

FrameworkWhen to useReference
HTMLStatic sites, any backend, SSGsreferences/html.md
Next.jsNext.js 13+ App Router projectsreferences/nextjs.md
ViteVite + React or Vite + Vue appsreferences/vite.md
Read only the reference file that matches the user's target framework.

Metadata Families

Every framework target must keep parity across these families. When modifying one family, verify the others remain consistent.

1. Essential / Primary

TagConstraint
<title>
/
title
Under 60 characters
description
150-160 characters
keywords
5-10 terms max, comma-separated
author
Full name
robots
index, follow
by default; include
max-image-preview:large
,
max-snippet:-1
,
max-video-preview:-1
canonical
Absolute URL, must match deployment URL
viewport
width=device-width, initial-scale=1.0

2. Open Graph (
og:*
)

PropertyNotes
og:type
website
for home/landing;
article
for blog posts;
product
for e-commerce
og:url
Absolute URL
og:title
Can differ from
<title>
for social context
og:description
Can differ from meta description
og:image
Absolute URL, 1200x630px, JPG or PNG, under 1 MB
og:image:width
/
og:image:height
1200
/
630
og:image:alt
Required when image is present
og:site_name
Brand name
og:locale
e.g.
en_US
For
article
type also include:
article:published_time
,
article:modified_time
,
article:author
,
article:tag
.

3. Twitter Cards (
twitter:*
)

PropertyNotes
twitter:card
summary_large_image
(default) or
summary
twitter:site
Organization handle with
@
prefix
twitter:creator
Author handle with
@
prefix
twitter:title
Under 70 characters
twitter:description
Under 200 characters
twitter:image
Same spec as OG image
twitter:image:alt
Required when image is present

4. Theme Color

Provide three values:
  • Default:
    <meta name="theme-color" content="...">
    or single value
  • Light:
    media="(prefers-color-scheme: light)"
  • Dark:
    media="(prefers-color-scheme: dark)"
Next.js uses the
themeColor
array in the Metadata object.

5. Icons and Manifest

AssetSizeFormat
favicon.ico
32x32 or multi-sizeICO
icon-16x16.png
16x16PNG
icon-32x32.png
32x32PNG
apple-touch-icon.png
180x180PNG
site.webmanifest
n/aJSON

6. Structured Data (JSON-LD)

Emit a
<script type="application/ld+json">
block (HTML/Vite) or use a separate Script component in Next.js. Required keys:
json
{
	"@context": "https://schema.org",
	"@type": "WebSite",
	"name": "",
	"description": "",
	"url": "",
	"image": { "@type": "ImageObject", "url": "", "width": 1200, "height": 630 },
	"author": { "@type": "Person", "name": "" },
	"publisher": {
		"@type": "Organization",
		"name": "",
		"logo": { "@type": "ImageObject", "url": "" }
	}
}
Common
@type
values:
WebSite
,
Article
,
Organization
,
Product
,
FAQPage
,
BreadcrumbList
.

7. Internationalization (hreflang)

html
<link rel="alternate" hreflang="en" href="https://example.com/en/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
Next.js equivalent:
alternates.languages
in the Metadata object.

8. Performance Hints

Include when external resources are used:
html
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="dns-prefetch" href="https://www.google-analytics.com" />

Placeholder Tokens

All boilerplate files use
{{PLACEHOLDER_NAME}}
tokens. Common tokens:
TokenPurpose
{{PAGE_TITLE}}
Page
<title>
{{PAGE_DESCRIPTION}}
Meta description
{{PAGE_URL}}
Page URL (absolute)
{{CANONICAL_URL}}
Canonical URL
{{KEYWORDS}}
Comma-separated keywords
{{AUTHOR_NAME}}
Content author
{{SITE_NAME}}
Brand / site name
{{THEME_COLOR}}
/
{{THEME_COLOR_LIGHT}}
/
{{THEME_COLOR_DARK}}
Hex color codes
{{OG_TITLE}}
/
{{OG_DESCRIPTION}}
/
{{OG_IMAGE_URL}}
/
{{OG_IMAGE_ALT}}
Open Graph
{{TWITTER_TITLE}}
/
{{TWITTER_DESCRIPTION}}
/
{{TWITTER_IMAGE_URL}}
/
{{TWITTER_IMAGE_ALT}}
Twitter
{{TWITTER_HANDLE}}
/
{{TWITTER_CREATOR_HANDLE}}
Twitter handles
{{SCHEMA_TYPE}}
/
{{SCHEMA_IMAGE_URL}}
JSON-LD
{{PUBLISHER_NAME}}
/
{{PUBLISHER_LOGO_URL}}
Publisher org
{{FAVICON_32x32_URL}}
/
{{FAVICON_16x16_URL}}
/
{{APPLE_TOUCH_ICON_URL}}
Icons
{{AUTHOR_URL}}
Author website URL (Next.js)
{{CREATOR_NAME}}
Content creator name (Next.js)
{{CATEGORY}}
Site category (Next.js)
{{GOOGLE_VERIFICATION_CODE}}
/
{{YANDEX_VERIFICATION_CODE}}
/
{{FACEBOOK_VERIFICATION_CODE}}
Search engine verification codes (Next.js)
{{EN_URL}}
/
{{ES_URL}}
Language-specific alternate URLs (Next.js)
{{ALTERNATE_EN_URL}}
/
{{ALTERNATE_DEFAULT_URL}}
hreflang alternate URLs (HTML/Vite)
When implementing for a user, replace every
{{...}}
token. Never leave placeholders in production output.

Quality Gate

Run these checks before considering any metadata task complete:
  1. No placeholders — grep for
    {{
    in all modified files; count must be zero.
  2. Absolute URLs — canonical, OG url, OG image, Twitter image, JSON-LD url/image must start with
    https://
    .
  3. Image alt text — every
    og:image
    /
    twitter:image
    must have a corresponding alt field.
  4. No duplicate tags — no two conflicting
    <title>
    ,
    description
    , or
    canonical
    tags in the same scope.
  5. Title length — verify under 60 characters.
  6. Description length — verify 150-160 characters.
  7. JSON-LD validity — valid JSON with required
    @context
    and
    @type
    keys.
  8. OG/Twitter parity — if OG title is set, Twitter title should also be set (and vice versa).
  9. Canonical consistency — canonical URL matches the actual page URL or intended redirect target.
  10. Theme color — includes both light and dark media variants.
  11. hreflang — includes
    x-default
    when language alternates exist.
  12. Robots — allows indexing unless user explicitly requests noindex.

Image Specifications

Use caseDimensionsRatioFormatMax size
OG / Twitter1200x6301.91:1JPG or PNG1 MB
Favicon 3232x321:1PNGn/a
Favicon 1616x161:1PNGn/a
Apple Touch180x1801:1PNGn/a

Testing Tools

Recommend to users after deployment:

Common Mistakes

MistakeImpactFix
Relative URLs in
og:image
or
twitter:image
Social platforms can't fetch the imageAlways use absolute URLs starting with
https://
Missing
<HelmetProvider>
in Vite React
All
<SEO>
tags silently fail to render
Wrap app root in
<HelmetProvider>
in
main.tsx
Missing
createHead()
in Vite Vue
useHead()
throws at runtime
Call
app.use(createHead())
in
main.ts
Committing verification codes to public reposExposes site ownership tokensUse environment variables for
verification
values
Duplicate
<title>
or
description
tags
Crawlers pick an unpredictable oneUse only one source of truth per scope (layout vs. page)
og:image
set without
og:image:alt
Accessibility failure, some validators warnAlways pair image with alt text
Using
generateMetadata
for static pages
Unnecessary async overhead on every requestUse static
export const metadata
when values are known at build time
Leaving
{{...}}
placeholder tokens
Broken display on social platforms, poor SEOGrep for
{{
before shipping
JSON-LD with trailing commas or commentsInvalid JSON, structured data ignoredValidate JSON before finishing
twitter:card
set to
summary
when image is 1200x630
Image gets cropped to tiny squareUse
summary_large_image
for landscape images

Migration Paths

FromToNotes
react-helmet
Vite React (
SEO.tsx
)
Replace with
react-helmet-async
; wrap root in
<HelmetProvider>
vue-meta
Vite Vue (
SEO.vue
)
Replace
metaInfo
with
@unhead/vue
useHead()
composable
next-seo
Next.js (
metadata.ts
)
Remove
<NextSeo>
; use exported
metadata
or
generateMetadata
Pages Router
<Head>
App RouterReplace
import Head
with
export const metadata