Package Exports
- @rwcode/seo
Readme
RealSEO
Simple all-in-one SEO toolkit for React and Next.js.
With one package you get:
- SEO component for head tags
- SEO analyzer with score and checks
- Terminal preview like Yoast (Google snippet style)
Install
npm install @rwcode/seoWhat You Can Do
- Add SEO tags to your page with one component.
- Get a SEO score in dev mode.
- Run CLI on a page file or URL and see preview + issues.
Changes in 0.1.1
- Build: switched to React automatic JSX runtime to avoid requiring a global
Reactin server environments (fixes ReferenceError in Next.js App Router / RSC). - Feature: added
toMetadata()helper for App Router consumers to produce Next.jsmetadataobjects without rendering a React component. - Compatibility:
SEOcomponent remains for pages/client use but is safe toimporton the server (won't throw during SSR). PrefertoMetadata()with App Router.
Quick Start (Pages Router)
import RealSEO from "@rwcode/seo";
const { SEO, SEODebugPanel, analyzeSEO } = RealSEO;
const seoProps = {
title: "Home - My Awesome Site",
description:
"We help developers ship faster with tools that feel great to use. Built for modern web teams.",
canonical: "https://mysite.com",
openGraph: {
title: "My Awesome Site",
description: "Fast tools for modern web teams.",
image: "https://mysite.com/og-image.png",
url: "https://mysite.com",
type: "website",
siteName: "My Awesome Site",
},
twitter: {
card: "summary_large_image",
site: "@mysite",
creator: "@mysite",
},
structuredData: {
"@context": "https://schema.org",
"@type": "WebSite",
name: "My Awesome Site",
url: "https://mysite.com",
},
};
export default function HomePage() {
const result = analyzeSEO(seoProps);
return (
<>
<SEO {...seoProps} />
<SEODebugPanel result={result} />
<main>
<h1>Welcome</h1>
</main>
</>
);
}Quick Start (App Router)
import RealSEO from "@rwcode/seo";
const { SEO, SEODebugPanel, analyzeSEO } = RealSEO;
const seoProps = {
title: "Home - My Awesome Site",
description:
"We help developers ship faster with tools that feel great to use. Built for modern web teams.",
canonical: "https://mysite.com",
openGraph: {
title: "My Awesome Site",
image: "https://mysite.com/og-image.png",
siteName: "My Awesome Site",
},
twitter: { card: "summary_large_image", site: "@mysite" },
};
export default function HomePage() {
const result = analyzeSEO(seoProps);
return (
<>
<SEO {...seoProps} />
<SEODebugPanel result={result} />
<main>
<h1>Welcome</h1>
</main>
</>
);
}CLI Usage (Current)
The CLI has 2 modes.
1) File mode (default)
Analyze SEO from page source or JSON config:
npx realseo ./src/app/page.jsx
npx realseo ./pages/index.jsx
npx realseo ./seo.config.jsonSupported input extensions:
- .js
- .jsx
- .ts
- .tsx
- .json
2) URL mode
Analyze rendered HTML from a URL:
npx realseo --url http://localhost:3000CLI Extraction Rules
File mode extracts SEO from:
- SEO spread props, example:
<SEO {...seoProps} /> - SEO inline props, example:
<SEO title="..." description="..." /> - App Router metadata, example:
export const metadata = { ... } - first JSON-LD script block if present
URL mode extracts SEO from rendered HTML:
- title
- meta description
- canonical link
- robots (noindex, nofollow)
- Open Graph tags
- Twitter tags
- first JSON-LD script block
Fast Error Handling
CLI now fails fast for invalid inputs:
- unsupported extension (example: .md)
- invalid JSON
- very large JSON files over 256KB
- JSON files that do not look like SEO config
- invalid URL or unsupported protocol
SEO Component API
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | empty | Page title |
| description | string | empty | Meta description |
| canonical | string | empty | Canonical URL |
| noIndex | boolean | false | Adds noindex to robots |
| noFollow | boolean | false | Adds nofollow to robots |
| titleTemplate | string | empty | Replaces %s with title |
| openGraph | object | {} | Open Graph tags |
| object | {} | Twitter tags | |
| structuredData | object | null | JSON-LD script |
| additionalMetaTags | array | [] | Extra meta tags |
openGraph fields
- title
- description
- image
- url
- type
- siteName
twitter fields
- card
- site
- creator
- title
- description
- image
SEO Checks (analyzeSEO)
| # | Check ID | Severity | Fails when |
|---|---|---|---|
| 1 | title-exists | error | title is missing |
| 2 | title-length | warning | title length is not 40 to 60 |
| 3 | description-exists | error | description is missing |
| 4 | description-length | warning | description length is not 120 to 158 |
| 5 | canonical-set | info | canonical is missing |
| 6 | og-image | warning | openGraph.image is missing |
| 7 | og-title | info | openGraph.title is missing |
| 8 | twitter-card | info | twitter.card is invalid or missing |
| 9 | structured-data | info | structuredData is missing or empty |
| 10 | no-index-warning | warning | noIndex is true |
Scoring
- starts at 100
- failed error: minus 20
- failed warning: minus 10
- failed info: minus 3
- minimum score is 0
Example seo.config.json
{
"title": "My Awesome Next.js Site",
"description": "We help developers ship faster with tools that feel great to use. Built for modern web teams.",
"canonical": "https://example.com",
"noIndex": false,
"noFollow": false,
"openGraph": {
"title": "My Awesome Next.js Site",
"description": "Fast tools for modern web teams.",
"image": "https://example.com/og-image.png",
"url": "https://example.com",
"type": "website",
"siteName": "My Awesome Site"
},
"twitter": {
"card": "summary_large_image",
"site": "@mysite",
"creator": "@author",
"title": "My Awesome Next.js Site",
"description": "Fast tools for modern web teams.",
"image": "https://example.com/twitter-image.png"
},
"structuredData": {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "My Awesome Next.js Site",
"url": "https://example.com"
}
}Dev Commands
npm run build
npm run devRequirements
- Node.js 18+
- React 18+
- Next.js 13+
License
MIT