@power-seo/sitemap 1.0.2 → 1.0.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 +367 -229
- package/dist/index.cjs +76 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -3
- package/dist/index.d.ts +39 -3
- package/dist/index.js +39 -6
- package/dist/index.js.map +1 -1
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -1,75 +1,92 @@
|
|
|
1
|
-
# @power-seo/sitemap
|
|
1
|
+
# @power-seo/sitemap
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@power-seo/sitemap)
|
|
4
4
|
[](https://www.npmjs.com/package/@power-seo/sitemap)
|
|
5
|
+
[](https://socket.dev/npm/package/@power-seo/sitemap)
|
|
6
|
+
[](https://github.com/CyberCraftBD/power-seo/actions)
|
|
5
7
|
[](https://opensource.org/licenses/MIT)
|
|
6
8
|
[](https://www.typescriptlang.org/)
|
|
7
9
|
[](https://bundlephobia.com/package/@power-seo/sitemap)
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Overview
|
|
12
|
-
|
|
13
|
-
**@power-seo/sitemap** is a zero-dependency XML sitemap generator for TypeScript that helps you generate standards-compliant sitemaps with image, video, and news extensions — including streaming generation and automatic index splitting for large sites.
|
|
14
|
-
|
|
15
|
-
**What it does**
|
|
16
|
-
|
|
17
|
-
- ✅ **Generate XML sitemaps** — `generateSitemap()` produces spec-compliant `<urlset>` XML strings
|
|
18
|
-
- ✅ **Stream large sitemaps** — `streamSitemap()` yields XML chunks with constant memory usage
|
|
19
|
-
- ✅ **Split into multiple files** — `splitSitemap()` auto-chunks at the 50,000-URL limit
|
|
20
|
-
- ✅ **Generate sitemap indexes** — `generateSitemapIndex()` creates `<sitemapindex>` files pointing to child sitemaps
|
|
21
|
-
- ✅ **Validate URL entries** — `validateSitemapUrl()` checks against Google's sitemap spec requirements
|
|
11
|
+
XML sitemap generation for TypeScript — streaming output, automatic index splitting, image/video/news extensions, and URL validation — works in Next.js, Remix, Express, and edge runtimes with zero runtime dependencies.
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
`@power-seo/sitemap` produces standards-compliant `<urlset>` and `<sitemapindex>` XML from typed URL arrays. Provide a hostname and URL list — get back a valid XML string ready to serve as `Content-Type: application/xml`. For large catalogs, stream chunks with constant memory usage or auto-split at the 50,000-URL spec limit with a generated index file. All five functions are independently importable and tree-shakeable.
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
- ❌ **Not a submission client** — use `@power-seo/search-console` to submit sitemaps to GSC
|
|
27
|
-
|
|
28
|
-
**Recommended for**
|
|
29
|
-
|
|
30
|
-
- **Next.js App Router sites**, **Remix apps**, **Express servers**, **static site generators**, and any Node.js/edge environment that generates sitemaps programmatically
|
|
15
|
+
> **Zero runtime dependencies** — only `@power-seo/core` as a peer.
|
|
31
16
|
|
|
32
17
|
---
|
|
33
18
|
|
|
34
|
-
## Why @power-seo/sitemap
|
|
35
|
-
|
|
36
|
-
**The problem**
|
|
37
|
-
|
|
38
|
-
- **Sites with 50,000+ URLs** cannot fit in a single sitemap file — the spec mandates splitting
|
|
39
|
-
- **Image and video sitemaps** require `<image:image>` and `<video:video>` namespace extensions that most generators don't support
|
|
40
|
-
- **Memory spikes** during XML string concatenation cause crashes or timeouts on large e-commerce catalogs
|
|
41
|
-
|
|
42
|
-
**Why developers care**
|
|
19
|
+
## Why @power-seo/sitemap?
|
|
43
20
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
21
|
+
| | Without | With |
|
|
22
|
+
| ----------------- | ----------------------------------------- | --------------------------------------------------- |
|
|
23
|
+
| Spec compliance | ❌ Hand-built XML, wrong namespaces | ✅ Correct `<urlset>` + namespace declarations |
|
|
24
|
+
| Large sites | ❌ Single file breaks at 50,000 URLs | ✅ Auto-split + sitemap index generation |
|
|
25
|
+
| Memory usage | ❌ String concat spikes on large catalogs | ✅ Synchronous generator yields chunks |
|
|
26
|
+
| Image indexing | ❌ Product images undiscoverable | ✅ `<image:image>` extension per URL |
|
|
27
|
+
| Video SEO | ❌ No structured video metadata | ✅ `<video:video>` extension with title, duration |
|
|
28
|
+
| News sitemaps | ❌ Missing publication + date tags | ✅ `<news:news>` extension for Google News |
|
|
29
|
+
| Hostname handling | ❌ Hardcode absolute URLs everywhere | ✅ Pass `hostname` once; use relative `loc` paths |
|
|
30
|
+
| Validation | ❌ Silent bad data reaches Google | ✅ `validateSitemapUrl()` returns errors + warnings |
|
|
47
31
|
|
|
48
32
|
---
|
|
49
33
|
|
|
50
|
-
##
|
|
34
|
+
## Features
|
|
51
35
|
|
|
52
|
-
- **Full sitemap spec support** — `<loc>`, `<lastmod>`, `<changefreq>`, `<priority>`,
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
36
|
+
- **Full sitemap spec support** — `<loc>`, `<lastmod>`, `<changefreq>`, `<priority>`, all optional elements
|
|
37
|
+
- **Hostname + relative paths** — pass `hostname` in config; `loc` can be a relative path like `/about`
|
|
38
|
+
- **Image sitemap extension** — `<image:image>` tags with `loc`, `caption`, `title`, `geoLocation`, `license`
|
|
39
|
+
- **Video sitemap extension** — `<video:video>` tags with title, description, thumbnail, duration, rating
|
|
55
40
|
- **News sitemap extension** — `<news:news>` tags with publication name, language, date
|
|
56
|
-
- **Streaming generation** — `streamSitemap()`
|
|
57
|
-
- **Automatic index splitting** — `splitSitemap()` chunks at `MAX_URLS_PER_SITEMAP` (50,000)
|
|
41
|
+
- **Streaming generation** — `streamSitemap()` is a synchronous generator yielding XML string chunks; no memory spike on large lists
|
|
42
|
+
- **Automatic index splitting** — `splitSitemap()` chunks at `MAX_URLS_PER_SITEMAP` (50,000) and returns both sitemaps and the index XML
|
|
58
43
|
- **Sitemap index generation** — `generateSitemapIndex()` creates a `<sitemapindex>` pointing to child sitemaps
|
|
59
44
|
- **URL validation** — `validateSitemapUrl()` returns `{ valid, errors, warnings }` without throwing
|
|
60
|
-
- **
|
|
45
|
+
- **Next.js App Router adapter** — `toNextSitemap()` (from `@power-seo/sitemap/next`) converts `SitemapURL[]` to the `MetadataRoute.Sitemap[]` format for `app/sitemap.ts`
|
|
46
|
+
- **Constants exported** — `MAX_URLS_PER_SITEMAP` (50,000) and `MAX_SITEMAP_SIZE_BYTES` (52,428,800)
|
|
61
47
|
- **Framework-agnostic** — works in Next.js API routes, Remix loaders, Express, Fastify, and edge runtimes
|
|
62
48
|
- **Full TypeScript support** — typed `SitemapURL`, `SitemapImage`, `SitemapVideo`, `SitemapNews`, `SitemapConfig`
|
|
63
49
|
- **Zero runtime dependencies** — pure TypeScript, no external XML libraries
|
|
50
|
+
- **Tree-shakeable** — import only the functions you use
|
|
64
51
|
|
|
65
52
|
---
|
|
66
53
|
|
|
67
|
-
##
|
|
54
|
+
## Comparison
|
|
55
|
+
|
|
56
|
+
| Feature | @power-seo/sitemap | next-sitemap | sitemap (npm) | xmlbuilder2 |
|
|
57
|
+
| -------------------------------- | :----------------: | :----------: | :-----------: | :---------: |
|
|
58
|
+
| Image sitemap extension | ✅ | ✅ | ✅ | ❌ |
|
|
59
|
+
| Video sitemap extension | ✅ | ❌ | ✅ | ❌ |
|
|
60
|
+
| News sitemap extension | ✅ | ❌ | ✅ | ❌ |
|
|
61
|
+
| Streaming generation | ✅ | ❌ | ❌ | ❌ |
|
|
62
|
+
| Auto index splitting | ✅ | ✅ | ❌ | ❌ |
|
|
63
|
+
| URL validation | ✅ | ❌ | ❌ | ❌ |
|
|
64
|
+
| Hostname + relative loc paths | ✅ | ❌ | ❌ | ❌ |
|
|
65
|
+
| Zero runtime dependencies | ✅ | ❌ | ❌ | ❌ |
|
|
66
|
+
| Edge runtime compatible | ✅ | ❌ | ❌ | ❌ |
|
|
67
|
+
| TypeScript-first | ✅ | Partial | ❌ | ❌ |
|
|
68
|
+
| Tree-shakeable | ✅ | ❌ | ❌ | ❌ |
|
|
69
|
+
| Next.js `app/sitemap.ts` adapter | ✅ | ✅ | ❌ | ❌ |
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Installation
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm install @power-seo/sitemap
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
yarn add @power-seo/sitemap
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pnpm add @power-seo/sitemap
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
bun add @power-seo/sitemap
|
|
89
|
+
```
|
|
73
90
|
|
|
74
91
|
---
|
|
75
92
|
|
|
@@ -79,200 +96,216 @@
|
|
|
79
96
|
import { generateSitemap } from '@power-seo/sitemap';
|
|
80
97
|
|
|
81
98
|
const xml = generateSitemap({
|
|
99
|
+
hostname: 'https://example.com',
|
|
82
100
|
urls: [
|
|
83
|
-
{ loc: '
|
|
84
|
-
{ loc: '
|
|
85
|
-
{ loc: '
|
|
101
|
+
{ loc: '/', lastmod: '2026-01-01', changefreq: 'daily', priority: 1.0 },
|
|
102
|
+
{ loc: '/about', changefreq: 'monthly', priority: 0.8 },
|
|
103
|
+
{ loc: '/blog/post-1', lastmod: '2026-01-15', priority: 0.6 },
|
|
86
104
|
],
|
|
87
105
|
});
|
|
88
106
|
|
|
89
107
|
// Returns valid XML string:
|
|
90
108
|
// <?xml version="1.0" encoding="UTF-8"?>
|
|
91
|
-
// <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
|
109
|
+
// <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
110
|
+
// <url><loc>https://example.com/</loc>...
|
|
92
111
|
```
|
|
93
112
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
- A standards-compliant XML sitemap string ready to serve as `Content-Type: application/xml`
|
|
97
|
-
- `<urlset>` containing `<url>` entries with the fields you provided
|
|
113
|
+
`hostname` is required — it is prepended to any `loc` value that is a relative path. Absolute `loc` values (starting with `http`) are used as-is.
|
|
98
114
|
|
|
99
115
|
---
|
|
100
116
|
|
|
101
|
-
##
|
|
117
|
+
## Usage
|
|
102
118
|
|
|
103
|
-
|
|
104
|
-
npm i @power-seo/sitemap
|
|
105
|
-
# or
|
|
106
|
-
yarn add @power-seo/sitemap
|
|
107
|
-
# or
|
|
108
|
-
pnpm add @power-seo/sitemap
|
|
109
|
-
# or
|
|
110
|
-
bun add @power-seo/sitemap
|
|
111
|
-
```
|
|
119
|
+
### Generating a Sitemap
|
|
112
120
|
|
|
113
|
-
|
|
121
|
+
`generateSitemap()` accepts a `SitemapConfig` with `hostname` and `urls` and returns a complete XML string.
|
|
114
122
|
|
|
115
|
-
|
|
123
|
+
```ts
|
|
124
|
+
import { generateSitemap } from '@power-seo/sitemap';
|
|
116
125
|
|
|
117
|
-
|
|
126
|
+
const xml = generateSitemap({
|
|
127
|
+
hostname: 'https://example.com',
|
|
128
|
+
urls: [
|
|
129
|
+
{ loc: '/', lastmod: '2026-01-01', changefreq: 'daily', priority: 1.0 },
|
|
130
|
+
{ loc: '/products', changefreq: 'weekly', priority: 0.9 },
|
|
131
|
+
{ loc: '/blog', changefreq: 'daily', priority: 0.8 },
|
|
132
|
+
],
|
|
133
|
+
});
|
|
118
134
|
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- ✅ Edge runtimes — no `fs`, no `path`, no Node.js-specific APIs (except `streamSitemap` which uses `AsyncIterable`)
|
|
124
|
-
- ✅ Fastify / Express — serve the XML string as response body
|
|
135
|
+
// Serve as application/xml
|
|
136
|
+
res.setHeader('Content-Type', 'application/xml');
|
|
137
|
+
res.send(xml);
|
|
138
|
+
```
|
|
125
139
|
|
|
126
|
-
|
|
140
|
+
### Streaming a Large Sitemap
|
|
127
141
|
|
|
128
|
-
|
|
129
|
-
- **Edge runtime:** `generateSitemap()` and `generateSitemapIndex()` are edge-compatible; `streamSitemap()` requires Node.js streams if writing to disk
|
|
130
|
-
- **Browser-only usage:** Not applicable — sitemap generation is a server-side concern
|
|
142
|
+
`streamSitemap()` is a synchronous generator. It yields XML string chunks one `<url>` at a time — keeping memory usage constant regardless of catalog size.
|
|
131
143
|
|
|
132
|
-
|
|
144
|
+
```ts
|
|
145
|
+
import { streamSitemap } from '@power-seo/sitemap';
|
|
133
146
|
|
|
134
|
-
|
|
147
|
+
const urls = fetchAllProductUrls(); // Iterable<SitemapURL>
|
|
135
148
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
- **Video platforms** — `<video:video>` extension for YouTube-style video SEO
|
|
149
|
+
const stream = streamSitemap('https://example.com', urls);
|
|
150
|
+
for (const chunk of stream) {
|
|
151
|
+
response.write(chunk);
|
|
152
|
+
}
|
|
153
|
+
response.end();
|
|
154
|
+
```
|
|
143
155
|
|
|
144
|
-
|
|
156
|
+
### Splitting Large Sitemaps with an Index
|
|
157
|
+
|
|
158
|
+
`splitSitemap()` chunks a config at the 50,000-URL spec limit and returns all individual sitemap XML strings plus a sitemap index XML string that references them.
|
|
145
159
|
|
|
146
|
-
|
|
160
|
+
```ts
|
|
161
|
+
import { splitSitemap } from '@power-seo/sitemap';
|
|
162
|
+
|
|
163
|
+
const { index, sitemaps } = splitSitemap({
|
|
164
|
+
hostname: 'https://example.com',
|
|
165
|
+
urls: largeUrlArray, // more than 50,000 entries
|
|
166
|
+
});
|
|
147
167
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
- No image sitemap: product images not discovered by Googlebot Images
|
|
168
|
+
// Write each sitemap file
|
|
169
|
+
for (const { filename, xml } of sitemaps) {
|
|
170
|
+
fs.writeFileSync(`./public${filename}`, xml);
|
|
171
|
+
}
|
|
153
172
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
- splitSitemap(allUrls) + generateSitemapIndex() → auto-split + index file
|
|
157
|
-
- urls[i].images = [{ loc, caption }] → <image:image> tags for each product
|
|
173
|
+
// Write the index (default filenames: /sitemap-0.xml, /sitemap-1.xml, ...)
|
|
174
|
+
fs.writeFileSync('./public/sitemap.xml', index);
|
|
158
175
|
```
|
|
159
176
|
|
|
160
|
-
|
|
177
|
+
Custom filename pattern:
|
|
161
178
|
|
|
162
|
-
|
|
179
|
+
```ts
|
|
180
|
+
const { index, sitemaps } = splitSitemap(
|
|
181
|
+
{ hostname: 'https://example.com', urls: largeUrlArray },
|
|
182
|
+
'/sitemaps/part-{index}.xml', // default: '/sitemap-{index}.xml'
|
|
183
|
+
);
|
|
184
|
+
```
|
|
163
185
|
|
|
164
|
-
|
|
165
|
-
- **Keep `priority` values realistic** — setting everything to 1.0 signals ignored priority; reserve 1.0 for the homepage
|
|
166
|
-
- **Use `changefreq: 'never'` for permanent content** — signals Googlebot to skip re-crawling
|
|
167
|
-
- **Set `sitemap.xml` URL in `robots.txt`** — `Sitemap: https://example.com/sitemap.xml` is required for discovery
|
|
168
|
-
- **Submit to Google Search Console** after generating — use `@power-seo/search-console` `submitSitemap()`
|
|
186
|
+
### Generating a Sitemap Index Manually
|
|
169
187
|
|
|
170
|
-
|
|
188
|
+
Use `generateSitemapIndex()` when you maintain separate sitemaps per section or locale and want to combine them under a single index file.
|
|
171
189
|
|
|
172
|
-
|
|
190
|
+
```ts
|
|
191
|
+
import { generateSitemapIndex } from '@power-seo/sitemap';
|
|
173
192
|
|
|
174
|
-
|
|
193
|
+
const indexXml = generateSitemapIndex({
|
|
194
|
+
sitemaps: [
|
|
195
|
+
{ loc: 'https://example.com/sitemap-pages.xml', lastmod: '2026-01-01' },
|
|
196
|
+
{ loc: 'https://example.com/sitemap-products.xml', lastmod: '2026-01-15' },
|
|
197
|
+
{ loc: 'https://example.com/sitemap-blog.xml', lastmod: '2026-01-20' },
|
|
198
|
+
],
|
|
199
|
+
});
|
|
200
|
+
```
|
|
175
201
|
|
|
176
|
-
|
|
177
|
-
- **Runtime**: Serve dynamically from an API route; regenerate on demand or on ISR revalidation
|
|
178
|
-
- **CI/CD**: Validate sitemap URL entries as part of pull request checks
|
|
202
|
+
### Image Sitemaps
|
|
179
203
|
|
|
180
|
-
|
|
204
|
+
Add `images` to any `SitemapURL` entry to emit `<image:image>` extension tags:
|
|
181
205
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
3. **Output**: Valid XML string or `AsyncIterable<string>` stream
|
|
185
|
-
4. **Action**: Serve as `application/xml`, write to disk, or submit to GSC via `@power-seo/search-console`
|
|
206
|
+
```ts
|
|
207
|
+
import { generateSitemap } from '@power-seo/sitemap';
|
|
186
208
|
|
|
187
|
-
|
|
209
|
+
const xml = generateSitemap({
|
|
210
|
+
hostname: 'https://example.com',
|
|
211
|
+
urls: [
|
|
212
|
+
{
|
|
213
|
+
loc: '/products/blue-sneaker',
|
|
214
|
+
lastmod: '2026-01-10',
|
|
215
|
+
images: [
|
|
216
|
+
{
|
|
217
|
+
loc: 'https://cdn.example.com/sneaker-blue.jpg',
|
|
218
|
+
caption: 'Blue sneaker — side view',
|
|
219
|
+
title: 'Blue Running Sneaker',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
loc: 'https://cdn.example.com/sneaker-blue-top.jpg',
|
|
223
|
+
caption: 'Blue sneaker — top view',
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
});
|
|
229
|
+
```
|
|
188
230
|
|
|
189
|
-
|
|
231
|
+
### Validating URL Entries
|
|
190
232
|
|
|
191
|
-
|
|
192
|
-
| ------------------------- | -----------: | ------------: | ----------: | -----------------: |
|
|
193
|
-
| Image sitemap extension | ✅ | ✅ | ❌ | ✅ |
|
|
194
|
-
| Video sitemap extension | ❌ | ✅ | ❌ | ✅ |
|
|
195
|
-
| News sitemap extension | ❌ | ✅ | ❌ | ✅ |
|
|
196
|
-
| Streaming generation | ❌ | ❌ | ❌ | ✅ |
|
|
197
|
-
| Auto index splitting | ✅ | ❌ | ❌ | ✅ |
|
|
198
|
-
| URL validation | ❌ | ❌ | ❌ | ✅ |
|
|
199
|
-
| Zero runtime dependencies | ❌ | ❌ | ❌ | ✅ |
|
|
200
|
-
| Edge runtime compatible | ❌ | ❌ | ❌ | ✅ |
|
|
233
|
+
`validateSitemapUrl()` checks a `SitemapURL` against the sitemap spec and returns structured errors and warnings — useful in CI or before serving.
|
|
201
234
|
|
|
202
|
-
|
|
235
|
+
```ts
|
|
236
|
+
import { validateSitemapUrl } from '@power-seo/sitemap';
|
|
203
237
|
|
|
204
|
-
|
|
238
|
+
const result = validateSitemapUrl({
|
|
239
|
+
loc: '/about',
|
|
240
|
+
priority: 1.5, // out of range
|
|
241
|
+
changefreq: 'daily',
|
|
242
|
+
});
|
|
205
243
|
|
|
206
|
-
|
|
244
|
+
// result.valid → false
|
|
245
|
+
// result.errors → ['priority must be between 0.0 and 1.0']
|
|
246
|
+
// result.warnings → []
|
|
247
|
+
```
|
|
207
248
|
|
|
208
|
-
|
|
209
|
-
| ------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------- |
|
|
210
|
-
| [`@power-seo/core`](https://www.npmjs.com/package/@power-seo/core) | `npm i @power-seo/core` | Framework-agnostic utilities, types, validators, and constants |
|
|
211
|
-
| [`@power-seo/react`](https://www.npmjs.com/package/@power-seo/react) | `npm i @power-seo/react` | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs |
|
|
212
|
-
| [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta) | `npm i @power-seo/meta` | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR |
|
|
213
|
-
| [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 20 builders + 18 React components |
|
|
214
|
-
| [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components |
|
|
215
|
-
| [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability) | `npm i @power-seo/readability` | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI |
|
|
216
|
-
| [`@power-seo/preview`](https://www.npmjs.com/package/@power-seo/preview) | `npm i @power-seo/preview` | SERP, Open Graph, and Twitter/X Card preview generators |
|
|
217
|
-
| [`@power-seo/sitemap`](https://www.npmjs.com/package/@power-seo/sitemap) | `npm i @power-seo/sitemap` | XML sitemap generation, streaming, index splitting, and validation |
|
|
218
|
-
| [`@power-seo/redirects`](https://www.npmjs.com/package/@power-seo/redirects) | `npm i @power-seo/redirects` | Redirect engine with Next.js, Remix, and Express adapters |
|
|
219
|
-
| [`@power-seo/links`](https://www.npmjs.com/package/@power-seo/links) | `npm i @power-seo/links` | Link graph analysis — orphan detection, suggestions, equity scoring |
|
|
220
|
-
| [`@power-seo/audit`](https://www.npmjs.com/package/@power-seo/audit) | `npm i @power-seo/audit` | Full SEO audit engine — meta, content, structure, performance rules |
|
|
221
|
-
| [`@power-seo/images`](https://www.npmjs.com/package/@power-seo/images) | `npm i @power-seo/images` | Image SEO — alt text, lazy loading, format analysis, image sitemaps |
|
|
222
|
-
| [`@power-seo/ai`](https://www.npmjs.com/package/@power-seo/ai) | `npm i @power-seo/ai` | LLM-agnostic AI prompt templates and parsers for SEO tasks |
|
|
223
|
-
| [`@power-seo/analytics`](https://www.npmjs.com/package/@power-seo/analytics) | `npm i @power-seo/analytics` | Merge GSC + audit data, trend analysis, ranking insights, dashboard |
|
|
224
|
-
| [`@power-seo/search-console`](https://www.npmjs.com/package/@power-seo/search-console) | `npm i @power-seo/search-console` | Google Search Console API — OAuth2, service account, URL inspection |
|
|
225
|
-
| [`@power-seo/integrations`](https://www.npmjs.com/package/@power-seo/integrations) | `npm i @power-seo/integrations` | Semrush and Ahrefs API clients with rate limiting and pagination |
|
|
226
|
-
| [`@power-seo/tracking`](https://www.npmjs.com/package/@power-seo/tracking) | `npm i @power-seo/tracking` | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management |
|
|
249
|
+
### Next.js App Router — `app/sitemap.ts` Convention
|
|
227
250
|
|
|
228
|
-
|
|
251
|
+
Next.js App Router has a built-in `app/sitemap.ts` file convention that returns an array of URL objects (not XML). Use `toNextSitemap()` from the `/next` subpath to convert `SitemapURL[]` to the required format:
|
|
229
252
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
| Sitemap submission | Manual GSC UI | `@power-seo/search-console` — `submitSitemap()` |
|
|
234
|
-
| Image SEO | Manual `<image:image>` | `@power-seo/sitemap` + `@power-seo/images` |
|
|
235
|
-
| Structured data | Manual JSON-LD | `@power-seo/schema` — typed builders |
|
|
253
|
+
```ts
|
|
254
|
+
// app/sitemap.ts
|
|
255
|
+
import { toNextSitemap } from '@power-seo/sitemap/next';
|
|
236
256
|
|
|
237
|
-
|
|
257
|
+
export default async function sitemap() {
|
|
258
|
+
const urls = await fetchUrlsFromCms();
|
|
238
259
|
|
|
239
|
-
|
|
260
|
+
return toNextSitemap(urls);
|
|
261
|
+
// Returns NextSitemapEntry[] — Next.js renders the XML automatically
|
|
262
|
+
}
|
|
263
|
+
```
|
|
240
264
|
|
|
241
|
-
|
|
265
|
+
`toNextSitemap()` filters out invalid URLs, converts `lastmod` strings to `Date` objects, and maps `changefreq` to `changeFrequency` as required by Next.js.
|
|
242
266
|
|
|
243
|
-
|
|
244
|
-
- **Sitemap index**: Use `generateSitemapIndex()` to aggregate tenant sitemaps into a root index
|
|
245
|
-
- **Scheduled regeneration**: Rebuild sitemaps nightly as new content is published
|
|
267
|
+
### Next.js App Router — Route Handler (XML)
|
|
246
268
|
|
|
247
|
-
|
|
269
|
+
For full control over the XML output (useful when you need image/video/news extensions), use a route handler instead:
|
|
248
270
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
271
|
+
```ts
|
|
272
|
+
// app/sitemap.xml/route.ts
|
|
273
|
+
import { generateSitemap } from '@power-seo/sitemap';
|
|
252
274
|
|
|
253
|
-
|
|
275
|
+
export async function GET() {
|
|
276
|
+
const urls = await fetchUrlsFromCms();
|
|
254
277
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
278
|
+
const xml = generateSitemap({
|
|
279
|
+
hostname: 'https://example.com',
|
|
280
|
+
urls,
|
|
281
|
+
});
|
|
259
282
|
|
|
260
|
-
|
|
283
|
+
return new Response(xml, {
|
|
284
|
+
headers: { 'Content-Type': 'application/xml' },
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
```
|
|
261
288
|
|
|
262
|
-
|
|
289
|
+
### Remix Resource Route
|
|
263
290
|
|
|
264
|
-
|
|
291
|
+
```ts
|
|
292
|
+
// app/routes/sitemap[.xml].ts
|
|
293
|
+
import { generateSitemap } from '@power-seo/sitemap';
|
|
294
|
+
import type { LoaderFunctionArgs } from '@remix-run/node';
|
|
265
295
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
- ✅ Stream large sitemaps to avoid memory spikes
|
|
269
|
-
- ✅ Split sitemaps and generate sitemap index files
|
|
296
|
+
export async function loader({ request }: LoaderFunctionArgs) {
|
|
297
|
+
const urls = await fetchUrlsFromDb();
|
|
270
298
|
|
|
271
|
-
|
|
299
|
+
const xml = generateSitemap({
|
|
300
|
+
hostname: 'https://example.com',
|
|
301
|
+
urls,
|
|
302
|
+
});
|
|
272
303
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
304
|
+
return new Response(xml, {
|
|
305
|
+
headers: { 'Content-Type': 'application/xml' },
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
```
|
|
276
309
|
|
|
277
310
|
---
|
|
278
311
|
|
|
@@ -284,37 +317,51 @@ All 17 packages are independently installable — use only what you need.
|
|
|
284
317
|
function generateSitemap(config: SitemapConfig): string;
|
|
285
318
|
```
|
|
286
319
|
|
|
287
|
-
| Prop
|
|
288
|
-
|
|
|
289
|
-
| `
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
| Prop | Type | Default | Description |
|
|
294
|
-
| ------------ | --------------------------------------------------------------------------------- | ------- | ---------------------------------------- |
|
|
295
|
-
| `loc` | `string` | — | **Required.** Absolute URL |
|
|
296
|
-
| `lastmod` | `string` | — | Last modified (ISO 8601 or `YYYY-MM-DD`) |
|
|
297
|
-
| `changefreq` | `'always' \| 'hourly' \| 'daily' \| 'weekly' \| 'monthly' \| 'yearly' \| 'never'` | — | Change frequency |
|
|
298
|
-
| `priority` | `number` | `0.5` | Priority 0.0–1.0 |
|
|
299
|
-
| `images` | `SitemapImage[]` | — | Image extension entries |
|
|
300
|
-
| `videos` | `SitemapVideo[]` | — | Video extension entries |
|
|
301
|
-
| `news` | `SitemapNews` | — | News extension entry |
|
|
320
|
+
| Prop | Type | Required | Description |
|
|
321
|
+
| ------------------- | -------------- | -------- | ------------------------------------------------------------------------- |
|
|
322
|
+
| `hostname` | `string` | ✅ | Base URL prepended to relative `loc` paths (e.g. `'https://example.com'`) |
|
|
323
|
+
| `urls` | `SitemapURL[]` | ✅ | Array of URL entries |
|
|
324
|
+
| `maxUrlsPerSitemap` | `number` | — | Override the 50,000-URL chunk size (used by `splitSitemap`) |
|
|
325
|
+
| `outputDir` | `string` | — | Optional output directory hint (informational; does not write files) |
|
|
302
326
|
|
|
303
|
-
### `streamSitemap(
|
|
327
|
+
### `streamSitemap(hostname, urls)`
|
|
304
328
|
|
|
305
329
|
```ts
|
|
306
|
-
function streamSitemap(
|
|
330
|
+
function streamSitemap(
|
|
331
|
+
hostname: string,
|
|
332
|
+
urls: Iterable<SitemapURL>,
|
|
333
|
+
): Generator<string, void, undefined>;
|
|
307
334
|
```
|
|
308
335
|
|
|
309
|
-
|
|
336
|
+
Synchronous generator. Yields XML string chunks — one for the XML declaration and opening tag, one per `<url>` block, and one for the closing tag. Does not buffer the full XML in memory.
|
|
310
337
|
|
|
311
|
-
|
|
338
|
+
| Param | Type | Description |
|
|
339
|
+
| ---------- | ---------------------- | ------------------------------------------------------------------ |
|
|
340
|
+
| `hostname` | `string` | Base URL prepended to relative `loc` paths |
|
|
341
|
+
| `urls` | `Iterable<SitemapURL>` | Any iterable of URL entries — arrays, generators, database cursors |
|
|
342
|
+
|
|
343
|
+
### `splitSitemap(config, sitemapUrlPattern?)`
|
|
312
344
|
|
|
313
345
|
```ts
|
|
314
|
-
function splitSitemap(
|
|
346
|
+
function splitSitemap(
|
|
347
|
+
config: SitemapConfig,
|
|
348
|
+
sitemapUrlPattern?: string,
|
|
349
|
+
): { index: string; sitemaps: Array<{ filename: string; xml: string }> };
|
|
315
350
|
```
|
|
316
351
|
|
|
317
|
-
Splits
|
|
352
|
+
Splits a large URL set into multiple sitemap files and returns the index XML and all sitemap XMLs. The `sitemapUrlPattern` parameter controls generated filenames using `{index}` as a placeholder.
|
|
353
|
+
|
|
354
|
+
| Param | Type | Default | Description |
|
|
355
|
+
| ------------------- | --------------- | ------------------------ | --------------------------------------- |
|
|
356
|
+
| `config` | `SitemapConfig` | — | Same config as `generateSitemap()` |
|
|
357
|
+
| `sitemapUrlPattern` | `string` | `'/sitemap-{index}.xml'` | Filename pattern for each split sitemap |
|
|
358
|
+
|
|
359
|
+
**Return value:**
|
|
360
|
+
|
|
361
|
+
| Field | Type | Description |
|
|
362
|
+
| ---------- | ------------------------------------------ | ---------------------------------------------------------------- |
|
|
363
|
+
| `index` | `string` | Sitemap index XML (`<sitemapindex>`) referencing all split files |
|
|
364
|
+
| `sitemaps` | `Array<{ filename: string; xml: string }>` | Each split sitemap with its filename and XML string |
|
|
318
365
|
|
|
319
366
|
### `generateSitemapIndex(config)`
|
|
320
367
|
|
|
@@ -322,9 +369,9 @@ Splits `urls` into chunks of at most `maxPerFile` (default: `MAX_URLS_PER_SITEMA
|
|
|
322
369
|
function generateSitemapIndex(config: SitemapIndexConfig): string;
|
|
323
370
|
```
|
|
324
371
|
|
|
325
|
-
| Prop | Type | Description
|
|
326
|
-
| ---------- | --------------------- |
|
|
327
|
-
| `sitemaps` | `SitemapIndexEntry[]` | Array of `{ loc: string; lastmod?: string }` |
|
|
372
|
+
| Prop | Type | Description |
|
|
373
|
+
| ---------- | --------------------- | ---------------------------------------------------- |
|
|
374
|
+
| `sitemaps` | `SitemapIndexEntry[]` | Array of `{ loc: string; lastmod?: string }` entries |
|
|
328
375
|
|
|
329
376
|
### `validateSitemapUrl(url)`
|
|
330
377
|
|
|
@@ -332,47 +379,138 @@ function generateSitemapIndex(config: SitemapIndexConfig): string;
|
|
|
332
379
|
function validateSitemapUrl(url: SitemapURL): SitemapValidationResult;
|
|
333
380
|
```
|
|
334
381
|
|
|
335
|
-
Returns `{ valid: boolean; errors: string[]; warnings: string[] }`.
|
|
382
|
+
Returns `{ valid: boolean; errors: string[]; warnings: string[] }`. Never throws.
|
|
383
|
+
|
|
384
|
+
### `toNextSitemap(urls)` — from `@power-seo/sitemap/next`
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
import { toNextSitemap } from '@power-seo/sitemap/next';
|
|
388
|
+
|
|
389
|
+
function toNextSitemap(urls: SitemapURL[]): NextSitemapEntry[];
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Converts a `SitemapURL[]` to the array format expected by Next.js App Router's `app/sitemap.ts` file convention. Invalid URLs (per `validateSitemapUrl`) are filtered out automatically. `lastmod` strings are converted to `Date` objects; `changefreq` is mapped to `changeFrequency`.
|
|
393
|
+
|
|
394
|
+
| Field | Type | Description |
|
|
395
|
+
| ----------------- | ---------------- | ------------------------------------ |
|
|
396
|
+
| `url` | `string` | Absolute URL (`loc`) |
|
|
397
|
+
| `lastModified` | `Date \| string` | From `lastmod` (converted to `Date`) |
|
|
398
|
+
| `changeFrequency` | `string` | From `changefreq` |
|
|
399
|
+
| `priority` | `number` | From `priority` |
|
|
336
400
|
|
|
337
401
|
---
|
|
338
402
|
|
|
339
|
-
##
|
|
403
|
+
## Types
|
|
404
|
+
|
|
405
|
+
| Type | Description |
|
|
406
|
+
| ------------------------- | --------------------------------------------------------------------------------------------- |
|
|
407
|
+
| `SitemapConfig` | `{ hostname: string; urls: SitemapURL[]; maxUrlsPerSitemap?: number; outputDir?: string }` |
|
|
408
|
+
| `SitemapURL` | Single URL entry — see field table below |
|
|
409
|
+
| `SitemapImage` | `{ loc: string; caption?: string; geoLocation?: string; title?: string; license?: string }` |
|
|
410
|
+
| `SitemapVideo` | Video extension entry with `thumbnailLoc`, `title`, `description`, and optional fields |
|
|
411
|
+
| `SitemapNews` | `{ publication: { name: string; language: string }; publicationDate: string; title: string }` |
|
|
412
|
+
| `SitemapIndexConfig` | `{ sitemaps: SitemapIndexEntry[] }` |
|
|
413
|
+
| `SitemapIndexEntry` | `{ loc: string; lastmod?: string }` |
|
|
414
|
+
| `SitemapValidationResult` | `{ valid: boolean; errors: string[]; warnings: string[] }` |
|
|
415
|
+
|
|
416
|
+
### `SitemapURL` Fields
|
|
417
|
+
|
|
418
|
+
| Prop | Type | Default | Description |
|
|
419
|
+
| ------------ | --------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------ |
|
|
420
|
+
| `loc` | `string` | — | **Required.** URL path (e.g. `/about`) or absolute URL. Hostname is prepended to relative paths. |
|
|
421
|
+
| `lastmod` | `string` | — | Last modified date — ISO 8601 or `YYYY-MM-DD` |
|
|
422
|
+
| `changefreq` | `'always' \| 'hourly' \| 'daily' \| 'weekly' \| 'monthly' \| 'yearly' \| 'never'` | — | Suggested crawl frequency |
|
|
423
|
+
| `priority` | `number` | (no tag emitted) | Priority 0.0–1.0. When omitted, no `<priority>` tag is written. |
|
|
424
|
+
| `images` | `SitemapImage[]` | — | Image extension entries — emits `<image:image>` blocks |
|
|
425
|
+
| `videos` | `SitemapVideo[]` | — | Video extension entries — emits `<video:video>` blocks |
|
|
426
|
+
| `news` | `SitemapNews` | — | News extension entry — emits `<news:news>` block |
|
|
427
|
+
|
|
428
|
+
### Constants
|
|
429
|
+
|
|
430
|
+
| Constant | Value | Description |
|
|
431
|
+
| ------------------------ | ------------ | ------------------------------------------------------------- |
|
|
432
|
+
| `MAX_URLS_PER_SITEMAP` | `50_000` | Maximum URLs allowed per sitemap file (spec limit) |
|
|
433
|
+
| `MAX_SITEMAP_SIZE_BYTES` | `52_428_800` | Maximum sitemap file size in bytes (50 MB = 50 × 1024 × 1024) |
|
|
340
434
|
|
|
341
|
-
|
|
342
|
-
- PRs: [github.com/cybercraftbd/power-seo/pulls](https://github.com/cybercraftbd/power-seo/pulls)
|
|
343
|
-
- Development setup:
|
|
344
|
-
1. `pnpm i`
|
|
345
|
-
2. `pnpm build`
|
|
346
|
-
3. `pnpm test`
|
|
435
|
+
---
|
|
347
436
|
|
|
348
|
-
|
|
437
|
+
## Use Cases
|
|
349
438
|
|
|
350
|
-
- `
|
|
351
|
-
-
|
|
439
|
+
- **Next.js App Router** — generate sitemaps in `app/sitemap.xml/route.ts` at request time or build time
|
|
440
|
+
- **E-commerce catalogs** — product image sitemaps with `<image:image>` for every listing; keep Google Images up to date
|
|
441
|
+
- **News publishers** — `<news:news>` extension for Google News sitemap submission
|
|
442
|
+
- **Multi-locale sites** — separate sitemaps per locale with a unified sitemap index
|
|
443
|
+
- **Programmatic SEO** — generate sitemaps for thousands of auto-generated pages with no memory overhead
|
|
444
|
+
- **Large sites** — automatic splitting at 50,000 URLs per file with a generated index
|
|
445
|
+
- **Video platforms** — `<video:video>` extension with title, description, and thumbnail for video SEO
|
|
446
|
+
- **CI/CD pipelines** — validate URL entries with `validateSitemapUrl()` as part of pull request checks
|
|
352
447
|
|
|
353
448
|
---
|
|
354
449
|
|
|
355
|
-
##
|
|
450
|
+
## Architecture Overview
|
|
451
|
+
|
|
452
|
+
- **Pure TypeScript** — no compiled binary, no native modules
|
|
453
|
+
- **Zero runtime dependencies** — only `@power-seo/core` as a peer dependency
|
|
454
|
+
- **Framework-agnostic** — works in any JavaScript environment that supports ES2020+
|
|
455
|
+
- **SSR compatible** — safe to run in Next.js Server Components, Remix loaders, or Express handlers
|
|
456
|
+
- **Edge runtime safe** — no `fs`, no `path`, no Node.js-specific APIs; runs in Cloudflare Workers, Vercel Edge, Deno
|
|
457
|
+
- **Synchronous generator streaming** — `streamSitemap()` uses `function*` — no async overhead, no backpressure complexity
|
|
458
|
+
- **Auto namespace detection** — `generateSitemap()` only adds `xmlns:image`, `xmlns:video`, `xmlns:news` declarations when the URL set actually uses those extensions
|
|
459
|
+
- **Tree-shakeable** — `"sideEffects": false` with named exports per function
|
|
460
|
+
- **Dual ESM + CJS** — ships both formats via tsup for any bundler or `require()` usage
|
|
461
|
+
|
|
462
|
+
---
|
|
356
463
|
|
|
357
|
-
|
|
464
|
+
## Supply Chain Security
|
|
358
465
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
466
|
+
- No install scripts (`postinstall`, `preinstall`)
|
|
467
|
+
- No runtime network access
|
|
468
|
+
- No `eval` or dynamic code execution
|
|
469
|
+
- npm provenance enabled — every release is signed via Sigstore through GitHub Actions
|
|
470
|
+
- CI-signed builds — all releases published via verified `github.com/CyberCraftBD/power-seo` workflow
|
|
471
|
+
- Safe for SSR, Edge, and server environments
|
|
365
472
|
|
|
366
473
|
---
|
|
367
474
|
|
|
368
|
-
##
|
|
475
|
+
## The [@power-seo](https://www.npmjs.com/org/power-seo) Ecosystem
|
|
369
476
|
|
|
370
|
-
|
|
477
|
+
All 17 packages are independently installable — use only what you need.
|
|
478
|
+
|
|
479
|
+
| Package | Install | Description |
|
|
480
|
+
| ------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------- |
|
|
481
|
+
| [`@power-seo/core`](https://www.npmjs.com/package/@power-seo/core) | `npm i @power-seo/core` | Framework-agnostic utilities, types, validators, and constants |
|
|
482
|
+
| [`@power-seo/react`](https://www.npmjs.com/package/@power-seo/react) | `npm i @power-seo/react` | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs |
|
|
483
|
+
| [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta) | `npm i @power-seo/meta` | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR |
|
|
484
|
+
| [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 20 builders + 18 React components |
|
|
485
|
+
| [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components |
|
|
486
|
+
| [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability) | `npm i @power-seo/readability` | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI |
|
|
487
|
+
| [`@power-seo/preview`](https://www.npmjs.com/package/@power-seo/preview) | `npm i @power-seo/preview` | SERP, Open Graph, and Twitter/X Card preview generators |
|
|
488
|
+
| [`@power-seo/sitemap`](https://www.npmjs.com/package/@power-seo/sitemap) | `npm i @power-seo/sitemap` | XML sitemap generation, streaming, index splitting, and validation |
|
|
489
|
+
| [`@power-seo/redirects`](https://www.npmjs.com/package/@power-seo/redirects) | `npm i @power-seo/redirects` | Redirect engine with Next.js, Remix, and Express adapters |
|
|
490
|
+
| [`@power-seo/links`](https://www.npmjs.com/package/@power-seo/links) | `npm i @power-seo/links` | Link graph analysis — orphan detection, suggestions, equity scoring |
|
|
491
|
+
| [`@power-seo/audit`](https://www.npmjs.com/package/@power-seo/audit) | `npm i @power-seo/audit` | Full SEO audit engine — meta, content, structure, performance rules |
|
|
492
|
+
| [`@power-seo/images`](https://www.npmjs.com/package/@power-seo/images) | `npm i @power-seo/images` | Image SEO — alt text, lazy loading, format analysis, image sitemaps |
|
|
493
|
+
| [`@power-seo/ai`](https://www.npmjs.com/package/@power-seo/ai) | `npm i @power-seo/ai` | LLM-agnostic AI prompt templates and parsers for SEO tasks |
|
|
494
|
+
| [`@power-seo/analytics`](https://www.npmjs.com/package/@power-seo/analytics) | `npm i @power-seo/analytics` | Merge GSC + audit data, trend analysis, ranking insights, dashboard |
|
|
495
|
+
| [`@power-seo/search-console`](https://www.npmjs.com/package/@power-seo/search-console) | `npm i @power-seo/search-console` | Google Search Console API — OAuth2, service account, URL inspection |
|
|
496
|
+
| [`@power-seo/integrations`](https://www.npmjs.com/package/@power-seo/integrations) | `npm i @power-seo/integrations` | Semrush and Ahrefs API clients with rate limiting and pagination |
|
|
497
|
+
| [`@power-seo/tracking`](https://www.npmjs.com/package/@power-seo/tracking) | `npm i @power-seo/tracking` | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management |
|
|
371
498
|
|
|
372
499
|
---
|
|
373
500
|
|
|
374
501
|
## Keywords
|
|
375
502
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
503
|
+
xml sitemap generator typescript · sitemap npm package · nextjs sitemap · streaming sitemap · sitemap index generator · image sitemap extension · video sitemap extension · news sitemap google · split sitemap 50000 urls · sitemap validation · edge runtime sitemap · remix sitemap · programmatic seo sitemap · sitemap generator zero dependencies · typescript xml sitemap · sitemap url priority · crawl budget optimization · sitemap changelog · google sitemap spec · seo sitemap typescript
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## About [CyberCraft Bangladesh](https://ccbd.dev)
|
|
508
|
+
|
|
509
|
+
**[CyberCraft Bangladesh](https://ccbd.dev)** is a Bangladesh-based enterprise-grade software development and Full Stack SEO service provider company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies.
|
|
510
|
+
|
|
511
|
+
[](https://ccbd.dev)
|
|
512
|
+
[](https://github.com/cybercraftbd)
|
|
513
|
+
[](https://www.npmjs.com/org/power-seo)
|
|
514
|
+
[](mailto:info@ccbd.dev)
|
|
515
|
+
|
|
516
|
+
© 2026 [CyberCraft Bangladesh](https://ccbd.dev) · Released under the [MIT License](../../LICENSE)
|