@masters-ws/react-seo 1.4.4 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +213 -0
- package/dist/index.mjs +212 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ Professional high-performance SEO package for React and Next.js. **Zero-dependen
|
|
|
18
18
|
- ✅ **i18n Ready** — No hardcoded strings, all labels are configurable
|
|
19
19
|
- ✅ **Multilingual Support** — Easy `hreflang` management
|
|
20
20
|
- ✅ **Performance Optimized** — DNS Prefetch, Preconnect, Preload support
|
|
21
|
+
- ✅ **SEO Auditor** — Real-time analysis & preview sidebar (Dev-only)
|
|
21
22
|
|
|
22
23
|
## Installation
|
|
23
24
|
|
|
@@ -33,6 +34,35 @@ npm install @masters-ws/react-seo react-helmet-async
|
|
|
33
34
|
|
|
34
35
|
---
|
|
35
36
|
|
|
37
|
+
## 🔍 SEO Auditor (Development Only)
|
|
38
|
+
|
|
39
|
+
Boost your productivity with the built-in **SEO Auditor**. It provides a real-time analysis of your page's SEO health and shows a live preview of how your page looks in Google search results and social media cards.
|
|
40
|
+
|
|
41
|
+
- **Developer Friendly:** Only renders when `process.env.NODE_ENV === 'development'`.
|
|
42
|
+
- **Live Previews:** See exactly how Google and social platforms see your content.
|
|
43
|
+
- **Audit Checklist:** Instant feedback on title length, description, H1 count, alt tags, and more.
|
|
44
|
+
- **Zero Configuration:** Just drop it into your root layout.
|
|
45
|
+
|
|
46
|
+
### Usage:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
// app/layout.tsx (Next.js App Router)
|
|
50
|
+
import { SEOAuditor } from '@masters-ws/react-seo';
|
|
51
|
+
|
|
52
|
+
export default function RootLayout({ children }) {
|
|
53
|
+
return (
|
|
54
|
+
<html>
|
|
55
|
+
<body>
|
|
56
|
+
{children}
|
|
57
|
+
<SEOAuditor />
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
36
66
|
## 🚀 Quick Start: Next.js App Router (Recommended)
|
|
37
67
|
|
|
38
68
|
### Product Page (One-Call Setup)
|
package/dist/index.d.mts
CHANGED
|
@@ -278,4 +278,6 @@ interface SeoJobPostingProps {
|
|
|
278
278
|
}
|
|
279
279
|
declare const SeoJobPosting: React.FC<SeoJobPostingProps>;
|
|
280
280
|
|
|
281
|
-
|
|
281
|
+
declare const SEOAuditor: React.FC;
|
|
282
|
+
|
|
283
|
+
export { Breadcrumb, BreadcrumbItem, type BreadcrumbProps, type FAQItem, type HowToStep, SEO, SEOAuditor, SEOData, type SEOProps, SEOProvider, type SEOProviderProps, SeoArticle, type SeoArticleProps, SeoAuthor, type SeoAuthorProps, SeoCategory, type SeoCategoryProps, SeoCourse, type SeoCourseProps, SeoEvent, type SeoEventProps, SeoFAQ, type SeoFAQProps, SeoHowTo, type SeoHowToProps, SeoJobPosting, type SeoJobPostingProps, SeoLocalBusiness, type SeoLocalBusinessProps, SeoProduct, type SeoProductProps, SeoRecipe, type SeoRecipeProps, SeoReview, type SeoReviewProps, SeoTag, type SeoTagProps, SeoVideo, type SeoVideoProps, SiteConfig, useSEOConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -278,4 +278,6 @@ interface SeoJobPostingProps {
|
|
|
278
278
|
}
|
|
279
279
|
declare const SeoJobPosting: React.FC<SeoJobPostingProps>;
|
|
280
280
|
|
|
281
|
-
|
|
281
|
+
declare const SEOAuditor: React.FC;
|
|
282
|
+
|
|
283
|
+
export { Breadcrumb, BreadcrumbItem, type BreadcrumbProps, type FAQItem, type HowToStep, SEO, SEOAuditor, SEOData, type SEOProps, SEOProvider, type SEOProviderProps, SeoArticle, type SeoArticleProps, SeoAuthor, type SeoAuthorProps, SeoCategory, type SeoCategoryProps, SeoCourse, type SeoCourseProps, SeoEvent, type SeoEventProps, SeoFAQ, type SeoFAQProps, SeoHowTo, type SeoHowToProps, SeoJobPosting, type SeoJobPostingProps, SeoLocalBusiness, type SeoLocalBusinessProps, SeoProduct, type SeoProductProps, SeoRecipe, type SeoRecipeProps, SeoReview, type SeoReviewProps, SeoTag, type SeoTagProps, SeoVideo, type SeoVideoProps, SiteConfig, useSEOConfig };
|
package/dist/index.js
CHANGED
|
@@ -187,6 +187,7 @@ __export(index_exports, {
|
|
|
187
187
|
Breadcrumb: () => Breadcrumb,
|
|
188
188
|
JsonLd: () => JsonLd,
|
|
189
189
|
SEO: () => SEO,
|
|
190
|
+
SEOAuditor: () => SEOAuditor,
|
|
190
191
|
SEOProvider: () => SEOProvider,
|
|
191
192
|
SeoArticle: () => SeoArticle,
|
|
192
193
|
SeoAuthor: () => SeoAuthor,
|
|
@@ -2588,11 +2589,223 @@ var SeoJobPosting = ({ job }) => {
|
|
|
2588
2589
|
};
|
|
2589
2590
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Helmet, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("script", { type: "application/ld+json", children: JSON.stringify(schema) }) });
|
|
2590
2591
|
};
|
|
2592
|
+
|
|
2593
|
+
// src/components/SEOAuditor.tsx
|
|
2594
|
+
var import_react6 = require("react");
|
|
2595
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2596
|
+
var COLORS = {
|
|
2597
|
+
primary: "#0061e0",
|
|
2598
|
+
success: "#008a00",
|
|
2599
|
+
warning: "#ea4335",
|
|
2600
|
+
bg: "#ffffff",
|
|
2601
|
+
text: "#202124",
|
|
2602
|
+
muted: "#70757a",
|
|
2603
|
+
border: "#dadce0"
|
|
2604
|
+
};
|
|
2605
|
+
var SEOAuditor = () => {
|
|
2606
|
+
const isDev = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
2607
|
+
const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
|
|
2608
|
+
const [data, setData] = (0, import_react6.useState)({
|
|
2609
|
+
title: "",
|
|
2610
|
+
description: "",
|
|
2611
|
+
ogImage: "",
|
|
2612
|
+
ogTitle: "",
|
|
2613
|
+
ogDescription: "",
|
|
2614
|
+
h1Count: 0,
|
|
2615
|
+
imgWithoutAlt: 0,
|
|
2616
|
+
canonical: ""
|
|
2617
|
+
});
|
|
2618
|
+
(0, import_react6.useEffect)(() => {
|
|
2619
|
+
if (!isDev || typeof document === "undefined") return;
|
|
2620
|
+
const analyze = () => {
|
|
2621
|
+
setData({
|
|
2622
|
+
title: document.title,
|
|
2623
|
+
description: document.querySelector('meta[name="description"]')?.getAttribute("content") || "",
|
|
2624
|
+
ogImage: document.querySelector('meta[property="og:image"]')?.getAttribute("content") || "",
|
|
2625
|
+
ogTitle: document.querySelector('meta[property="og:title"]')?.getAttribute("content") || "",
|
|
2626
|
+
ogDescription: document.querySelector('meta[property="og:description"]')?.getAttribute("content") || "",
|
|
2627
|
+
h1Count: document.querySelectorAll("h1").length,
|
|
2628
|
+
imgWithoutAlt: Array.from(document.querySelectorAll("img")).filter((img) => !img.getAttribute("alt")).length,
|
|
2629
|
+
canonical: document.querySelector('link[rel="canonical"]')?.getAttribute("href") || ""
|
|
2630
|
+
});
|
|
2631
|
+
};
|
|
2632
|
+
analyze();
|
|
2633
|
+
const observer = new MutationObserver(analyze);
|
|
2634
|
+
observer.observe(document.head, { subtree: true, childList: true, attributes: true });
|
|
2635
|
+
window.addEventListener("focus", analyze);
|
|
2636
|
+
return () => {
|
|
2637
|
+
window.removeEventListener("focus", analyze);
|
|
2638
|
+
observer.disconnect();
|
|
2639
|
+
};
|
|
2640
|
+
}, [isDev]);
|
|
2641
|
+
if (!isDev) return null;
|
|
2642
|
+
const issues = [];
|
|
2643
|
+
if (!data.title) issues.push("Title is missing");
|
|
2644
|
+
else if (data.title.length < 30) issues.push("Title is too short (min 30 chars recommended)");
|
|
2645
|
+
else if (data.title.length > 60) issues.push("Title is too long (max 60 chars recommended)");
|
|
2646
|
+
if (!data.description) issues.push("Meta description is missing");
|
|
2647
|
+
else if (data.description.length < 120) issues.push("Description is too short (min 120 chars recommended)");
|
|
2648
|
+
else if (data.description.length > 160) issues.push("Description is too long (max 160 chars recommended)");
|
|
2649
|
+
if (data.h1Count !== 1) issues.push(`Found ${data.h1Count} H1 tags (should be exactly 1)`);
|
|
2650
|
+
if (data.imgWithoutAlt > 0) issues.push(`${data.imgWithoutAlt} images missing alt attributes`);
|
|
2651
|
+
if (!data.ogImage) issues.push("OpenGraph image missing for social sharing");
|
|
2652
|
+
const score = Math.max(0, 100 - issues.length * 15);
|
|
2653
|
+
const styles = {
|
|
2654
|
+
button: {
|
|
2655
|
+
position: "fixed",
|
|
2656
|
+
bottom: "20px",
|
|
2657
|
+
right: "20px",
|
|
2658
|
+
width: "56px",
|
|
2659
|
+
height: "56px",
|
|
2660
|
+
borderRadius: "28px",
|
|
2661
|
+
background: isOpen ? COLORS.warning : COLORS.primary,
|
|
2662
|
+
color: "white",
|
|
2663
|
+
display: "flex",
|
|
2664
|
+
alignItems: "center",
|
|
2665
|
+
justifyContent: "center",
|
|
2666
|
+
cursor: "pointer",
|
|
2667
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.2)",
|
|
2668
|
+
zIndex: 9999999,
|
|
2669
|
+
border: "none",
|
|
2670
|
+
fontSize: "24px",
|
|
2671
|
+
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
2672
|
+
outline: "none",
|
|
2673
|
+
padding: 0
|
|
2674
|
+
},
|
|
2675
|
+
sidebar: {
|
|
2676
|
+
position: "fixed",
|
|
2677
|
+
top: 0,
|
|
2678
|
+
right: isOpen ? 0 : "-420px",
|
|
2679
|
+
width: "380px",
|
|
2680
|
+
height: "100vh",
|
|
2681
|
+
background: COLORS.bg,
|
|
2682
|
+
boxShadow: "-4px 0 24px rgba(0,0,0,0.15)",
|
|
2683
|
+
zIndex: 9999998,
|
|
2684
|
+
transition: "right 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
2685
|
+
overflowY: "auto",
|
|
2686
|
+
padding: "0",
|
|
2687
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
2688
|
+
color: COLORS.text,
|
|
2689
|
+
textAlign: "left"
|
|
2690
|
+
},
|
|
2691
|
+
header: {
|
|
2692
|
+
padding: "24px",
|
|
2693
|
+
background: COLORS.primary,
|
|
2694
|
+
color: "white",
|
|
2695
|
+
position: "sticky",
|
|
2696
|
+
top: 0,
|
|
2697
|
+
zIndex: 10
|
|
2698
|
+
},
|
|
2699
|
+
headerTitle: { fontSize: "20px", fontWeight: "bold", margin: "0 0 4px 0", display: "flex", alignItems: "center", gap: "8px" },
|
|
2700
|
+
headerSubtitle: { fontSize: "13px", opacity: 0.8 },
|
|
2701
|
+
content: { padding: "24px" },
|
|
2702
|
+
scoreContainer: { textAlign: "center", marginBottom: "24px" },
|
|
2703
|
+
scoreText: {
|
|
2704
|
+
fontSize: "56px",
|
|
2705
|
+
fontWeight: "bold",
|
|
2706
|
+
color: score > 80 ? COLORS.success : score > 50 ? "#f4b400" : COLORS.warning,
|
|
2707
|
+
lineHeight: "1"
|
|
2708
|
+
},
|
|
2709
|
+
section: { marginTop: "24px", borderTop: `1px solid ${COLORS.border}`, paddingTop: "20px" },
|
|
2710
|
+
sectionTitle: { fontSize: "13px", fontWeight: "bold", textTransform: "uppercase", color: COLORS.muted, marginBottom: "12px", letterSpacing: "0.05em" },
|
|
2711
|
+
googlePreview: { background: "white", padding: "16px", border: `1px solid ${COLORS.border}`, borderRadius: "12px", boxShadow: "0 2px 6px rgba(0,0,0,0.05)" },
|
|
2712
|
+
googleTitle: { color: "#1a0dab", fontSize: "20px", marginBottom: "4px", textDecoration: "none", display: "block", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
2713
|
+
googleUrl: { color: "#202124", fontSize: "14px", marginBottom: "4px", display: "block" },
|
|
2714
|
+
googleDesc: { color: "#4d5156", fontSize: "14px", lineHeight: "1.58" },
|
|
2715
|
+
socialPreview: { background: "white", border: `1px solid ${COLORS.border}`, borderRadius: "12px", overflow: "hidden", boxShadow: "0 2px 6px rgba(0,0,0,0.05)" },
|
|
2716
|
+
socialImage: { width: "100%", aspectRatio: "1.91/1", background: "#f5f5f5", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden" },
|
|
2717
|
+
socialContent: { padding: "12px", background: "#f0f2f5", borderTop: `1px solid ${COLORS.border}` },
|
|
2718
|
+
issue: { background: "#fff1f0", padding: "10px 14px", borderRadius: "6px", marginBottom: "10px", fontSize: "13px", color: "#cf1322", border: "1px solid #ffa39e", display: "flex", alignItems: "flex-start", gap: "8px" },
|
|
2719
|
+
successItem: { background: "#f6ffed", padding: "10px 14px", borderRadius: "6px", marginBottom: "10px", fontSize: "13px", color: "#389e0d", border: "1px solid #b7eb8f", display: "flex", alignItems: "flex-start", gap: "8px" },
|
|
2720
|
+
footer: { marginTop: "32px", padding: "16px", background: "#f8f9fa", borderRadius: "12px", fontSize: "12px", color: COLORS.muted, border: `1px solid ${COLORS.border}` }
|
|
2721
|
+
};
|
|
2722
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2723
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2724
|
+
"button",
|
|
2725
|
+
{
|
|
2726
|
+
style: styles.button,
|
|
2727
|
+
onClick: () => setIsOpen(!isOpen),
|
|
2728
|
+
title: isOpen ? "Close Auditor" : "Open SEO Auditor",
|
|
2729
|
+
children: isOpen ? "\u2715" : "\u{1F50D}"
|
|
2730
|
+
}
|
|
2731
|
+
),
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.sidebar, children: [
|
|
2733
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.header, children: [
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.headerTitle, children: [
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "\u{1F4CA}" }),
|
|
2736
|
+
" SEO Auditor"
|
|
2737
|
+
] }),
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.headerSubtitle, children: "Real-time analysis & preview" })
|
|
2739
|
+
] }),
|
|
2740
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.content, children: [
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.scoreContainer, children: [
|
|
2742
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.scoreText, children: [
|
|
2743
|
+
score,
|
|
2744
|
+
"%"
|
|
2745
|
+
] }),
|
|
2746
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { color: COLORS.muted, fontSize: "14px", marginTop: "4px" }, children: "Page SEO Score" })
|
|
2747
|
+
] }),
|
|
2748
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.section, children: [
|
|
2749
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.sectionTitle, children: "Google Search Result" }),
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.googlePreview, children: [
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.googleTitle, children: data.title || "Add Page Title" }),
|
|
2752
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.googleUrl, children: typeof window !== "undefined" ? data.canonical || window.location.href : "" }),
|
|
2753
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.googleDesc, children: data.description || "\u26A0\uFE0F Pro Tip: Add a meta description between 120-160 characters to improve search standing." })
|
|
2754
|
+
] })
|
|
2755
|
+
] }),
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.section, children: [
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.sectionTitle, children: "Social Media Preview" }),
|
|
2758
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.socialPreview, children: [
|
|
2759
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.socialImage, children: data.ogImage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("img", { src: data.ogImage, alt: "Social preview", style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { color: COLORS.muted, textAlign: "center", padding: "20px" }, children: "\u{1F4F7} No OG image found" }) }),
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.socialContent, children: [
|
|
2761
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { color: COLORS.muted, fontSize: "11px", textTransform: "uppercase", marginBottom: "2px" }, children: typeof window !== "undefined" ? window.location.hostname : "" }),
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontWeight: "bold", fontSize: "15px", color: COLORS.text, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", display: "-webkit-box", WebkitLineClamp: "2", WebkitBoxOrient: "vertical" }, children: data.ogTitle || data.title || "No Social Title" }),
|
|
2763
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: "13px", color: COLORS.muted, overflow: "hidden", textOverflow: "ellipsis", display: "-webkit-box", WebkitLineClamp: "2", WebkitBoxOrient: "vertical" }, children: data.ogDescription || data.description || "No summary available." })
|
|
2764
|
+
] })
|
|
2765
|
+
] })
|
|
2766
|
+
] }),
|
|
2767
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.section, children: [
|
|
2768
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: styles.sectionTitle, children: "SEO Audit Checklist" }),
|
|
2769
|
+
issues.length > 0 ? issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.issue, children: [
|
|
2770
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontWeight: "bold" }, children: "\u274C" }),
|
|
2771
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: issue })
|
|
2772
|
+
] }, i)) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.successItem, children: [
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontWeight: "bold" }, children: "\u2705" }),
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "All structural checks passed! Excellent work." })
|
|
2775
|
+
] }),
|
|
2776
|
+
data.h1Count === 1 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.successItem, children: [
|
|
2777
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "\u2705" }),
|
|
2778
|
+
" Found exactly one H1 tag"
|
|
2779
|
+
] }),
|
|
2780
|
+
data.imgWithoutAlt === 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.successItem, children: [
|
|
2781
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "\u2705" }),
|
|
2782
|
+
" All images have alt attributes"
|
|
2783
|
+
] }),
|
|
2784
|
+
data.canonical && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.successItem, children: [
|
|
2785
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "\u2705" }),
|
|
2786
|
+
" Canonical link is defined"
|
|
2787
|
+
] })
|
|
2788
|
+
] }),
|
|
2789
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: styles.footer, children: [
|
|
2790
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("strong", { children: "\u{1F4A1} Pro Tip:" }),
|
|
2791
|
+
" Use ",
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: "generateArticleMetadata()" }),
|
|
2793
|
+
" or ",
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: "generateProductMetadata()" }),
|
|
2795
|
+
" from ",
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: "@masters-ws/react-seo/core" }),
|
|
2797
|
+
" for one-call professional SEO setup in Next.js."
|
|
2798
|
+
] })
|
|
2799
|
+
] })
|
|
2800
|
+
] })
|
|
2801
|
+
] });
|
|
2802
|
+
};
|
|
2591
2803
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2592
2804
|
0 && (module.exports = {
|
|
2593
2805
|
Breadcrumb,
|
|
2594
2806
|
JsonLd,
|
|
2595
2807
|
SEO,
|
|
2808
|
+
SEOAuditor,
|
|
2596
2809
|
SEOProvider,
|
|
2597
2810
|
SeoArticle,
|
|
2598
2811
|
SeoAuthor,
|
package/dist/index.mjs
CHANGED
|
@@ -1581,10 +1581,222 @@ var SeoJobPosting = ({ job }) => {
|
|
|
1581
1581
|
};
|
|
1582
1582
|
return /* @__PURE__ */ jsx17(Helmet, { children: /* @__PURE__ */ jsx17("script", { type: "application/ld+json", children: JSON.stringify(schema) }) });
|
|
1583
1583
|
};
|
|
1584
|
+
|
|
1585
|
+
// src/components/SEOAuditor.tsx
|
|
1586
|
+
import { useState, useEffect } from "react";
|
|
1587
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1588
|
+
var COLORS = {
|
|
1589
|
+
primary: "#0061e0",
|
|
1590
|
+
success: "#008a00",
|
|
1591
|
+
warning: "#ea4335",
|
|
1592
|
+
bg: "#ffffff",
|
|
1593
|
+
text: "#202124",
|
|
1594
|
+
muted: "#70757a",
|
|
1595
|
+
border: "#dadce0"
|
|
1596
|
+
};
|
|
1597
|
+
var SEOAuditor = () => {
|
|
1598
|
+
const isDev = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
1599
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1600
|
+
const [data, setData] = useState({
|
|
1601
|
+
title: "",
|
|
1602
|
+
description: "",
|
|
1603
|
+
ogImage: "",
|
|
1604
|
+
ogTitle: "",
|
|
1605
|
+
ogDescription: "",
|
|
1606
|
+
h1Count: 0,
|
|
1607
|
+
imgWithoutAlt: 0,
|
|
1608
|
+
canonical: ""
|
|
1609
|
+
});
|
|
1610
|
+
useEffect(() => {
|
|
1611
|
+
if (!isDev || typeof document === "undefined") return;
|
|
1612
|
+
const analyze = () => {
|
|
1613
|
+
setData({
|
|
1614
|
+
title: document.title,
|
|
1615
|
+
description: document.querySelector('meta[name="description"]')?.getAttribute("content") || "",
|
|
1616
|
+
ogImage: document.querySelector('meta[property="og:image"]')?.getAttribute("content") || "",
|
|
1617
|
+
ogTitle: document.querySelector('meta[property="og:title"]')?.getAttribute("content") || "",
|
|
1618
|
+
ogDescription: document.querySelector('meta[property="og:description"]')?.getAttribute("content") || "",
|
|
1619
|
+
h1Count: document.querySelectorAll("h1").length,
|
|
1620
|
+
imgWithoutAlt: Array.from(document.querySelectorAll("img")).filter((img) => !img.getAttribute("alt")).length,
|
|
1621
|
+
canonical: document.querySelector('link[rel="canonical"]')?.getAttribute("href") || ""
|
|
1622
|
+
});
|
|
1623
|
+
};
|
|
1624
|
+
analyze();
|
|
1625
|
+
const observer = new MutationObserver(analyze);
|
|
1626
|
+
observer.observe(document.head, { subtree: true, childList: true, attributes: true });
|
|
1627
|
+
window.addEventListener("focus", analyze);
|
|
1628
|
+
return () => {
|
|
1629
|
+
window.removeEventListener("focus", analyze);
|
|
1630
|
+
observer.disconnect();
|
|
1631
|
+
};
|
|
1632
|
+
}, [isDev]);
|
|
1633
|
+
if (!isDev) return null;
|
|
1634
|
+
const issues = [];
|
|
1635
|
+
if (!data.title) issues.push("Title is missing");
|
|
1636
|
+
else if (data.title.length < 30) issues.push("Title is too short (min 30 chars recommended)");
|
|
1637
|
+
else if (data.title.length > 60) issues.push("Title is too long (max 60 chars recommended)");
|
|
1638
|
+
if (!data.description) issues.push("Meta description is missing");
|
|
1639
|
+
else if (data.description.length < 120) issues.push("Description is too short (min 120 chars recommended)");
|
|
1640
|
+
else if (data.description.length > 160) issues.push("Description is too long (max 160 chars recommended)");
|
|
1641
|
+
if (data.h1Count !== 1) issues.push(`Found ${data.h1Count} H1 tags (should be exactly 1)`);
|
|
1642
|
+
if (data.imgWithoutAlt > 0) issues.push(`${data.imgWithoutAlt} images missing alt attributes`);
|
|
1643
|
+
if (!data.ogImage) issues.push("OpenGraph image missing for social sharing");
|
|
1644
|
+
const score = Math.max(0, 100 - issues.length * 15);
|
|
1645
|
+
const styles = {
|
|
1646
|
+
button: {
|
|
1647
|
+
position: "fixed",
|
|
1648
|
+
bottom: "20px",
|
|
1649
|
+
right: "20px",
|
|
1650
|
+
width: "56px",
|
|
1651
|
+
height: "56px",
|
|
1652
|
+
borderRadius: "28px",
|
|
1653
|
+
background: isOpen ? COLORS.warning : COLORS.primary,
|
|
1654
|
+
color: "white",
|
|
1655
|
+
display: "flex",
|
|
1656
|
+
alignItems: "center",
|
|
1657
|
+
justifyContent: "center",
|
|
1658
|
+
cursor: "pointer",
|
|
1659
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.2)",
|
|
1660
|
+
zIndex: 9999999,
|
|
1661
|
+
border: "none",
|
|
1662
|
+
fontSize: "24px",
|
|
1663
|
+
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1664
|
+
outline: "none",
|
|
1665
|
+
padding: 0
|
|
1666
|
+
},
|
|
1667
|
+
sidebar: {
|
|
1668
|
+
position: "fixed",
|
|
1669
|
+
top: 0,
|
|
1670
|
+
right: isOpen ? 0 : "-420px",
|
|
1671
|
+
width: "380px",
|
|
1672
|
+
height: "100vh",
|
|
1673
|
+
background: COLORS.bg,
|
|
1674
|
+
boxShadow: "-4px 0 24px rgba(0,0,0,0.15)",
|
|
1675
|
+
zIndex: 9999998,
|
|
1676
|
+
transition: "right 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1677
|
+
overflowY: "auto",
|
|
1678
|
+
padding: "0",
|
|
1679
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
1680
|
+
color: COLORS.text,
|
|
1681
|
+
textAlign: "left"
|
|
1682
|
+
},
|
|
1683
|
+
header: {
|
|
1684
|
+
padding: "24px",
|
|
1685
|
+
background: COLORS.primary,
|
|
1686
|
+
color: "white",
|
|
1687
|
+
position: "sticky",
|
|
1688
|
+
top: 0,
|
|
1689
|
+
zIndex: 10
|
|
1690
|
+
},
|
|
1691
|
+
headerTitle: { fontSize: "20px", fontWeight: "bold", margin: "0 0 4px 0", display: "flex", alignItems: "center", gap: "8px" },
|
|
1692
|
+
headerSubtitle: { fontSize: "13px", opacity: 0.8 },
|
|
1693
|
+
content: { padding: "24px" },
|
|
1694
|
+
scoreContainer: { textAlign: "center", marginBottom: "24px" },
|
|
1695
|
+
scoreText: {
|
|
1696
|
+
fontSize: "56px",
|
|
1697
|
+
fontWeight: "bold",
|
|
1698
|
+
color: score > 80 ? COLORS.success : score > 50 ? "#f4b400" : COLORS.warning,
|
|
1699
|
+
lineHeight: "1"
|
|
1700
|
+
},
|
|
1701
|
+
section: { marginTop: "24px", borderTop: `1px solid ${COLORS.border}`, paddingTop: "20px" },
|
|
1702
|
+
sectionTitle: { fontSize: "13px", fontWeight: "bold", textTransform: "uppercase", color: COLORS.muted, marginBottom: "12px", letterSpacing: "0.05em" },
|
|
1703
|
+
googlePreview: { background: "white", padding: "16px", border: `1px solid ${COLORS.border}`, borderRadius: "12px", boxShadow: "0 2px 6px rgba(0,0,0,0.05)" },
|
|
1704
|
+
googleTitle: { color: "#1a0dab", fontSize: "20px", marginBottom: "4px", textDecoration: "none", display: "block", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
1705
|
+
googleUrl: { color: "#202124", fontSize: "14px", marginBottom: "4px", display: "block" },
|
|
1706
|
+
googleDesc: { color: "#4d5156", fontSize: "14px", lineHeight: "1.58" },
|
|
1707
|
+
socialPreview: { background: "white", border: `1px solid ${COLORS.border}`, borderRadius: "12px", overflow: "hidden", boxShadow: "0 2px 6px rgba(0,0,0,0.05)" },
|
|
1708
|
+
socialImage: { width: "100%", aspectRatio: "1.91/1", background: "#f5f5f5", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden" },
|
|
1709
|
+
socialContent: { padding: "12px", background: "#f0f2f5", borderTop: `1px solid ${COLORS.border}` },
|
|
1710
|
+
issue: { background: "#fff1f0", padding: "10px 14px", borderRadius: "6px", marginBottom: "10px", fontSize: "13px", color: "#cf1322", border: "1px solid #ffa39e", display: "flex", alignItems: "flex-start", gap: "8px" },
|
|
1711
|
+
successItem: { background: "#f6ffed", padding: "10px 14px", borderRadius: "6px", marginBottom: "10px", fontSize: "13px", color: "#389e0d", border: "1px solid #b7eb8f", display: "flex", alignItems: "flex-start", gap: "8px" },
|
|
1712
|
+
footer: { marginTop: "32px", padding: "16px", background: "#f8f9fa", borderRadius: "12px", fontSize: "12px", color: COLORS.muted, border: `1px solid ${COLORS.border}` }
|
|
1713
|
+
};
|
|
1714
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1715
|
+
/* @__PURE__ */ jsx18(
|
|
1716
|
+
"button",
|
|
1717
|
+
{
|
|
1718
|
+
style: styles.button,
|
|
1719
|
+
onClick: () => setIsOpen(!isOpen),
|
|
1720
|
+
title: isOpen ? "Close Auditor" : "Open SEO Auditor",
|
|
1721
|
+
children: isOpen ? "\u2715" : "\u{1F50D}"
|
|
1722
|
+
}
|
|
1723
|
+
),
|
|
1724
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.sidebar, children: [
|
|
1725
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.header, children: [
|
|
1726
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.headerTitle, children: [
|
|
1727
|
+
/* @__PURE__ */ jsx18("span", { children: "\u{1F4CA}" }),
|
|
1728
|
+
" SEO Auditor"
|
|
1729
|
+
] }),
|
|
1730
|
+
/* @__PURE__ */ jsx18("div", { style: styles.headerSubtitle, children: "Real-time analysis & preview" })
|
|
1731
|
+
] }),
|
|
1732
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.content, children: [
|
|
1733
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.scoreContainer, children: [
|
|
1734
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.scoreText, children: [
|
|
1735
|
+
score,
|
|
1736
|
+
"%"
|
|
1737
|
+
] }),
|
|
1738
|
+
/* @__PURE__ */ jsx18("div", { style: { color: COLORS.muted, fontSize: "14px", marginTop: "4px" }, children: "Page SEO Score" })
|
|
1739
|
+
] }),
|
|
1740
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.section, children: [
|
|
1741
|
+
/* @__PURE__ */ jsx18("div", { style: styles.sectionTitle, children: "Google Search Result" }),
|
|
1742
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.googlePreview, children: [
|
|
1743
|
+
/* @__PURE__ */ jsx18("div", { style: styles.googleTitle, children: data.title || "Add Page Title" }),
|
|
1744
|
+
/* @__PURE__ */ jsx18("div", { style: styles.googleUrl, children: typeof window !== "undefined" ? data.canonical || window.location.href : "" }),
|
|
1745
|
+
/* @__PURE__ */ jsx18("div", { style: styles.googleDesc, children: data.description || "\u26A0\uFE0F Pro Tip: Add a meta description between 120-160 characters to improve search standing." })
|
|
1746
|
+
] })
|
|
1747
|
+
] }),
|
|
1748
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.section, children: [
|
|
1749
|
+
/* @__PURE__ */ jsx18("div", { style: styles.sectionTitle, children: "Social Media Preview" }),
|
|
1750
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.socialPreview, children: [
|
|
1751
|
+
/* @__PURE__ */ jsx18("div", { style: styles.socialImage, children: data.ogImage ? /* @__PURE__ */ jsx18("img", { src: data.ogImage, alt: "Social preview", style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ jsx18("div", { style: { color: COLORS.muted, textAlign: "center", padding: "20px" }, children: "\u{1F4F7} No OG image found" }) }),
|
|
1752
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.socialContent, children: [
|
|
1753
|
+
/* @__PURE__ */ jsx18("div", { style: { color: COLORS.muted, fontSize: "11px", textTransform: "uppercase", marginBottom: "2px" }, children: typeof window !== "undefined" ? window.location.hostname : "" }),
|
|
1754
|
+
/* @__PURE__ */ jsx18("div", { style: { fontWeight: "bold", fontSize: "15px", color: COLORS.text, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", display: "-webkit-box", WebkitLineClamp: "2", WebkitBoxOrient: "vertical" }, children: data.ogTitle || data.title || "No Social Title" }),
|
|
1755
|
+
/* @__PURE__ */ jsx18("div", { style: { fontSize: "13px", color: COLORS.muted, overflow: "hidden", textOverflow: "ellipsis", display: "-webkit-box", WebkitLineClamp: "2", WebkitBoxOrient: "vertical" }, children: data.ogDescription || data.description || "No summary available." })
|
|
1756
|
+
] })
|
|
1757
|
+
] })
|
|
1758
|
+
] }),
|
|
1759
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.section, children: [
|
|
1760
|
+
/* @__PURE__ */ jsx18("div", { style: styles.sectionTitle, children: "SEO Audit Checklist" }),
|
|
1761
|
+
issues.length > 0 ? issues.map((issue, i) => /* @__PURE__ */ jsxs3("div", { style: styles.issue, children: [
|
|
1762
|
+
/* @__PURE__ */ jsx18("span", { style: { fontWeight: "bold" }, children: "\u274C" }),
|
|
1763
|
+
/* @__PURE__ */ jsx18("span", { children: issue })
|
|
1764
|
+
] }, i)) : /* @__PURE__ */ jsxs3("div", { style: styles.successItem, children: [
|
|
1765
|
+
/* @__PURE__ */ jsx18("span", { style: { fontWeight: "bold" }, children: "\u2705" }),
|
|
1766
|
+
/* @__PURE__ */ jsx18("span", { children: "All structural checks passed! Excellent work." })
|
|
1767
|
+
] }),
|
|
1768
|
+
data.h1Count === 1 && /* @__PURE__ */ jsxs3("div", { style: styles.successItem, children: [
|
|
1769
|
+
/* @__PURE__ */ jsx18("span", { children: "\u2705" }),
|
|
1770
|
+
" Found exactly one H1 tag"
|
|
1771
|
+
] }),
|
|
1772
|
+
data.imgWithoutAlt === 0 && /* @__PURE__ */ jsxs3("div", { style: styles.successItem, children: [
|
|
1773
|
+
/* @__PURE__ */ jsx18("span", { children: "\u2705" }),
|
|
1774
|
+
" All images have alt attributes"
|
|
1775
|
+
] }),
|
|
1776
|
+
data.canonical && /* @__PURE__ */ jsxs3("div", { style: styles.successItem, children: [
|
|
1777
|
+
/* @__PURE__ */ jsx18("span", { children: "\u2705" }),
|
|
1778
|
+
" Canonical link is defined"
|
|
1779
|
+
] })
|
|
1780
|
+
] }),
|
|
1781
|
+
/* @__PURE__ */ jsxs3("div", { style: styles.footer, children: [
|
|
1782
|
+
/* @__PURE__ */ jsx18("strong", { children: "\u{1F4A1} Pro Tip:" }),
|
|
1783
|
+
" Use ",
|
|
1784
|
+
/* @__PURE__ */ jsx18("code", { children: "generateArticleMetadata()" }),
|
|
1785
|
+
" or ",
|
|
1786
|
+
/* @__PURE__ */ jsx18("code", { children: "generateProductMetadata()" }),
|
|
1787
|
+
" from ",
|
|
1788
|
+
/* @__PURE__ */ jsx18("code", { children: "@masters-ws/react-seo/core" }),
|
|
1789
|
+
" for one-call professional SEO setup in Next.js."
|
|
1790
|
+
] })
|
|
1791
|
+
] })
|
|
1792
|
+
] })
|
|
1793
|
+
] });
|
|
1794
|
+
};
|
|
1584
1795
|
export {
|
|
1585
1796
|
Breadcrumb,
|
|
1586
1797
|
JsonLd,
|
|
1587
1798
|
SEO,
|
|
1799
|
+
SEOAuditor,
|
|
1588
1800
|
SEOProvider,
|
|
1589
1801
|
SeoArticle,
|
|
1590
1802
|
SeoAuthor,
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masters-ws/react-seo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Professional high-performance SEO package for React/Next.js. Zero-dependency core for Next.js App Router, optional Helmet components for React.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.mjs",
|
|
12
|
-
"
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"./core": {
|
|
15
|
-
"
|
|
15
|
+
"types": "./dist/core/index.d.ts",
|
|
16
16
|
"import": "./dist/core/index.mjs",
|
|
17
|
-
"
|
|
17
|
+
"require": "./dist/core/index.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"files": [
|