@masters-ws/react-seo 1.2.0 → 1.4.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.
@@ -0,0 +1,1272 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface SiteConfig {
4
+ name: string;
5
+ description: string;
6
+ url: string;
7
+ logo?: string;
8
+ publisher?: string;
9
+ twitterHandle?: string;
10
+ facebookAppId?: string;
11
+ language?: string;
12
+ socialLinks?: string[];
13
+ googleAnalyticsId?: string;
14
+ gtmId?: string;
15
+ facebookPixelId?: string;
16
+ yandexMetricaId?: string;
17
+ themeColor?: string;
18
+ manifest?: string;
19
+ }
20
+ interface SEOData {
21
+ title?: string;
22
+ description?: string;
23
+ image?: string;
24
+ canonical?: string;
25
+ type?: 'website' | 'article' | 'product' | 'profile' | 'video' | 'faq';
26
+ robots?: string;
27
+ noindex?: boolean;
28
+ keywords?: string[];
29
+ prev?: string;
30
+ next?: string;
31
+ alternates?: Array<{
32
+ hreflang: string;
33
+ href: string;
34
+ }>;
35
+ ogTitle?: string;
36
+ ogDescription?: string;
37
+ ogImage?: string;
38
+ ogImageWidth?: number;
39
+ ogImageHeight?: number;
40
+ ogImageAlt?: string;
41
+ ogType?: string;
42
+ ogLocale?: string;
43
+ twitterCard?: 'summary' | 'summary_large_image' | 'app' | 'player';
44
+ twitterTitle?: string;
45
+ twitterDescription?: string;
46
+ twitterImage?: string;
47
+ twitterImageAlt?: string;
48
+ publishedTime?: string;
49
+ modifiedTime?: string;
50
+ author?: {
51
+ name: string;
52
+ url?: string;
53
+ image?: string;
54
+ };
55
+ tags?: string[];
56
+ section?: string;
57
+ readingTime?: number;
58
+ product?: {
59
+ sku?: string;
60
+ brand?: string;
61
+ price?: number;
62
+ currency?: string;
63
+ availability?: string;
64
+ rating?: number;
65
+ reviewCount?: number;
66
+ };
67
+ dnsPrefetch?: string[];
68
+ preconnect?: string[];
69
+ prefetch?: string[];
70
+ preload?: Array<{
71
+ href: string;
72
+ as: string;
73
+ type?: string;
74
+ }>;
75
+ whatsappImage?: string;
76
+ whatsappDescription?: string;
77
+ schema?: any;
78
+ }
79
+ interface BreadcrumbItem {
80
+ name: string;
81
+ item: string;
82
+ }
83
+
84
+ /**
85
+ * Generate Organization Schema
86
+ */
87
+ declare function generateOrganizationSchema(config: SiteConfig): {
88
+ "@context": string;
89
+ "@type": string;
90
+ name: string;
91
+ url: string;
92
+ logo: string | undefined;
93
+ description: string;
94
+ sameAs: string[];
95
+ };
96
+ /**
97
+ * Generate WebSite Schema with SearchAction
98
+ */
99
+ declare function generateWebSiteSchema(config: SiteConfig): {
100
+ "@context": string;
101
+ "@type": string;
102
+ name: string;
103
+ url: string;
104
+ description: string;
105
+ publisher: {
106
+ "@type": string;
107
+ name: string;
108
+ logo: string | undefined;
109
+ };
110
+ potentialAction: {
111
+ "@type": string;
112
+ target: string;
113
+ "query-input": string;
114
+ };
115
+ };
116
+ /**
117
+ * Generate WebPage Schema
118
+ */
119
+ declare function generateWebPageSchema(data: {
120
+ name: string;
121
+ description: string;
122
+ url: string;
123
+ image?: string;
124
+ datePublished?: string;
125
+ dateModified?: string;
126
+ breadcrumb?: Array<{
127
+ name: string;
128
+ item: string;
129
+ }>;
130
+ }, config: SiteConfig): {
131
+ "@context": string;
132
+ "@type": string;
133
+ name: string;
134
+ description: string;
135
+ url: string;
136
+ image: string | undefined;
137
+ datePublished: string | undefined;
138
+ dateModified: string | undefined;
139
+ isPartOf: {
140
+ "@type": string;
141
+ name: string;
142
+ url: string;
143
+ };
144
+ breadcrumb: {
145
+ "@context": string;
146
+ "@type": string;
147
+ itemListElement: {
148
+ "@type": string;
149
+ position: number;
150
+ name: string;
151
+ item: string;
152
+ }[];
153
+ } | undefined;
154
+ };
155
+ /**
156
+ * Generate CollectionPage Schema (for category / archive pages)
157
+ */
158
+ declare function generateCollectionPageSchema(data: {
159
+ name: string;
160
+ description: string;
161
+ url: string;
162
+ image?: string;
163
+ numberOfItems?: number;
164
+ }, config: SiteConfig): {
165
+ "@context": string;
166
+ "@type": string;
167
+ name: string;
168
+ description: string;
169
+ url: string;
170
+ image: string | undefined;
171
+ numberOfItems: number | undefined;
172
+ isPartOf: {
173
+ "@type": string;
174
+ name: string;
175
+ url: string;
176
+ };
177
+ };
178
+ /**
179
+ * Generate ItemList Schema (for product listings, search results, etc.)
180
+ *
181
+ * @example
182
+ * generateItemListSchema({
183
+ * name: "Electronics",
184
+ * url: "https://store.com/electronics",
185
+ * items: products.map(p => ({
186
+ * name: p.name,
187
+ * url: `https://store.com/products/${p.slug}`,
188
+ * image: p.image,
189
+ * position: p.index + 1,
190
+ * })),
191
+ * });
192
+ */
193
+ declare function generateItemListSchema(data: {
194
+ name?: string;
195
+ url?: string;
196
+ itemListOrder?: 'ascending' | 'descending' | 'unordered';
197
+ items: Array<{
198
+ url: string;
199
+ name: string;
200
+ image?: string;
201
+ position?: number;
202
+ }>;
203
+ }): {
204
+ "@context": string;
205
+ "@type": string;
206
+ name: string | undefined;
207
+ url: string | undefined;
208
+ itemListOrder: string;
209
+ numberOfItems: number;
210
+ itemListElement: {
211
+ "@type": string;
212
+ position: number;
213
+ name: string;
214
+ url: string;
215
+ image: string | undefined;
216
+ }[];
217
+ };
218
+ /**
219
+ * Generate NewsArticle Schema
220
+ */
221
+ declare function generateArticleSchema(data: {
222
+ title: string;
223
+ description: string;
224
+ image?: string | string[];
225
+ publishedTime?: string;
226
+ modifiedTime?: string;
227
+ author?: {
228
+ name: string;
229
+ url?: string;
230
+ };
231
+ url?: string;
232
+ wordCount?: number;
233
+ }, config: SiteConfig): {
234
+ "@context": string;
235
+ "@type": string;
236
+ headline: string;
237
+ description: string;
238
+ image: string | string[] | undefined;
239
+ datePublished: string | undefined;
240
+ dateModified: string | undefined;
241
+ mainEntityOfPage: string | undefined;
242
+ wordCount: number | undefined;
243
+ author: {
244
+ "@context": string;
245
+ "@type": string;
246
+ name: string;
247
+ url: string;
248
+ logo: string | undefined;
249
+ description: string;
250
+ sameAs: string[];
251
+ } | {
252
+ "@type": string;
253
+ name: string;
254
+ url: string | undefined;
255
+ };
256
+ publisher: {
257
+ "@context": string;
258
+ "@type": string;
259
+ name: string;
260
+ url: string;
261
+ logo: string | undefined;
262
+ description: string;
263
+ sameAs: string[];
264
+ };
265
+ };
266
+ /**
267
+ * Product review for use in Product schema
268
+ */
269
+ interface ProductReview {
270
+ author: string;
271
+ datePublished?: string;
272
+ reviewBody?: string;
273
+ ratingValue: number;
274
+ bestRating?: number;
275
+ }
276
+ /**
277
+ * Merchant return policy for Product schema
278
+ */
279
+ interface MerchantReturnPolicy {
280
+ returnPolicyCategory?: 'MerchantReturnFiniteReturnWindow' | 'MerchantReturnNotPermitted' | 'MerchantReturnUnlimitedWindow';
281
+ returnWithin?: number;
282
+ returnMethod?: 'ReturnByMail' | 'ReturnInStore' | 'ReturnAtKiosk';
283
+ returnFees?: 'FreeReturn' | 'ReturnFeesCustomerResponsibility' | 'OriginalShippingFees';
284
+ }
285
+ /**
286
+ * Shipping details for Product schema
287
+ */
288
+ interface ShippingDetails {
289
+ shippingRate?: {
290
+ value: number;
291
+ currency: string;
292
+ };
293
+ shippingDestination?: string;
294
+ deliveryTime?: {
295
+ minDays: number;
296
+ maxDays: number;
297
+ };
298
+ freeShippingThreshold?: number;
299
+ }
300
+ /**
301
+ * Product offer variant
302
+ */
303
+ interface ProductVariant {
304
+ name: string;
305
+ sku?: string;
306
+ price: number;
307
+ currency?: string;
308
+ availability?: string;
309
+ url?: string;
310
+ image?: string;
311
+ }
312
+ /**
313
+ * Generate Product Schema
314
+ * Supports multi-image, individual reviews, return policy, shipping, and variants.
315
+ */
316
+ declare function generateProductSchema(data: {
317
+ name: string;
318
+ description: string;
319
+ image?: string | string[];
320
+ sku?: string;
321
+ gtin?: string;
322
+ mpn?: string;
323
+ brand?: string;
324
+ price?: number;
325
+ currency?: string;
326
+ availability?: string;
327
+ rating?: number;
328
+ reviewCount?: number;
329
+ url?: string;
330
+ condition?: 'NewCondition' | 'UsedCondition' | 'RefurbishedCondition' | 'DamagedCondition';
331
+ reviews?: ProductReview[];
332
+ returnPolicy?: MerchantReturnPolicy;
333
+ shipping?: ShippingDetails;
334
+ variants?: ProductVariant[];
335
+ seller?: {
336
+ name: string;
337
+ url?: string;
338
+ };
339
+ }): {
340
+ "@context": string;
341
+ "@type": string;
342
+ name: string;
343
+ description: string;
344
+ image: string | string[] | undefined;
345
+ sku: string | undefined;
346
+ gtin: string | undefined;
347
+ mpn: string | undefined;
348
+ brand: {
349
+ "@type": string;
350
+ name: string;
351
+ } | undefined;
352
+ offers: any;
353
+ aggregateRating: {
354
+ "@type": string;
355
+ ratingValue: number;
356
+ reviewCount: number;
357
+ } | undefined;
358
+ review: {
359
+ "@type": string;
360
+ author: {
361
+ "@type": string;
362
+ name: string;
363
+ };
364
+ datePublished: string | undefined;
365
+ reviewBody: string | undefined;
366
+ reviewRating: {
367
+ "@type": string;
368
+ ratingValue: number;
369
+ bestRating: number;
370
+ };
371
+ }[] | undefined;
372
+ };
373
+ /**
374
+ * Generate FAQ Schema
375
+ */
376
+ declare function generateFAQSchema(questions: Array<{
377
+ q: string;
378
+ a: string;
379
+ }>): {
380
+ "@context": string;
381
+ "@type": string;
382
+ mainEntity: {
383
+ "@type": string;
384
+ name: string;
385
+ acceptedAnswer: {
386
+ "@type": string;
387
+ text: string;
388
+ };
389
+ }[];
390
+ };
391
+ /**
392
+ * Generate Breadcrumb Schema
393
+ */
394
+ declare function generateBreadcrumbSchema(items: Array<{
395
+ name: string;
396
+ item: string;
397
+ }>): {
398
+ "@context": string;
399
+ "@type": string;
400
+ itemListElement: {
401
+ "@type": string;
402
+ position: number;
403
+ name: string;
404
+ item: string;
405
+ }[];
406
+ };
407
+ /**
408
+ * Generate Video Schema
409
+ */
410
+ declare function generateVideoSchema(data: {
411
+ name: string;
412
+ description: string;
413
+ thumbnailUrl: string;
414
+ uploadDate: string;
415
+ duration?: string;
416
+ contentUrl?: string;
417
+ embedUrl?: string;
418
+ }): {
419
+ "@context": string;
420
+ "@type": string;
421
+ name: string;
422
+ description: string;
423
+ thumbnailUrl: string;
424
+ uploadDate: string;
425
+ duration: string | undefined;
426
+ contentUrl: string | undefined;
427
+ embedUrl: string | undefined;
428
+ };
429
+ /**
430
+ * Generate Event Schema
431
+ */
432
+ declare function generateEventSchema(data: {
433
+ name: string;
434
+ description: string;
435
+ startDate: string;
436
+ endDate?: string;
437
+ location?: {
438
+ name: string;
439
+ address: string;
440
+ } | {
441
+ url: string;
442
+ };
443
+ image?: string;
444
+ offers?: {
445
+ price: number;
446
+ currency: string;
447
+ url: string;
448
+ };
449
+ }): {
450
+ "@context": string;
451
+ "@type": string;
452
+ name: string;
453
+ description: string;
454
+ startDate: string;
455
+ endDate: string | undefined;
456
+ eventAttendanceMode: string;
457
+ location: {
458
+ "@type": string;
459
+ url: string;
460
+ name?: undefined;
461
+ address?: undefined;
462
+ } | {
463
+ "@type": string;
464
+ name: string;
465
+ address: string;
466
+ url?: undefined;
467
+ } | undefined;
468
+ image: string | undefined;
469
+ offers: {
470
+ "@type": string;
471
+ price: number;
472
+ priceCurrency: string;
473
+ url: string;
474
+ } | undefined;
475
+ };
476
+ /**
477
+ * Generate LocalBusiness Schema
478
+ */
479
+ declare function generateLocalBusinessSchema(data: {
480
+ name: string;
481
+ description: string;
482
+ image?: string;
483
+ telephone?: string;
484
+ address: {
485
+ street: string;
486
+ city: string;
487
+ region?: string;
488
+ postalCode?: string;
489
+ country: string;
490
+ };
491
+ geo?: {
492
+ lat: number;
493
+ lng: number;
494
+ };
495
+ openingHours?: string[];
496
+ priceRange?: string;
497
+ }): {
498
+ "@context": string;
499
+ "@type": string;
500
+ name: string;
501
+ description: string;
502
+ image: string | undefined;
503
+ telephone: string | undefined;
504
+ address: {
505
+ "@type": string;
506
+ streetAddress: string;
507
+ addressLocality: string;
508
+ addressRegion: string | undefined;
509
+ postalCode: string | undefined;
510
+ addressCountry: string;
511
+ };
512
+ geo: {
513
+ "@type": string;
514
+ latitude: number;
515
+ longitude: number;
516
+ } | undefined;
517
+ openingHours: string[] | undefined;
518
+ priceRange: string | undefined;
519
+ };
520
+ /**
521
+ * Generate SoftwareApplication Schema
522
+ */
523
+ declare function generateSoftwareSchema(data: {
524
+ name: string;
525
+ description: string;
526
+ operatingSystem?: string;
527
+ applicationCategory?: string;
528
+ offers?: {
529
+ price: number;
530
+ currency: string;
531
+ };
532
+ rating?: number;
533
+ reviewCount?: number;
534
+ downloadUrl?: string;
535
+ screenshot?: string;
536
+ }): {
537
+ "@context": string;
538
+ "@type": string;
539
+ name: string;
540
+ description: string;
541
+ operatingSystem: string | undefined;
542
+ applicationCategory: string | undefined;
543
+ offers: {
544
+ "@type": string;
545
+ price: number;
546
+ priceCurrency: string;
547
+ } | undefined;
548
+ aggregateRating: {
549
+ "@type": string;
550
+ ratingValue: number;
551
+ reviewCount: number;
552
+ } | undefined;
553
+ downloadUrl: string | undefined;
554
+ screenshot: string | undefined;
555
+ };
556
+ /**
557
+ * Generate Book Schema
558
+ */
559
+ declare function generateBookSchema(data: {
560
+ name: string;
561
+ author: string | {
562
+ name: string;
563
+ url?: string;
564
+ };
565
+ description: string;
566
+ isbn?: string;
567
+ numberOfPages?: number;
568
+ publisher?: string;
569
+ datePublished?: string;
570
+ image?: string;
571
+ inLanguage?: string;
572
+ genre?: string;
573
+ }): {
574
+ "@context": string;
575
+ "@type": string;
576
+ name: string;
577
+ author: {
578
+ "@type": string;
579
+ name: string;
580
+ url?: undefined;
581
+ } | {
582
+ "@type": string;
583
+ name: string;
584
+ url: string | undefined;
585
+ };
586
+ description: string;
587
+ isbn: string | undefined;
588
+ numberOfPages: number | undefined;
589
+ publisher: {
590
+ "@type": string;
591
+ name: string;
592
+ } | undefined;
593
+ datePublished: string | undefined;
594
+ image: string | undefined;
595
+ inLanguage: string | undefined;
596
+ genre: string | undefined;
597
+ };
598
+ /**
599
+ * Generate Movie Schema
600
+ */
601
+ declare function generateMovieSchema(data: {
602
+ name: string;
603
+ description: string;
604
+ image?: string;
605
+ director?: string;
606
+ actor?: string[];
607
+ dateCreated?: string;
608
+ duration?: string;
609
+ genre?: string[];
610
+ rating?: number;
611
+ reviewCount?: number;
612
+ }): {
613
+ "@context": string;
614
+ "@type": string;
615
+ name: string;
616
+ description: string;
617
+ image: string | undefined;
618
+ director: {
619
+ "@type": string;
620
+ name: string;
621
+ } | undefined;
622
+ actor: {
623
+ "@type": string;
624
+ name: string;
625
+ }[] | undefined;
626
+ dateCreated: string | undefined;
627
+ duration: string | undefined;
628
+ genre: string[] | undefined;
629
+ aggregateRating: {
630
+ "@type": string;
631
+ ratingValue: number;
632
+ reviewCount: number;
633
+ } | undefined;
634
+ };
635
+ /**
636
+ * Generate Podcast Schema (PodcastSeries)
637
+ */
638
+ declare function generatePodcastSchema(data: {
639
+ name: string;
640
+ description: string;
641
+ image?: string;
642
+ author?: string;
643
+ webFeed?: string;
644
+ url?: string;
645
+ genre?: string;
646
+ }): {
647
+ "@context": string;
648
+ "@type": string;
649
+ name: string;
650
+ description: string;
651
+ image: string | undefined;
652
+ author: {
653
+ "@type": string;
654
+ name: string;
655
+ } | undefined;
656
+ webFeed: string | undefined;
657
+ url: string | undefined;
658
+ genre: string | undefined;
659
+ };
660
+ /**
661
+ * Generate PodcastEpisode Schema
662
+ */
663
+ declare function generatePodcastEpisodeSchema(data: {
664
+ name: string;
665
+ description: string;
666
+ datePublished: string;
667
+ duration?: string;
668
+ url?: string;
669
+ audio?: string;
670
+ partOfSeries?: {
671
+ name: string;
672
+ url: string;
673
+ };
674
+ }): {
675
+ "@context": string;
676
+ "@type": string;
677
+ name: string;
678
+ description: string;
679
+ datePublished: string;
680
+ timeRequired: string | undefined;
681
+ url: string | undefined;
682
+ associatedMedia: {
683
+ "@type": string;
684
+ contentUrl: string;
685
+ } | undefined;
686
+ partOfSeries: {
687
+ "@type": string;
688
+ name: string;
689
+ url: string;
690
+ } | undefined;
691
+ };
692
+ /**
693
+ * Generate HowTo Schema
694
+ */
695
+ declare function generateHowToSchema(data: {
696
+ name: string;
697
+ description?: string;
698
+ image?: string;
699
+ totalTime?: string;
700
+ estimatedCost?: {
701
+ currency: string;
702
+ value: number;
703
+ };
704
+ supply?: string[];
705
+ tool?: string[];
706
+ steps: Array<{
707
+ name?: string;
708
+ text: string;
709
+ image?: string;
710
+ url?: string;
711
+ }> | string[];
712
+ }): {
713
+ "@context": string;
714
+ "@type": string;
715
+ name: string;
716
+ description: string | undefined;
717
+ image: string | undefined;
718
+ totalTime: string | undefined;
719
+ estimatedCost: {
720
+ "@type": string;
721
+ currency: string;
722
+ value: number;
723
+ } | undefined;
724
+ supply: {
725
+ "@type": string;
726
+ name: string;
727
+ }[] | undefined;
728
+ tool: {
729
+ "@type": string;
730
+ name: string;
731
+ }[] | undefined;
732
+ step: ({
733
+ "@type": string;
734
+ position: number;
735
+ name: string | undefined;
736
+ text: string;
737
+ image: string | undefined;
738
+ url: string | undefined;
739
+ } | {
740
+ "@type": string;
741
+ position: number;
742
+ text: string;
743
+ })[];
744
+ };
745
+ /**
746
+ * Generate Recipe Schema
747
+ */
748
+ declare function generateRecipeSchema(data: {
749
+ name: string;
750
+ description: string;
751
+ image: string | string[];
752
+ author: string;
753
+ publishedDate?: string;
754
+ prepTime?: string;
755
+ cookTime?: string;
756
+ totalTime?: string;
757
+ recipeYield?: string;
758
+ recipeCategory?: string;
759
+ recipeCuisine?: string;
760
+ ingredients: string[];
761
+ instructions: Array<{
762
+ name?: string;
763
+ text: string;
764
+ image?: string;
765
+ }>;
766
+ rating?: number;
767
+ reviewCount?: number;
768
+ }): {
769
+ "@context": string;
770
+ "@type": string;
771
+ name: string;
772
+ description: string;
773
+ image: string | string[];
774
+ author: {
775
+ "@type": string;
776
+ name: string;
777
+ };
778
+ datePublished: string | undefined;
779
+ prepTime: string | undefined;
780
+ cookTime: string | undefined;
781
+ totalTime: string | undefined;
782
+ recipeYield: string | undefined;
783
+ recipeCategory: string | undefined;
784
+ recipeCuisine: string | undefined;
785
+ recipeIngredient: string[];
786
+ recipeInstructions: {
787
+ "@type": string;
788
+ name: string | undefined;
789
+ text: string;
790
+ image: string | undefined;
791
+ }[];
792
+ aggregateRating: {
793
+ "@type": string;
794
+ ratingValue: number;
795
+ reviewCount: number;
796
+ } | undefined;
797
+ };
798
+ /**
799
+ * Generate JobPosting Schema
800
+ */
801
+ declare function generateJobPostingSchema(data: {
802
+ title: string;
803
+ description: string;
804
+ datePosted: string;
805
+ validThrough?: string;
806
+ employmentType?: string | string[];
807
+ hiringOrganization: {
808
+ name: string;
809
+ sameAs?: string;
810
+ logo?: string;
811
+ };
812
+ jobLocation: {
813
+ streetAddress: string;
814
+ addressLocality: string;
815
+ addressRegion?: string;
816
+ postalCode?: string;
817
+ addressCountry: string;
818
+ };
819
+ remote?: boolean;
820
+ baseSalary?: {
821
+ currency: string;
822
+ value: number | {
823
+ minValue: number;
824
+ maxValue: number;
825
+ };
826
+ unitText?: string;
827
+ };
828
+ }): {
829
+ "@context": string;
830
+ "@type": string;
831
+ title: string;
832
+ description: string;
833
+ datePosted: string;
834
+ validThrough: string | undefined;
835
+ employmentType: string | string[] | undefined;
836
+ jobLocationType: string | undefined;
837
+ hiringOrganization: {
838
+ "@type": string;
839
+ name: string;
840
+ sameAs: string | undefined;
841
+ logo: string | undefined;
842
+ };
843
+ jobLocation: {
844
+ "@type": string;
845
+ address: {
846
+ "@type": string;
847
+ streetAddress: string;
848
+ addressLocality: string;
849
+ addressRegion: string | undefined;
850
+ postalCode: string | undefined;
851
+ addressCountry: string;
852
+ };
853
+ };
854
+ baseSalary: {
855
+ "@type": string;
856
+ currency: string;
857
+ value: {
858
+ "@type": string;
859
+ value: number;
860
+ unitText: string;
861
+ minValue?: undefined;
862
+ maxValue?: undefined;
863
+ } | {
864
+ "@type": string;
865
+ minValue: number;
866
+ maxValue: number;
867
+ unitText: string;
868
+ value?: undefined;
869
+ };
870
+ } | undefined;
871
+ };
872
+
873
+ /**
874
+ * Converts SEOData and SiteConfig to a Next.js compatible Metadata object.
875
+ * This is designed to be used in Server Components (App Router).
876
+ *
877
+ * @example
878
+ * // In page.tsx (Server Component - no 'use client')
879
+ * import { toNextMetadata } from '@masters-ws/react-seo/core';
880
+ *
881
+ * export async function generateMetadata({ params }) {
882
+ * const post = await getPost(params.id);
883
+ * return toNextMetadata({ title: post.title, ... }, siteConfig);
884
+ * }
885
+ */
886
+ declare function toNextMetadata(props: SEOData, config: SiteConfig): any;
887
+ /**
888
+ * Generates pagination links for category/tag pages.
889
+ * Returns { prev, next, canonical } URLs.
890
+ */
891
+ declare function generatePaginationLinks(baseUrl: string, currentPage: number, totalPages: number): {
892
+ next: string | undefined;
893
+ prev: string | undefined;
894
+ canonical: string;
895
+ };
896
+ /**
897
+ * Generates title with page number suffix for paginated pages.
898
+ */
899
+ declare function generatePaginatedTitle(title: string, page: number, suffix?: string): string;
900
+
901
+ /**
902
+ * Deep-cleans a schema object by removing all undefined and null values.
903
+ * This prevents invalid JSON-LD output like {"sku": undefined}.
904
+ *
905
+ * @example
906
+ * const schema = cleanSchema({
907
+ * "@type": "Product",
908
+ * "name": "Shirt",
909
+ * "sku": undefined, // ← removed
910
+ * "brand": null, // ← removed
911
+ * "offers": {
912
+ * "@type": "Offer",
913
+ * "price": 29.99,
914
+ * "seller": undefined // ← removed
915
+ * }
916
+ * });
917
+ */
918
+ declare function cleanSchema<T extends Record<string, any>>(obj: T): T;
919
+ /**
920
+ * SEO validation warnings for development mode.
921
+ * Only logs in development (process.env.NODE_ENV !== 'production').
922
+ *
923
+ * @example
924
+ * validateSEO('Product', {
925
+ * name: product.name,
926
+ * price: product.price,
927
+ * }, ['name', 'price', 'image']);
928
+ */
929
+ declare function validateSEO(schemaType: string, data: Record<string, any>, requiredFields: string[]): string[];
930
+
931
+ /**
932
+ * Server-safe JSON-LD component for Next.js App Router.
933
+ * Renders schema markup as <script type="application/ld+json"> in server-rendered HTML.
934
+ *
935
+ * Unlike Helmet-based components, this works in Server Components,
936
+ * so Google sees the schemas on first crawl without JavaScript execution.
937
+ *
938
+ * @example
939
+ * // Single schema
940
+ * <JsonLd schema={productSchema} />
941
+ *
942
+ * // Multiple schemas (separate <script> tags)
943
+ * <JsonLd schema={[productSchema, breadcrumbSchema]} />
944
+ *
945
+ * // Multiple schemas using @graph pattern (single <script> tag — recommended)
946
+ * <JsonLd schema={[productSchema, breadcrumbSchema]} graph />
947
+ */
948
+ interface JsonLdProps {
949
+ /** A single schema object or an array of schema objects */
950
+ schema: Record<string, any> | Record<string, any>[];
951
+ /**
952
+ * If true, combines all schemas into a single <script> using the @graph pattern.
953
+ * This is Google's recommended approach for pages with multiple related schemas.
954
+ *
955
+ * When graph is true, individual @context properties are removed from each schema
956
+ * and a single @context is added at the top level.
957
+ *
958
+ * @default false
959
+ */
960
+ graph?: boolean;
961
+ }
962
+ declare function JsonLd({ schema, graph }: JsonLdProps): react_jsx_runtime.JSX.Element;
963
+
964
+ /**
965
+ * Product metadata input for convenience helper
966
+ */
967
+ interface ProductMetadataInput {
968
+ name: string;
969
+ description: string;
970
+ image?: string | string[];
971
+ sku?: string;
972
+ gtin?: string;
973
+ mpn?: string;
974
+ brand?: string;
975
+ price?: number;
976
+ currency?: string;
977
+ availability?: string;
978
+ rating?: number;
979
+ reviewCount?: number;
980
+ url: string;
981
+ condition?: 'NewCondition' | 'UsedCondition' | 'RefurbishedCondition' | 'DamagedCondition';
982
+ metaTitle?: string;
983
+ metaDescription?: string;
984
+ canonical?: string;
985
+ noindex?: boolean;
986
+ breadcrumbs?: Array<{
987
+ name: string;
988
+ item: string;
989
+ }>;
990
+ category?: string;
991
+ ogImage?: string;
992
+ ogImageWidth?: number;
993
+ ogImageHeight?: number;
994
+ reviews?: ProductReview[];
995
+ returnPolicy?: MerchantReturnPolicy;
996
+ shipping?: ShippingDetails;
997
+ variants?: ProductVariant[];
998
+ seller?: {
999
+ name: string;
1000
+ url?: string;
1001
+ };
1002
+ }
1003
+ /**
1004
+ * Result from generateProductMetadata
1005
+ */
1006
+ interface ProductMetadataResult {
1007
+ /** Next.js Metadata object - use as return from generateMetadata() */
1008
+ metadata: any;
1009
+ /** All JSON-LD schemas for the product page */
1010
+ schemas: Record<string, any>[];
1011
+ /** Individual schemas for granular control */
1012
+ productSchema: Record<string, any>;
1013
+ breadcrumbSchema: Record<string, any>;
1014
+ organizationSchema: Record<string, any>;
1015
+ websiteSchema: Record<string, any>;
1016
+ }
1017
+ /**
1018
+ * All-in-one helper for product pages in Next.js App Router.
1019
+ * Generates both the Metadata object AND all JSON-LD schemas in one call.
1020
+ *
1021
+ * @example
1022
+ * ```tsx
1023
+ * // app/products/[slug]/page.tsx (Server Component)
1024
+ * import { generateProductMetadata, JsonLd } from '@masters-ws/react-seo/core';
1025
+ *
1026
+ * const siteConfig = { name: 'My Store', url: 'https://store.com', ... };
1027
+ *
1028
+ * export async function generateMetadata({ params }) {
1029
+ * const product = await fetchProduct(params.slug);
1030
+ * const { metadata } = generateProductMetadata(product, siteConfig);
1031
+ * return metadata;
1032
+ * }
1033
+ *
1034
+ * export default async function ProductPage({ params }) {
1035
+ * const product = await fetchProduct(params.slug);
1036
+ * const { schemas } = generateProductMetadata(product, siteConfig);
1037
+ * return (
1038
+ * <>
1039
+ * <JsonLd schema={schemas} graph />
1040
+ * <ProductDetailClient product={product} />
1041
+ * </>
1042
+ * );
1043
+ * }
1044
+ * ```
1045
+ */
1046
+ declare function generateProductMetadata(product: ProductMetadataInput, config: SiteConfig): ProductMetadataResult;
1047
+
1048
+ /**
1049
+ * Article metadata input for convenience helper
1050
+ */
1051
+ interface ArticleMetadataInput {
1052
+ title: string;
1053
+ description: string;
1054
+ image?: string | string[];
1055
+ publishedTime: string;
1056
+ modifiedTime?: string;
1057
+ author?: {
1058
+ name: string;
1059
+ url?: string;
1060
+ image?: string;
1061
+ };
1062
+ url: string;
1063
+ category?: string;
1064
+ tags?: string[];
1065
+ readingTime?: number;
1066
+ wordCount?: number;
1067
+ metaTitle?: string;
1068
+ metaDescription?: string;
1069
+ canonical?: string;
1070
+ noindex?: boolean;
1071
+ breadcrumbs?: Array<{
1072
+ name: string;
1073
+ item: string;
1074
+ }>;
1075
+ ogImage?: string;
1076
+ ogImageWidth?: number;
1077
+ ogImageHeight?: number;
1078
+ }
1079
+ /**
1080
+ * Result from generateArticleMetadata
1081
+ */
1082
+ interface ArticleMetadataResult {
1083
+ /** Next.js Metadata object - use as return from generateMetadata() */
1084
+ metadata: any;
1085
+ /** All JSON-LD schemas for the article page */
1086
+ schemas: Record<string, any>[];
1087
+ /** Individual schemas for granular control */
1088
+ articleSchema: Record<string, any>;
1089
+ breadcrumbSchema: Record<string, any>;
1090
+ organizationSchema: Record<string, any>;
1091
+ websiteSchema: Record<string, any>;
1092
+ }
1093
+ /**
1094
+ * All-in-one helper for article pages in Next.js App Router.
1095
+ * Generates both the Metadata object AND all JSON-LD schemas in one call.
1096
+ *
1097
+ * @example
1098
+ * ```tsx
1099
+ * // app/news/[slug]/page.tsx (Server Component)
1100
+ * import { generateArticleMetadata, JsonLd } from '@masters-ws/react-seo/core';
1101
+ *
1102
+ * export async function generateMetadata({ params }) {
1103
+ * const article = await fetchArticle(params.slug);
1104
+ * const { metadata } = generateArticleMetadata(article, siteConfig);
1105
+ * return metadata;
1106
+ * }
1107
+ *
1108
+ * export default async function ArticlePage({ params }) {
1109
+ * const article = await fetchArticle(params.slug);
1110
+ * const { schemas } = generateArticleMetadata(article, siteConfig);
1111
+ * return (
1112
+ * <>
1113
+ * <JsonLd schema={schemas} graph />
1114
+ * <article>...</article>
1115
+ * </>
1116
+ * );
1117
+ * }
1118
+ * ```
1119
+ */
1120
+ declare function generateArticleMetadata(article: ArticleMetadataInput, config: SiteConfig): ArticleMetadataResult;
1121
+
1122
+ /**
1123
+ * Category/Collection metadata input
1124
+ */
1125
+ interface CategoryMetadataInput {
1126
+ name: string;
1127
+ description: string;
1128
+ image?: string;
1129
+ url: string;
1130
+ page?: number;
1131
+ totalPages?: number;
1132
+ metaTitle?: string;
1133
+ metaDescription?: string;
1134
+ noindex?: boolean;
1135
+ breadcrumbs?: Array<{
1136
+ name: string;
1137
+ item: string;
1138
+ }>;
1139
+ parentCategory?: string;
1140
+ items?: Array<{
1141
+ url: string;
1142
+ name: string;
1143
+ image?: string;
1144
+ position?: number;
1145
+ }>;
1146
+ pageSuffix?: string;
1147
+ }
1148
+ /**
1149
+ * Result from generateCategoryMetadata
1150
+ */
1151
+ interface CategoryMetadataResult {
1152
+ /** Next.js Metadata object */
1153
+ metadata: any;
1154
+ /** All JSON-LD schemas */
1155
+ schemas: Record<string, any>[];
1156
+ /** Individual schemas */
1157
+ collectionPageSchema: Record<string, any>;
1158
+ breadcrumbSchema: Record<string, any>;
1159
+ organizationSchema: Record<string, any>;
1160
+ itemListSchema?: Record<string, any>;
1161
+ }
1162
+ /**
1163
+ * All-in-one helper for category/collection pages in Next.js App Router.
1164
+ * Handles pagination, ItemList schema, and CollectionPage schema.
1165
+ *
1166
+ * @example
1167
+ * ```tsx
1168
+ * // app/categories/[slug]/page.tsx (Server Component)
1169
+ * import { generateCategoryMetadata, JsonLd } from '@masters-ws/react-seo/core';
1170
+ *
1171
+ * export async function generateMetadata({ params, searchParams }) {
1172
+ * const page = Number(searchParams.page) || 1;
1173
+ * const category = await fetchCategory(params.slug);
1174
+ * const { metadata } = generateCategoryMetadata({
1175
+ * name: category.name,
1176
+ * description: category.description,
1177
+ * url: `https://store.com/categories/${params.slug}`,
1178
+ * page,
1179
+ * totalPages: category.totalPages,
1180
+ * items: category.products.map((p, i) => ({
1181
+ * name: p.name,
1182
+ * url: `https://store.com/products/${p.slug}`,
1183
+ * image: p.image,
1184
+ * position: i + 1,
1185
+ * })),
1186
+ * }, siteConfig);
1187
+ * return metadata;
1188
+ * }
1189
+ * ```
1190
+ */
1191
+ declare function generateCategoryMetadata(category: CategoryMetadataInput, config: SiteConfig): CategoryMetadataResult;
1192
+
1193
+ /**
1194
+ * Homepage metadata input
1195
+ */
1196
+ interface HomepageMetadataInput {
1197
+ title?: string;
1198
+ description?: string;
1199
+ image?: string;
1200
+ canonical?: string;
1201
+ ogImage?: string;
1202
+ ogImageWidth?: number;
1203
+ ogImageHeight?: number;
1204
+ localBusiness?: {
1205
+ name: string;
1206
+ description: string;
1207
+ image?: string;
1208
+ telephone?: string;
1209
+ address: {
1210
+ street: string;
1211
+ city: string;
1212
+ region?: string;
1213
+ postalCode?: string;
1214
+ country: string;
1215
+ };
1216
+ geo?: {
1217
+ lat: number;
1218
+ lng: number;
1219
+ };
1220
+ openingHours?: string[];
1221
+ priceRange?: string;
1222
+ };
1223
+ socialLinks?: string[];
1224
+ }
1225
+ /**
1226
+ * Result from generateHomepageMetadata
1227
+ */
1228
+ interface HomepageMetadataResult {
1229
+ /** Next.js Metadata object */
1230
+ metadata: any;
1231
+ /** All JSON-LD schemas */
1232
+ schemas: Record<string, any>[];
1233
+ /** Individual schemas */
1234
+ webPageSchema: Record<string, any>;
1235
+ organizationSchema: Record<string, any>;
1236
+ websiteSchema: Record<string, any>;
1237
+ localBusinessSchema?: Record<string, any>;
1238
+ }
1239
+ /**
1240
+ * All-in-one helper for homepage / landing pages in Next.js App Router.
1241
+ *
1242
+ * @example
1243
+ * ```tsx
1244
+ * // app/page.tsx (Homepage — Server Component)
1245
+ * import { generateHomepageMetadata, JsonLd } from '@masters-ws/react-seo/core';
1246
+ *
1247
+ * const siteConfig = {
1248
+ * name: "My Company",
1249
+ * url: "https://mycompany.com",
1250
+ * description: "We build amazing things",
1251
+ * logo: "https://mycompany.com/logo.png",
1252
+ * };
1253
+ *
1254
+ * export async function generateMetadata() {
1255
+ * const { metadata } = generateHomepageMetadata({}, siteConfig);
1256
+ * return metadata;
1257
+ * }
1258
+ *
1259
+ * export default function HomePage() {
1260
+ * const { schemas } = generateHomepageMetadata({}, siteConfig);
1261
+ * return (
1262
+ * <>
1263
+ * <JsonLd schema={schemas} graph />
1264
+ * <main>...</main>
1265
+ * </>
1266
+ * );
1267
+ * }
1268
+ * ```
1269
+ */
1270
+ declare function generateHomepageMetadata(input: HomepageMetadataInput, config: SiteConfig): HomepageMetadataResult;
1271
+
1272
+ export { type ArticleMetadataInput as A, type BreadcrumbItem as B, type CategoryMetadataInput as C, generatePaginationLinks as D, generatePodcastEpisodeSchema as E, generatePodcastSchema as F, generateProductMetadata as G, type HomepageMetadataInput as H, generateProductSchema as I, JsonLd as J, generateRecipeSchema as K, generateSoftwareSchema as L, type MerchantReturnPolicy as M, generateVideoSchema as N, generateWebPageSchema as O, type ProductMetadataInput as P, generateWebSiteSchema as Q, toNextMetadata as R, type SiteConfig as S, validateSEO as T, type SEOData as a, type ArticleMetadataResult as b, type CategoryMetadataResult as c, type HomepageMetadataResult as d, type JsonLdProps as e, type ProductMetadataResult as f, type ProductReview as g, type ProductVariant as h, type ShippingDetails as i, cleanSchema as j, generateArticleMetadata as k, generateArticleSchema as l, generateBookSchema as m, generateBreadcrumbSchema as n, generateCategoryMetadata as o, generateCollectionPageSchema as p, generateEventSchema as q, generateFAQSchema as r, generateHomepageMetadata as s, generateHowToSchema as t, generateItemListSchema as u, generateJobPostingSchema as v, generateLocalBusinessSchema as w, generateMovieSchema as x, generateOrganizationSchema as y, generatePaginatedTitle as z };