@coherent.js/seo 1.0.0-beta.3 → 1.0.0-beta.5
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 +681 -0
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
# @coherent.js/seo
|
|
2
|
+
|
|
3
|
+
SEO optimization tools for Coherent.js applications - Meta tags, structured data, and search engine optimization utilities.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @coherent.js/seo
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @coherent.js/seo
|
|
11
|
+
# or
|
|
12
|
+
yarn add @coherent.js/seo
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
The `@coherent.js/seo` package provides comprehensive SEO tools for Coherent.js applications, including:
|
|
18
|
+
|
|
19
|
+
- Dynamic meta tag management
|
|
20
|
+
- Open Graph and Twitter Card support
|
|
21
|
+
- JSON-LD structured data generation
|
|
22
|
+
- Sitemap generation
|
|
23
|
+
- Robots.txt management
|
|
24
|
+
- SEO-friendly URL generation
|
|
25
|
+
- Canonical URL support
|
|
26
|
+
- Internationalization SEO
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import { createSEOHooks } from '@coherent.js/seo';
|
|
32
|
+
|
|
33
|
+
// Create SEO hooks
|
|
34
|
+
const seo = createSEOHooks();
|
|
35
|
+
|
|
36
|
+
// Add to your Coherent.js component
|
|
37
|
+
function BlogPost({ post }) {
|
|
38
|
+
// Set SEO metadata
|
|
39
|
+
seo.setMetadata({
|
|
40
|
+
title: `${post.title} - My Blog`,
|
|
41
|
+
description: post.excerpt,
|
|
42
|
+
keywords: post.tags,
|
|
43
|
+
author: post.author.name,
|
|
44
|
+
publishedTime: post.publishedAt,
|
|
45
|
+
image: post.featuredImage
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
div: {
|
|
50
|
+
children: [
|
|
51
|
+
{ h1: { text: post.title } },
|
|
52
|
+
{ div: {
|
|
53
|
+
innerHTML: post.content,
|
|
54
|
+
className: 'post-content'
|
|
55
|
+
}}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Features
|
|
63
|
+
|
|
64
|
+
### Dynamic Meta Tags
|
|
65
|
+
|
|
66
|
+
Automatically generate meta tags for search engines:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { createSEOHooks } from '@coherent.js/seo';
|
|
70
|
+
|
|
71
|
+
const seo = createSEOHooks();
|
|
72
|
+
|
|
73
|
+
function ProductPage({ product }) {
|
|
74
|
+
seo.setMetadata({
|
|
75
|
+
title: product.name,
|
|
76
|
+
description: product.description,
|
|
77
|
+
keywords: [product.category, product.brand, ...product.tags],
|
|
78
|
+
image: product.images[0],
|
|
79
|
+
locale: 'en_US',
|
|
80
|
+
type: 'product',
|
|
81
|
+
url: `https://example.com/products/${product.slug}`
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
div: {
|
|
86
|
+
children: [
|
|
87
|
+
{ h1: { text: product.name } },
|
|
88
|
+
{ p: { text: product.description } },
|
|
89
|
+
{ img: { src: product.images[0], alt: product.name } }
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Open Graph Support
|
|
97
|
+
|
|
98
|
+
Generate Open Graph meta tags for social sharing:
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
seo.setMetadata({
|
|
102
|
+
title: 'Awesome Product',
|
|
103
|
+
description: 'This product will change your life',
|
|
104
|
+
image: 'https://example.com/product-image.jpg',
|
|
105
|
+
type: 'product.item',
|
|
106
|
+
siteName: 'My E-commerce Store',
|
|
107
|
+
locale: 'en_US',
|
|
108
|
+
|
|
109
|
+
// Open Graph specific
|
|
110
|
+
og: {
|
|
111
|
+
price: {
|
|
112
|
+
amount: '29.99',
|
|
113
|
+
currency: 'USD'
|
|
114
|
+
},
|
|
115
|
+
availability: 'instock'
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Twitter Card Support
|
|
121
|
+
|
|
122
|
+
Generate Twitter Card meta tags:
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
seo.setMetadata({
|
|
126
|
+
title: 'Check out this awesome content!',
|
|
127
|
+
description: 'You won\'t believe what happens next',
|
|
128
|
+
image: 'https://example.com/twitter-card-image.jpg',
|
|
129
|
+
|
|
130
|
+
// Twitter specific
|
|
131
|
+
twitter: {
|
|
132
|
+
card: 'summary_large_image',
|
|
133
|
+
site: '@mywebsite',
|
|
134
|
+
creator: '@author'
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### JSON-LD Structured Data
|
|
140
|
+
|
|
141
|
+
Generate structured data for rich search results:
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
import { createArticleSchema, createBreadcrumbSchema } from '@coherent.js/seo';
|
|
145
|
+
|
|
146
|
+
function BlogPost({ post, breadcrumbs }) {
|
|
147
|
+
// Add article structured data
|
|
148
|
+
seo.addSchema(createArticleSchema({
|
|
149
|
+
headline: post.title,
|
|
150
|
+
description: post.excerpt,
|
|
151
|
+
author: {
|
|
152
|
+
name: post.author.name,
|
|
153
|
+
url: `/authors/${post.author.slug}`
|
|
154
|
+
},
|
|
155
|
+
datePublished: post.publishedAt,
|
|
156
|
+
dateModified: post.updatedAt,
|
|
157
|
+
image: post.featuredImage,
|
|
158
|
+
keywords: post.tags,
|
|
159
|
+
articleBody: post.content
|
|
160
|
+
}));
|
|
161
|
+
|
|
162
|
+
// Add breadcrumb schema
|
|
163
|
+
seo.addSchema(createBreadcrumbSchema(breadcrumbs));
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
div: {
|
|
167
|
+
children: [
|
|
168
|
+
{ h1: { text: post.title } },
|
|
169
|
+
{ div: { innerHTML: post.content } }
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## SEO Hooks
|
|
177
|
+
|
|
178
|
+
### Basic Usage
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
import { createSEOHooks } from '@coherent.js/seo';
|
|
182
|
+
|
|
183
|
+
const seo = createSEOHooks({
|
|
184
|
+
defaultTitle: 'My Website',
|
|
185
|
+
defaultDescription: 'Welcome to my awesome website',
|
|
186
|
+
defaultImage: '/default-social-image.jpg',
|
|
187
|
+
siteUrl: 'https://example.com'
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
function Page({ title, description }) {
|
|
191
|
+
seo.setMetadata({
|
|
192
|
+
title: title,
|
|
193
|
+
description: description
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
div: {
|
|
198
|
+
children: [
|
|
199
|
+
{ h1: { text: title } },
|
|
200
|
+
{ p: { text: description } }
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Advanced Configuration
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
const seo = createSEOHooks({
|
|
211
|
+
// Default metadata
|
|
212
|
+
defaultTitle: 'My Website',
|
|
213
|
+
defaultDescription: 'Default description',
|
|
214
|
+
defaultImage: '/images/default.jpg',
|
|
215
|
+
siteUrl: 'https://example.com',
|
|
216
|
+
|
|
217
|
+
// SEO settings
|
|
218
|
+
titleTemplate: '%s | My Website', // "Page Title | My Website"
|
|
219
|
+
truncateTitle: 60, // Truncate titles to 60 chars
|
|
220
|
+
truncateDescription: 160, // Truncate descriptions to 160 chars
|
|
221
|
+
|
|
222
|
+
// Social media
|
|
223
|
+
social: {
|
|
224
|
+
twitter: '@mytwitterhandle',
|
|
225
|
+
facebook: 'myfacebookpage',
|
|
226
|
+
linkedin: 'mylinkedincompany'
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
// Default Open Graph
|
|
230
|
+
og: {
|
|
231
|
+
type: 'website',
|
|
232
|
+
siteName: 'My Website'
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Sitemap Generation
|
|
238
|
+
|
|
239
|
+
Generate dynamic sitemaps:
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
import { createSitemap } from '@coherent.js/seo';
|
|
243
|
+
|
|
244
|
+
const sitemap = createSitemap({
|
|
245
|
+
siteUrl: 'https://example.com',
|
|
246
|
+
changefreq: 'daily',
|
|
247
|
+
priority: 0.7,
|
|
248
|
+
lastmod: new Date()
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Add URLs to sitemap
|
|
252
|
+
sitemap.add({
|
|
253
|
+
url: '/',
|
|
254
|
+
changefreq: 'daily',
|
|
255
|
+
priority: 1.0
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
sitemap.add({
|
|
259
|
+
url: '/about',
|
|
260
|
+
changefreq: 'monthly',
|
|
261
|
+
priority: 0.8
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
sitemap.add({
|
|
265
|
+
url: '/blog',
|
|
266
|
+
changefreq: 'weekly',
|
|
267
|
+
priority: 0.9
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Generate sitemap XML
|
|
271
|
+
const sitemapXml = sitemap.toXML();
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Robots.txt Management
|
|
275
|
+
|
|
276
|
+
Generate robots.txt files:
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
import { createRobotsTxt } from '@coherent.js/seo';
|
|
280
|
+
|
|
281
|
+
const robots = createRobotsTxt({
|
|
282
|
+
userAgent: '*', // Default user agent
|
|
283
|
+
allow: ['/'], // Allow all paths
|
|
284
|
+
disallow: ['/admin', '/private'], // Disallow specific paths
|
|
285
|
+
sitemap: 'https://example.com/sitemap.xml',
|
|
286
|
+
host: 'https://example.com'
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Add custom rules
|
|
290
|
+
robots.addRule({
|
|
291
|
+
userAgent: 'Googlebot',
|
|
292
|
+
allow: ['/'],
|
|
293
|
+
crawlDelay: 10
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Generate robots.txt content
|
|
297
|
+
const robotsTxt = robots.toString();
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Canonical URLs
|
|
301
|
+
|
|
302
|
+
Manage canonical URLs to prevent duplicate content issues:
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
function ProductPage({ product, queryParams }) {
|
|
306
|
+
// Set canonical URL without tracking parameters
|
|
307
|
+
const canonicalUrl = `https://example.com/products/${product.slug}`;
|
|
308
|
+
|
|
309
|
+
seo.setCanonical(canonicalUrl);
|
|
310
|
+
|
|
311
|
+
// Add alternate URLs for internationalization
|
|
312
|
+
seo.addAlternate({
|
|
313
|
+
href: `https://example.com/en/products/${product.slug}`,
|
|
314
|
+
hreflang: 'en'
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
seo.addAlternate({
|
|
318
|
+
href: `https://example.com/es/products/${product.slug}`,
|
|
319
|
+
hreflang: 'es'
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
div: {
|
|
324
|
+
children: [
|
|
325
|
+
{ h1: { text: product.name } },
|
|
326
|
+
{ p: { text: product.description } }
|
|
327
|
+
]
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Internationalization SEO
|
|
334
|
+
|
|
335
|
+
Support for multilingual SEO:
|
|
336
|
+
|
|
337
|
+
```javascript
|
|
338
|
+
function MultilingualPage({ content, language, translations }) {
|
|
339
|
+
// Set language
|
|
340
|
+
seo.setLanguage(language);
|
|
341
|
+
|
|
342
|
+
// Add alternate language versions
|
|
343
|
+
Object.entries(translations).forEach(([lang, url]) => {
|
|
344
|
+
seo.addAlternate({
|
|
345
|
+
href: url,
|
|
346
|
+
hreflang: lang
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Set direction for RTL languages
|
|
351
|
+
seo.setDirection(language === 'ar' || language === 'he' ? 'rtl' : 'ltr');
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
div: {
|
|
355
|
+
lang: language,
|
|
356
|
+
children: [
|
|
357
|
+
{ h1: { text: content.title } },
|
|
358
|
+
{ div: { innerHTML: content.body } }
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## API Reference
|
|
366
|
+
|
|
367
|
+
### createSEOHooks(options)
|
|
368
|
+
|
|
369
|
+
Create SEO hooks for metadata management.
|
|
370
|
+
|
|
371
|
+
**Parameters:**
|
|
372
|
+
- `options.defaultTitle` - Default page title
|
|
373
|
+
- `options.defaultDescription` - Default page description
|
|
374
|
+
- `options.defaultImage` - Default social image
|
|
375
|
+
- `options.siteUrl` - Base site URL
|
|
376
|
+
- `options.titleTemplate` - Title template string
|
|
377
|
+
- `options.truncateTitle` - Title character limit
|
|
378
|
+
- `options.truncateDescription` - Description character limit
|
|
379
|
+
|
|
380
|
+
**Returns:** SEO hooks object with methods
|
|
381
|
+
|
|
382
|
+
### SEO Hooks Methods
|
|
383
|
+
|
|
384
|
+
- `seo.setMetadata(metadata)` - Set page metadata
|
|
385
|
+
- `seo.setTitle(title)` - Set page title
|
|
386
|
+
- `seo.setDescription(description)` - Set page description
|
|
387
|
+
- `seo.setCanonical(url)` - Set canonical URL
|
|
388
|
+
- `seo.addAlternate(options)` - Add alternate language URL
|
|
389
|
+
- `seo.addSchema(schema)` - Add JSON-LD schema
|
|
390
|
+
- `seo.setLanguage(lang)` - Set page language
|
|
391
|
+
- `seo.setDirection(dir)` - Set text direction
|
|
392
|
+
|
|
393
|
+
### createSitemap(options)
|
|
394
|
+
|
|
395
|
+
Create a sitemap generator.
|
|
396
|
+
|
|
397
|
+
**Parameters:**
|
|
398
|
+
- `options.siteUrl` - Base site URL
|
|
399
|
+
- `options.changefreq` - Default change frequency
|
|
400
|
+
- `options.priority` - Default priority
|
|
401
|
+
- `options.lastmod` - Default last modified date
|
|
402
|
+
|
|
403
|
+
**Returns:** Sitemap generator object
|
|
404
|
+
|
|
405
|
+
### createRobotsTxt(options)
|
|
406
|
+
|
|
407
|
+
Create a robots.txt generator.
|
|
408
|
+
|
|
409
|
+
**Parameters:**
|
|
410
|
+
- `options.userAgent` - Default user agent
|
|
411
|
+
- `options.allow` - Allowed paths
|
|
412
|
+
- `options.disallow` - Disallowed paths
|
|
413
|
+
- `options.sitemap` - Sitemap URL
|
|
414
|
+
- `options.host` - Host URL
|
|
415
|
+
|
|
416
|
+
**Returns:** Robots.txt generator object
|
|
417
|
+
|
|
418
|
+
## Schema Generators
|
|
419
|
+
|
|
420
|
+
### createArticleSchema(options)
|
|
421
|
+
|
|
422
|
+
Generate Article JSON-LD schema.
|
|
423
|
+
|
|
424
|
+
**Parameters:**
|
|
425
|
+
- `options.headline` - Article headline
|
|
426
|
+
- `options.description` - Article description
|
|
427
|
+
- `options.author` - Author information
|
|
428
|
+
- `options.datePublished` - Publication date
|
|
429
|
+
- `options.dateModified` - Modification date
|
|
430
|
+
- `options.image` - Featured image
|
|
431
|
+
- `options.keywords` - Article keywords
|
|
432
|
+
- `options.articleBody` - Article content
|
|
433
|
+
|
|
434
|
+
### createBreadcrumbSchema(breadcrumbs)
|
|
435
|
+
|
|
436
|
+
Generate Breadcrumb JSON-LD schema.
|
|
437
|
+
|
|
438
|
+
**Parameters:**
|
|
439
|
+
- `breadcrumbs` - Array of breadcrumb objects with name and url
|
|
440
|
+
|
|
441
|
+
### createProductSchema(options)
|
|
442
|
+
|
|
443
|
+
Generate Product JSON-LD schema.
|
|
444
|
+
|
|
445
|
+
**Parameters:**
|
|
446
|
+
- `options.name` - Product name
|
|
447
|
+
- `options.description` - Product description
|
|
448
|
+
- `options.image` - Product images
|
|
449
|
+
- `options.offers` - Product offers/pricing
|
|
450
|
+
- `options.brand` - Product brand
|
|
451
|
+
- `options.category` - Product category
|
|
452
|
+
- `options.sku` - Product SKU
|
|
453
|
+
|
|
454
|
+
## Examples
|
|
455
|
+
|
|
456
|
+
### Blog with Full SEO
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
import {
|
|
460
|
+
createSEOHooks,
|
|
461
|
+
createArticleSchema,
|
|
462
|
+
createBreadcrumbSchema
|
|
463
|
+
} from '@coherent.js/seo';
|
|
464
|
+
|
|
465
|
+
const seo = createSEOHooks({
|
|
466
|
+
siteUrl: 'https://myblog.com',
|
|
467
|
+
defaultTitle: 'My Blog',
|
|
468
|
+
titleTemplate: '%s | My Blog'
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
function BlogPost({ post }) {
|
|
472
|
+
// Set basic metadata
|
|
473
|
+
seo.setMetadata({
|
|
474
|
+
title: post.title,
|
|
475
|
+
description: post.excerpt,
|
|
476
|
+
image: post.featuredImage,
|
|
477
|
+
publishedTime: post.publishedAt,
|
|
478
|
+
modifiedTime: post.updatedAt,
|
|
479
|
+
type: 'article',
|
|
480
|
+
author: post.author.name,
|
|
481
|
+
tags: post.tags
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// Add structured data
|
|
485
|
+
seo.addSchema(createArticleSchema({
|
|
486
|
+
headline: post.title,
|
|
487
|
+
description: post.excerpt,
|
|
488
|
+
author: {
|
|
489
|
+
name: post.author.name,
|
|
490
|
+
url: `/authors/${post.author.slug}`
|
|
491
|
+
},
|
|
492
|
+
datePublished: post.publishedAt,
|
|
493
|
+
dateModified: post.updatedAt,
|
|
494
|
+
image: post.featuredImage,
|
|
495
|
+
keywords: post.tags,
|
|
496
|
+
articleBody: post.content
|
|
497
|
+
}));
|
|
498
|
+
|
|
499
|
+
// Add breadcrumbs
|
|
500
|
+
seo.addSchema(createBreadcrumbSchema([
|
|
501
|
+
{ name: 'Home', url: '/' },
|
|
502
|
+
{ name: 'Blog', url: '/blog' },
|
|
503
|
+
{ name: post.title, url: `/blog/${post.slug}` }
|
|
504
|
+
]));
|
|
505
|
+
|
|
506
|
+
// Set canonical URL
|
|
507
|
+
seo.setCanonical(`https://myblog.com/blog/${post.slug}`);
|
|
508
|
+
|
|
509
|
+
return {
|
|
510
|
+
article: {
|
|
511
|
+
className: 'blog-post',
|
|
512
|
+
children: [
|
|
513
|
+
{ h1: { text: post.title } },
|
|
514
|
+
{
|
|
515
|
+
div: {
|
|
516
|
+
className: 'post-meta',
|
|
517
|
+
children: [
|
|
518
|
+
{ span: { text: `By ${post.author.name}` } },
|
|
519
|
+
{ time: {
|
|
520
|
+
text: formatDate(post.publishedAt),
|
|
521
|
+
datetime: post.publishedAt
|
|
522
|
+
}}
|
|
523
|
+
]
|
|
524
|
+
}
|
|
525
|
+
},
|
|
526
|
+
{ div: {
|
|
527
|
+
className: 'post-content',
|
|
528
|
+
innerHTML: post.content
|
|
529
|
+
}}
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### E-commerce Product Page
|
|
537
|
+
|
|
538
|
+
```javascript
|
|
539
|
+
import {
|
|
540
|
+
createSEOHooks,
|
|
541
|
+
createProductSchema
|
|
542
|
+
} from '@coherent.js/seo';
|
|
543
|
+
|
|
544
|
+
const seo = createSEOHooks({
|
|
545
|
+
siteUrl: 'https://mystore.com'
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
function ProductPage({ product, reviews }) {
|
|
549
|
+
// Basic SEO metadata
|
|
550
|
+
seo.setMetadata({
|
|
551
|
+
title: `${product.name} | My Store`,
|
|
552
|
+
description: product.description,
|
|
553
|
+
image: product.images[0],
|
|
554
|
+
type: 'product.item',
|
|
555
|
+
|
|
556
|
+
// Open Graph for social sharing
|
|
557
|
+
og: {
|
|
558
|
+
price: {
|
|
559
|
+
amount: product.price.toString(),
|
|
560
|
+
currency: product.currency
|
|
561
|
+
},
|
|
562
|
+
availability: product.inStock ? 'instock' : 'outofstock',
|
|
563
|
+
condition: 'new'
|
|
564
|
+
},
|
|
565
|
+
|
|
566
|
+
// Twitter Card
|
|
567
|
+
twitter: {
|
|
568
|
+
card: 'summary_large_image',
|
|
569
|
+
label1: 'Price',
|
|
570
|
+
data1: `${product.currency} ${product.price}`,
|
|
571
|
+
label2: 'Availability',
|
|
572
|
+
data2: product.inStock ? 'In Stock' : 'Out of Stock'
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
// Product structured data
|
|
577
|
+
seo.addSchema(createProductSchema({
|
|
578
|
+
name: product.name,
|
|
579
|
+
description: product.description,
|
|
580
|
+
image: product.images,
|
|
581
|
+
offers: {
|
|
582
|
+
price: product.price.toString(),
|
|
583
|
+
priceCurrency: product.currency,
|
|
584
|
+
availability: product.inStock ? 'InStock' : 'OutOfStock',
|
|
585
|
+
url: `https://mystore.com/products/${product.slug}`,
|
|
586
|
+
seller: {
|
|
587
|
+
name: 'My Store'
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
brand: product.brand,
|
|
591
|
+
category: product.category,
|
|
592
|
+
sku: product.sku,
|
|
593
|
+
gtin: product.gtin,
|
|
594
|
+
aggregateRating: {
|
|
595
|
+
ratingValue: reviews.averageRating,
|
|
596
|
+
reviewCount: reviews.count
|
|
597
|
+
}
|
|
598
|
+
}));
|
|
599
|
+
|
|
600
|
+
// Set canonical and alternates
|
|
601
|
+
seo.setCanonical(`https://mystore.com/products/${product.slug}`);
|
|
602
|
+
|
|
603
|
+
return {
|
|
604
|
+
div: {
|
|
605
|
+
className: 'product-page',
|
|
606
|
+
children: [
|
|
607
|
+
{ h1: { text: product.name } },
|
|
608
|
+
{
|
|
609
|
+
div: {
|
|
610
|
+
className: 'product-images',
|
|
611
|
+
children: product.images.map(img => ({
|
|
612
|
+
img: { src: img, alt: product.name }
|
|
613
|
+
}))
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
{ p: { text: product.description } },
|
|
617
|
+
{ p: { text: `${product.currency} ${product.price}` } },
|
|
618
|
+
{
|
|
619
|
+
button: {
|
|
620
|
+
text: product.inStock ? 'Add to Cart' : 'Out of Stock',
|
|
621
|
+
disabled: !product.inStock
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
]
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
## Best Practices
|
|
631
|
+
|
|
632
|
+
### 1. Unique Titles and Descriptions
|
|
633
|
+
|
|
634
|
+
```javascript
|
|
635
|
+
// Good: Unique for each page
|
|
636
|
+
seo.setMetadata({
|
|
637
|
+
title: `How to Master Coherent.js | Developer Guide`,
|
|
638
|
+
description: 'Learn advanced techniques for building high-performance Coherent.js applications with this comprehensive guide.'
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Avoid: Generic/duplicated content
|
|
642
|
+
seo.setMetadata({
|
|
643
|
+
title: 'Page Title',
|
|
644
|
+
description: 'This is a description'
|
|
645
|
+
});
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### 2. Optimal Lengths
|
|
649
|
+
|
|
650
|
+
```javascript
|
|
651
|
+
// Title: 50-60 characters
|
|
652
|
+
// Description: 150-160 characters
|
|
653
|
+
seo.setMetadata({
|
|
654
|
+
title: 'Coherent.js Performance Optimization Guide', // 42 chars - good
|
|
655
|
+
description: 'Maximize your Coherent.js application performance with these proven optimization techniques and best practices.' // 117 chars - good
|
|
656
|
+
});
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### 3. Image Optimization
|
|
660
|
+
|
|
661
|
+
```javascript
|
|
662
|
+
seo.setMetadata({
|
|
663
|
+
// Use appropriately sized images
|
|
664
|
+
image: {
|
|
665
|
+
url: 'https://example.com/social-image.jpg',
|
|
666
|
+
width: 1200,
|
|
667
|
+
height: 630,
|
|
668
|
+
alt: 'Description of image content'
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
## Related Packages
|
|
674
|
+
|
|
675
|
+
- [@coherent.js/core](../core/README.md) - Core framework
|
|
676
|
+
- [@coherent.js/i18n](../i18n/README.md) - Internationalization
|
|
677
|
+
- [@coherent.js/client](../client/README.md) - Client-side utilities
|
|
678
|
+
|
|
679
|
+
## License
|
|
680
|
+
|
|
681
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/seo",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.5",
|
|
4
4
|
"description": "SEO utilities for Coherent.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"author": "Coherent.js Team",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@coherent.js/core": "1.0.0-beta.
|
|
23
|
+
"@coherent.js/core": "1.0.0-beta.5"
|
|
24
24
|
},
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"README.md",
|
|
36
36
|
"types/"
|
|
37
37
|
],
|
|
38
|
+
"sideEffects": false,
|
|
38
39
|
"scripts": {
|
|
39
40
|
"build": "node build.mjs",
|
|
40
41
|
"clean": "rm -rf dist"
|