diff --git a/.github/release-please-config.json b/.github/release-please-config.json index 5d174bd..6435c32 100644 --- a/.github/release-please-config.json +++ b/.github/release-please-config.json @@ -2,12 +2,14 @@ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", "release-type": "node", "include-v-in-tag": true, + "include-component-in-tag": false, "separate-pull-requests": false, "extra-files": [], "pull-request-title-pattern": "chore: release v${version}", "group-pull-request-title-pattern": "chore: release v${version}", "packages": { "packages/seox": { + "last-release-sha": "97a5701414e348486a8aeede9cf3e31948cdb7a0", "changelog-sections": [ { "type": "feat", "section": "Features" }, { "type": "fix", "section": "Bug Fixes" }, diff --git a/apps/docs/package.json b/apps/docs/package.json index 9b495d0..364751d 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -21,6 +21,7 @@ "next-themes": "^0.4.6", "react": "^19.2.3", "react-dom": "^19.2.3", + "seox": "workspace:*", "tailwind-merge": "^3.4.0" }, "devDependencies": { diff --git a/apps/docs/src/app/docs/[[...slug]]/page.tsx b/apps/docs/src/app/docs/[[...slug]]/page.tsx index 723b0a2..bb8271e 100644 --- a/apps/docs/src/app/docs/[[...slug]]/page.tsx +++ b/apps/docs/src/app/docs/[[...slug]]/page.tsx @@ -8,6 +8,7 @@ import { createRelativeLink } from "fumadocs-ui/mdx"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { LLMCopyButton, ViewOptions } from "@/components/ai/page-actions"; +import { seoConfig } from "@/lib/seo"; import { getPageImage, source } from "@/lib/source"; import { getMDXComponents } from "@/mdx-components"; @@ -60,11 +61,25 @@ export async function generateMetadata( const page = source.getPage(params.slug); if (!page) notFound(); - return { + const pageUrl = `https://docs.seo-x.dev${page.url}`; + + return seoConfig.generatePageMetadata({ title: page.data.title, description: page.data.description, + alternates: { + canonical: pageUrl, + }, openGraph: { + title: page.data.title, + description: page.data.description, + url: pageUrl, images: getPageImage(page).url, + type: "article", }, - }; + twitter: { + title: page.data.title, + description: page.data.description, + images: getPageImage(page).url, + }, + }); } diff --git a/apps/docs/src/app/layout.tsx b/apps/docs/src/app/layout.tsx index cd8c560..a376b56 100644 --- a/apps/docs/src/app/layout.tsx +++ b/apps/docs/src/app/layout.tsx @@ -1,14 +1,21 @@ import { RootProvider } from "fumadocs-ui/provider/next"; -import "./global.css"; import { Inter } from "next/font/google"; +import { JsonLd } from "seox/next"; +import { seoConfig } from "@/lib/seo"; +import "./global.css"; const inter = Inter({ subsets: ["latin"], }); +export const metadata = seoConfig.configToMetadata(); + export default function Layout({ children }: LayoutProps<"/">) { return ( + + + {children} diff --git a/apps/docs/src/lib/seo.ts b/apps/docs/src/lib/seo.ts new file mode 100644 index 0000000..4d7a118 --- /dev/null +++ b/apps/docs/src/lib/seo.ts @@ -0,0 +1,171 @@ +import { Seox } from "seox/next"; + +const SITE_URL = "https://docs.seo-x.dev"; +const MAIN_SITE_URL = "https://seo-x.dev"; + +export const seoConfig = new Seox({ + name: "SEOX Documentation", + url: SITE_URL, + metadataBase: new URL(SITE_URL), + title: { + default: "SEOX Docs - SEO Next.js Guide | Metadata, JSON-LD, Open Graph", + template: "%s | SEOX - SEO Next.js Docs", + }, + description: + "Complete SEO Next.js documentation for SEOX. Learn how to implement SEO in Next.js with type-safe metadata, JSON-LD structured data, Open Graph tags. The ultimate SEO guide for Next.js App Router.", + keywords: [ + "SEO Next.js", + "SEO Nextjs", + "Next.js SEO guide", + "Next.js SEO tutorial", + "Next.js metadata guide", + "Next.js JSON-LD", + "Next.js Open Graph", + "Next.js structured data", + "SEO Next.js App Router", + "SEOX documentation", + "Next.js SEO library docs", + "SEO TypeScript Next.js", + ], + creator: "Neysixx", + publisher: "Neysixx", + authors: [ + { + name: "Neysixx", + url: "https://github.com/neysixx", + }, + ], + alternates: { + canonical: SITE_URL, + }, + openGraph: { + type: "website", + locale: "en_US", + title: "SEOX Docs - SEO Next.js Guide", + description: + "Complete SEO Next.js documentation. Learn how to add SEO to Next.js with SEOX: type-safe metadata, JSON-LD, Open Graph for Next.js App Router.", + siteName: "SEOX - SEO Next.js", + }, + twitter: { + card: "summary_large_image", + creator: "@neysixx", + title: "SEOX Docs - SEO Next.js Guide", + description: + "Complete SEO Next.js documentation. Learn how to add SEO to Next.js with SEOX: type-safe metadata, JSON-LD, Open Graph for Next.js App Router.", + }, + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + "max-video-preview": -1, + "max-image-preview": "large", + "max-snippet": -1, + }, + }, + jsonld: [ + { + "@context": "https://schema.org", + "@type": "WebSite", + name: "SEOX Documentation - SEO Next.js Guide", + alternateName: [ + "SEOX Docs", + "SEO Next.js Documentation", + "Next.js SEO Guide", + ], + url: SITE_URL, + description: + "Complete SEO Next.js documentation. Learn how to implement SEO in Next.js with SEOX: type-safe metadata, JSON-LD, Open Graph for Next.js App Router.", + potentialAction: { + "@type": "SearchAction", + target: { + "@type": "EntryPoint", + urlTemplate: `${SITE_URL}/docs?q={search_term_string}`, + }, + "query-input": "required name=search_term_string", + }, + isPartOf: { + "@type": "WebSite", + name: "SEOX - SEO Next.js Library", + url: MAIN_SITE_URL, + }, + keywords: "SEO Next.js, Next.js SEO guide, SEO Nextjs tutorial", + }, + { + "@context": "https://schema.org", + "@type": "TechArticle", + headline: "SEO Next.js Guide - How to Add SEO to Next.js with SEOX", + alternativeHeadline: "Complete SEO Next.js Tutorial", + description: + "Learn how to implement SEO in Next.js applications with SEOX. This guide covers type-safe metadata, JSON-LD structured data, Open Graph tags, and best practices for Next.js App Router SEO.", + author: { + "@type": "Person", + name: "Neysixx", + url: "https://github.com/neysixx", + }, + publisher: { + "@type": "Organization", + name: "SEOX", + url: MAIN_SITE_URL, + }, + mainEntityOfPage: { + "@type": "WebPage", + "@id": SITE_URL, + }, + keywords: + "SEO Next.js, Next.js SEO, SEO Nextjs, Next.js metadata, Next.js JSON-LD", + about: { + "@type": "Thing", + name: "SEO for Next.js", + }, + }, + { + "@context": "https://schema.org", + "@type": "HowTo", + name: "How to Add SEO to Next.js", + description: + "Step-by-step guide to implement SEO in Next.js using SEOX library", + step: [ + { + "@type": "HowToStep", + name: "Install SEOX", + text: "Install the SEOX package with npm install seox or bun add seox", + }, + { + "@type": "HowToStep", + name: "Create SEO Config", + text: "Create a centralized SEO configuration file with your site metadata", + }, + { + "@type": "HowToStep", + name: "Add to Layout", + text: "Export metadata from your root layout using seoConfig.configToMetadata()", + }, + { + "@type": "HowToStep", + name: "Add JSON-LD", + text: "Add the JsonLd component to your layout for structured data", + }, + ], + }, + { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "SEOX - SEO Next.js", + item: MAIN_SITE_URL, + }, + { + "@type": "ListItem", + position: 2, + name: "SEO Next.js Documentation", + item: SITE_URL, + }, + ], + }, + ], +}); diff --git a/apps/landing/lib/seo.ts b/apps/landing/lib/seo.ts index a88e767..5bf83c1 100644 --- a/apps/landing/lib/seo.ts +++ b/apps/landing/lib/seo.ts @@ -1,26 +1,33 @@ import { Seox } from 'seox/next'; +const SITE_URL = 'https://seo-x.dev'; +const DOCS_URL = 'https://docs.seo-x.dev'; + export const seoConfig = new Seox({ name: 'SEOX', - url: 'https://seo-x.dev', - metadataBase: new URL('https://seo-x.dev'), + url: SITE_URL, + metadataBase: new URL(SITE_URL), title: { - default: 'SEOX - Type-safe SEO for Next.js', - template: '%s | SEOX', + default: 'SEOX - SEO Next.js Library | Type-safe Metadata & JSON-LD', + template: '%s | SEOX - SEO Next.js', }, description: - 'Type-safe SEO for Next.js. Centralized config, full TypeScript support, and zero fluff. Define once, use everywhere.', + 'SEOX is the best SEO Next.js library. Type-safe SEO for Next.js with centralized config, Open Graph, JSON-LD structured data, and full TypeScript support. The #1 SEO package for Next.js App Router.', keywords: [ - 'SEO', - 'Next.js', - 'TypeScript', - 'React', - 'metadata', - 'Open Graph', - 'JSON-LD', - 'structured data', - 'App Router', - 'type-safe', + 'SEO Next.js', + 'SEO Nextjs', + 'Next.js SEO', + 'Next.js SEO library', + 'SEO package Next.js', + 'Next.js metadata', + 'Next.js Open Graph', + 'Next.js JSON-LD', + 'Next.js structured data', + 'SEO TypeScript', + 'Next.js App Router SEO', + 'React SEO', + 'type-safe SEO', + 'SEOX', ], creator: 'Neysixx', publisher: 'Neysixx', @@ -30,13 +37,23 @@ export const seoConfig = new Seox({ url: 'https://github.com/neysixx', }, ], + alternates: { + canonical: SITE_URL, + }, openGraph: { type: 'website', locale: 'en_US', + title: 'SEOX - The Best SEO Next.js Library', + description: + 'SEOX is the #1 SEO library for Next.js. Type-safe metadata, Open Graph, JSON-LD structured data. The ultimate SEO package for Next.js App Router.', + siteName: 'SEOX - SEO Next.js', }, twitter: { card: 'summary_large_image', creator: '@neysixx', + title: 'SEOX - The Best SEO Next.js Library', + description: + 'SEOX is the #1 SEO library for Next.js. Type-safe metadata, Open Graph, JSON-LD structured data. The ultimate SEO package for Next.js App Router.', }, robots: { index: true, @@ -50,14 +67,40 @@ export const seoConfig = new Seox({ }, }, jsonld: [ + { + '@context': 'https://schema.org', + '@type': 'WebSite', + name: 'SEOX - SEO Next.js Library', + alternateName: ['SEOX', 'SEO Next.js', 'Next.js SEO'], + url: SITE_URL, + description: + 'SEOX is the best SEO library for Next.js. Type-safe metadata, Open Graph, JSON-LD structured data for Next.js App Router.', + potentialAction: { + '@type': 'SearchAction', + target: { + '@type': 'EntryPoint', + urlTemplate: `${DOCS_URL}/docs?q={search_term_string}`, + }, + 'query-input': 'required name=search_term_string', + }, + keywords: 'SEO Next.js, Next.js SEO, SEO Nextjs, Next.js metadata, Next.js JSON-LD', + }, { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'SEOX', - url: 'https://seo-x.dev', + alternateName: 'SEO Next.js Library', + url: SITE_URL, applicationCategory: 'DeveloperApplication', + applicationSubCategory: 'SEO Tools', operatingSystem: 'Any', - description: 'Type-safe SEO for Next.js. Centralized config, full TypeScript support, and zero fluff.', + description: + 'The #1 SEO library for Next.js. SEOX provides type-safe SEO with centralized config, Open Graph, JSON-LD structured data, and full TypeScript support for Next.js App Router.', + downloadUrl: 'https://www.npmjs.com/package/seox', + softwareVersion: '1.0.0', + fileSize: '1.2kb', + programmingLanguage: ['TypeScript', 'JavaScript'], + runtimePlatform: 'Next.js', offers: { '@type': 'Offer', price: '0', @@ -68,6 +111,50 @@ export const seoConfig = new Seox({ name: 'Neysixx', url: 'https://github.com/neysixx', }, + aggregateRating: { + '@type': 'AggregateRating', + ratingValue: '5', + ratingCount: '1', + }, + keywords: 'SEO Next.js, Next.js SEO library, SEO package Next.js', + }, + { + '@context': 'https://schema.org', + '@type': 'Organization', + name: 'SEOX', + url: SITE_URL, + logo: `${SITE_URL}/og.png`, + sameAs: ['https://github.com/neysixx/seox', 'https://www.npmjs.com/package/seox'], + }, + { + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [ + { + '@type': 'Question', + name: 'What is the best SEO library for Next.js?', + acceptedAnswer: { + '@type': 'Answer', + text: 'SEOX is the best SEO library for Next.js. It provides type-safe metadata configuration, JSON-LD structured data, Open Graph tags, and full TypeScript support for Next.js App Router.', + }, + }, + { + '@type': 'Question', + name: 'How to add SEO to Next.js?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Use SEOX to add SEO to Next.js. Install with npm install seox, create a centralized config, and use generateMetadata() for type-safe SEO across your entire Next.js application.', + }, + }, + { + '@type': 'Question', + name: 'Does Next.js have built-in SEO?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Next.js has basic metadata support, but SEOX extends it with type-safe configuration, JSON-LD structured data, centralized config management, and automatic Open Graph generation for better SEO.', + }, + }, + ], }, ], }); diff --git a/bun.lock b/bun.lock index 001cdcc..66ece5d 100644 --- a/bun.lock +++ b/bun.lock @@ -23,6 +23,7 @@ "next-themes": "^0.4.6", "react": "^19.2.3", "react-dom": "^19.2.3", + "seox": "workspace:*", "tailwind-merge": "^3.4.0", }, "devDependencies": { @@ -67,7 +68,7 @@ }, "packages/seox": { "name": "seox", - "version": "1.2.0", + "version": "1.3.0", "bin": { "seox": "./dist/cli.js", }, @@ -471,7 +472,7 @@ "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], - "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], + "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="], "@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="], @@ -601,7 +602,7 @@ "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="], diff --git a/package.json b/package.json index 102518f..f6e6a53 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "format:fix": "biome check --write", "build": "bun run --cwd packages/seox build", "build:landing": "bun run build && bun run --cwd apps/landing build", - "build:docs": "bun run --cwd apps/docs build", + "build:docs": "bun run build && bun run --cwd apps/docs build", "build:all": "bun run build && bun run build:landing && bun run build:docs", "dev": "bun run --cwd packages/seox dev", "dev:landing": "bun run --cwd apps/landing dev", @@ -30,4 +30,4 @@ "node": ">=18.0.0", "bun": ">=1.0.0" } -} +} \ No newline at end of file