@onruntime/next-sitemap 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,7 @@ Dynamic sitemap generation for Next.js with automatic route discovery.
17
17
  - Multi-sitemap support with sitemap index (for sites with >50,000 URLs)
18
18
  - hreflang alternates for i18n
19
19
  - Fully static generation (SSG)
20
+ - robots.txt generation with Next.js `MetadataRoute.Robots` compatibility
20
21
 
21
22
  ## Installation
22
23
 
@@ -354,6 +355,47 @@ export async function GET() {
354
355
  </urlset>
355
356
  ```
356
357
 
358
+ ## Robots.txt (Pages Router)
359
+
360
+ For Pages Router, use `createRobotsApiHandler` to generate a `robots.txt` file. The configuration uses the same format as [Next.js `MetadataRoute.Robots`](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/robots).
361
+
362
+ ```typescript
363
+ // pages/api/robots.txt.ts
364
+ import { createRobotsApiHandler } from "@onruntime/next-sitemap/pages";
365
+
366
+ export default createRobotsApiHandler({
367
+ rules: {
368
+ userAgent: "*",
369
+ allow: "/",
370
+ disallow: ["/admin", "/private"],
371
+ },
372
+ sitemap: "https://example.com/sitemap.xml",
373
+ });
374
+ ```
375
+
376
+ Add a rewrite in `next.config.ts`:
377
+
378
+ ```typescript
379
+ {
380
+ source: "/robots.txt",
381
+ destination: "/api/robots.txt",
382
+ }
383
+ ```
384
+
385
+ **Note:** For App Router, use the [native `robots.ts` file convention](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/robots) instead.
386
+
387
+ ## Requirements
388
+
389
+ This package requires a **Node.js server runtime**. It works with:
390
+ - Vercel
391
+ - Netlify (with Next.js runtime)
392
+ - Railway, Render, Fly.io
393
+ - AWS (EC2, ECS, Lambda)
394
+ - Docker containers
395
+ - Any Node.js server
396
+
397
+ It does **not** work with static exports (`output: 'export'`) or static hosting platforms like Cloudflare Pages, Netlify (static mode), or GitHub Pages.
398
+
357
399
  ## Troubleshooting
358
400
 
359
401
  ### Dynamic routes not included in sitemap
@@ -4,7 +4,8 @@
4
4
  function calculateDepthPriority(pathname) {
5
5
  if (pathname === "/") return 1;
6
6
  const depth = pathname.split("/").filter(Boolean).length;
7
- return Math.max(0.1, 1 - depth * 0.2);
7
+ const priority = Math.max(0.1, 1 - depth * 0.2);
8
+ return Math.round(priority * 100) / 100;
8
9
  }
9
10
  function shouldExclude(pathname, exclude) {
10
11
  if (!exclude) return false;
@@ -35,11 +36,16 @@ function getChangeFreq(pathname, changeFreq) {
35
36
  }
36
37
  return changeFreq;
37
38
  }
39
+ function normalizePath(pathname) {
40
+ if (pathname === "/") return pathname;
41
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
42
+ }
38
43
  function buildUrl(baseUrl, pathname, locale, defaultLocale) {
44
+ const normalizedPath = normalizePath(pathname);
39
45
  if (!locale || locale === defaultLocale) {
40
- return `${baseUrl}${pathname}`;
46
+ return `${baseUrl}${normalizedPath}`;
41
47
  }
42
- return `${baseUrl}/${locale}${pathname}`;
48
+ return `${baseUrl}/${locale}${normalizedPath}`;
43
49
  }
44
50
  function generateSitemapXml(entries) {
45
51
  const hasAlternates = entries.some((e) => e.alternates?.languages);
package/dist/app/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
  function calculateDepthPriority(pathname) {
3
3
  if (pathname === "/") return 1;
4
4
  const depth = pathname.split("/").filter(Boolean).length;
5
- return Math.max(0.1, 1 - depth * 0.2);
5
+ const priority = Math.max(0.1, 1 - depth * 0.2);
6
+ return Math.round(priority * 100) / 100;
6
7
  }
7
8
  function shouldExclude(pathname, exclude) {
8
9
  if (!exclude) return false;
@@ -33,11 +34,16 @@ function getChangeFreq(pathname, changeFreq) {
33
34
  }
34
35
  return changeFreq;
35
36
  }
37
+ function normalizePath(pathname) {
38
+ if (pathname === "/") return pathname;
39
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
40
+ }
36
41
  function buildUrl(baseUrl, pathname, locale, defaultLocale) {
42
+ const normalizedPath = normalizePath(pathname);
37
43
  if (!locale || locale === defaultLocale) {
38
- return `${baseUrl}${pathname}`;
44
+ return `${baseUrl}${normalizedPath}`;
39
45
  }
40
- return `${baseUrl}/${locale}${pathname}`;
46
+ return `${baseUrl}/${locale}${normalizedPath}`;
41
47
  }
42
48
  function generateSitemapXml(entries) {
43
49
  const hasAlternates = entries.some((e) => e.alternates?.languages);
package/dist/index.cjs CHANGED
@@ -4,7 +4,8 @@
4
4
  function calculateDepthPriority(pathname) {
5
5
  if (pathname === "/") return 1;
6
6
  const depth = pathname.split("/").filter(Boolean).length;
7
- return Math.max(0.1, 1 - depth * 0.2);
7
+ const priority = Math.max(0.1, 1 - depth * 0.2);
8
+ return Math.round(priority * 100) / 100;
8
9
  }
9
10
  function shouldExclude(pathname, exclude) {
10
11
  if (!exclude) return false;
@@ -35,11 +36,16 @@ function getChangeFreq(pathname, changeFreq) {
35
36
  }
36
37
  return changeFreq;
37
38
  }
39
+ function normalizePath(pathname) {
40
+ if (pathname === "/") return pathname;
41
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
42
+ }
38
43
  function buildUrl(baseUrl, pathname, locale, defaultLocale) {
44
+ const normalizedPath = normalizePath(pathname);
39
45
  if (!locale || locale === defaultLocale) {
40
- return `${baseUrl}${pathname}`;
46
+ return `${baseUrl}${normalizedPath}`;
41
47
  }
42
- return `${baseUrl}/${locale}${pathname}`;
48
+ return `${baseUrl}/${locale}${normalizedPath}`;
43
49
  }
44
50
  function generateSitemapXml(entries) {
45
51
  const hasAlternates = entries.some((e) => e.alternates?.languages);
@@ -100,4 +106,5 @@ exports.generateSitemapIndexXml = generateSitemapIndexXml;
100
106
  exports.generateSitemapXml = generateSitemapXml;
101
107
  exports.getChangeFreq = getChangeFreq;
102
108
  exports.getPriority = getPriority;
109
+ exports.normalizePath = normalizePath;
103
110
  exports.shouldExclude = shouldExclude;
package/dist/index.d.cts CHANGED
@@ -92,6 +92,10 @@ interface RouteInfo {
92
92
  type PageModule = {
93
93
  generateStaticParams?: () => Promise<Record<string, string>[]>;
94
94
  };
95
+ /**
96
+ * Normalize pathname by removing trailing slash (except for root)
97
+ */
98
+ declare function normalizePath(pathname: string): string;
95
99
  /**
96
100
  * Generate the full URL for a pathname
97
101
  */
@@ -108,4 +112,4 @@ declare function generateSitemapIndexXml(baseUrl: string, sitemapCount: number,
108
112
  additionalSitemaps?: string[];
109
113
  }): string;
110
114
 
111
- export { type ChangeFrequency, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, shouldExclude };
115
+ export { type ChangeFrequency, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, normalizePath, shouldExclude };
package/dist/index.d.ts CHANGED
@@ -92,6 +92,10 @@ interface RouteInfo {
92
92
  type PageModule = {
93
93
  generateStaticParams?: () => Promise<Record<string, string>[]>;
94
94
  };
95
+ /**
96
+ * Normalize pathname by removing trailing slash (except for root)
97
+ */
98
+ declare function normalizePath(pathname: string): string;
95
99
  /**
96
100
  * Generate the full URL for a pathname
97
101
  */
@@ -108,4 +112,4 @@ declare function generateSitemapIndexXml(baseUrl: string, sitemapCount: number,
108
112
  additionalSitemaps?: string[];
109
113
  }): string;
110
114
 
111
- export { type ChangeFrequency, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, shouldExclude };
115
+ export { type ChangeFrequency, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, normalizePath, shouldExclude };
package/dist/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
  function calculateDepthPriority(pathname) {
3
3
  if (pathname === "/") return 1;
4
4
  const depth = pathname.split("/").filter(Boolean).length;
5
- return Math.max(0.1, 1 - depth * 0.2);
5
+ const priority = Math.max(0.1, 1 - depth * 0.2);
6
+ return Math.round(priority * 100) / 100;
6
7
  }
7
8
  function shouldExclude(pathname, exclude) {
8
9
  if (!exclude) return false;
@@ -33,11 +34,16 @@ function getChangeFreq(pathname, changeFreq) {
33
34
  }
34
35
  return changeFreq;
35
36
  }
37
+ function normalizePath(pathname) {
38
+ if (pathname === "/") return pathname;
39
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
40
+ }
36
41
  function buildUrl(baseUrl, pathname, locale, defaultLocale) {
42
+ const normalizedPath = normalizePath(pathname);
37
43
  if (!locale || locale === defaultLocale) {
38
- return `${baseUrl}${pathname}`;
44
+ return `${baseUrl}${normalizedPath}`;
39
45
  }
40
- return `${baseUrl}/${locale}${pathname}`;
46
+ return `${baseUrl}/${locale}${normalizedPath}`;
41
47
  }
42
48
  function generateSitemapXml(entries) {
43
49
  const hasAlternates = entries.some((e) => e.alternates?.languages);
@@ -92,4 +98,4 @@ ${allEntries}
92
98
  </sitemapindex>`;
93
99
  }
94
100
 
95
- export { buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, shouldExclude };
101
+ export { buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, normalizePath, shouldExclude };
@@ -4,7 +4,8 @@
4
4
  function calculateDepthPriority(pathname) {
5
5
  if (pathname === "/") return 1;
6
6
  const depth = pathname.split("/").filter(Boolean).length;
7
- return Math.max(0.1, 1 - depth * 0.2);
7
+ const priority = Math.max(0.1, 1 - depth * 0.2);
8
+ return Math.round(priority * 100) / 100;
8
9
  }
9
10
  function shouldExclude(pathname, exclude) {
10
11
  if (!exclude) return false;
@@ -35,11 +36,16 @@ function getChangeFreq(pathname, changeFreq) {
35
36
  }
36
37
  return changeFreq;
37
38
  }
39
+ function normalizePath(pathname) {
40
+ if (pathname === "/") return pathname;
41
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
42
+ }
38
43
  function buildUrl(baseUrl, pathname, locale, defaultLocale) {
44
+ const normalizedPath = normalizePath(pathname);
39
45
  if (!locale || locale === defaultLocale) {
40
- return `${baseUrl}${pathname}`;
46
+ return `${baseUrl}${normalizedPath}`;
41
47
  }
42
- return `${baseUrl}/${locale}${pathname}`;
48
+ return `${baseUrl}/${locale}${normalizedPath}`;
43
49
  }
44
50
  function generateSitemapXml(entries) {
45
51
  const hasAlternates = entries.some((e) => e.alternates?.languages);
@@ -94,6 +100,44 @@ ${allEntries}
94
100
  </sitemapindex>`;
95
101
  }
96
102
 
103
+ // src/pages/robots.ts
104
+ function generateRobotsTxt(config) {
105
+ const lines = [];
106
+ const rules = Array.isArray(config.rules) ? config.rules : [config.rules];
107
+ for (const rule of rules) {
108
+ const userAgents = Array.isArray(rule.userAgent) ? rule.userAgent : [rule.userAgent];
109
+ for (const userAgent of userAgents) {
110
+ lines.push(`User-agent: ${userAgent}`);
111
+ }
112
+ if (rule.allow) {
113
+ const allows = Array.isArray(rule.allow) ? rule.allow : [rule.allow];
114
+ for (const allow of allows) {
115
+ lines.push(`Allow: ${allow}`);
116
+ }
117
+ }
118
+ if (rule.disallow) {
119
+ const disallows = Array.isArray(rule.disallow) ? rule.disallow : [rule.disallow];
120
+ for (const disallow of disallows) {
121
+ lines.push(`Disallow: ${disallow}`);
122
+ }
123
+ }
124
+ if (rule.crawlDelay !== void 0) {
125
+ lines.push(`Crawl-delay: ${rule.crawlDelay}`);
126
+ }
127
+ lines.push("");
128
+ }
129
+ if (config.sitemap) {
130
+ const sitemaps = Array.isArray(config.sitemap) ? config.sitemap : [config.sitemap];
131
+ for (const sitemap of sitemaps) {
132
+ lines.push(`Sitemap: ${sitemap}`);
133
+ }
134
+ }
135
+ if (config.host) {
136
+ lines.push(`Host: ${config.host}`);
137
+ }
138
+ return lines.join("\n").trim() + "\n";
139
+ }
140
+
97
141
  // src/pages/index.ts
98
142
  function extractRoutes(pagesContext, localeSegment) {
99
143
  const routes = [];
@@ -261,7 +305,16 @@ async function getSitemapStaticPaths(options) {
261
305
  fallback: false
262
306
  };
263
307
  }
308
+ function createRobotsApiHandler(config) {
309
+ return function handler(_req, res) {
310
+ const robotsTxt = generateRobotsTxt(config);
311
+ res.setHeader("Content-Type", "text/plain");
312
+ res.status(200).send(robotsTxt);
313
+ };
314
+ }
264
315
 
316
+ exports.createRobotsApiHandler = createRobotsApiHandler;
265
317
  exports.createSitemapApiHandler = createSitemapApiHandler;
266
318
  exports.createSitemapIndexApiHandler = createSitemapIndexApiHandler;
319
+ exports.generateRobotsTxt = generateRobotsTxt;
267
320
  exports.getSitemapStaticPaths = getSitemapStaticPaths;
@@ -1,4 +1,5 @@
1
- import { NextApiRequest, NextApiResponse } from 'next';
1
+ import { MetadataRoute, NextApiRequest, NextApiResponse } from 'next';
2
+ export { MetadataRoute } from 'next';
2
3
 
3
4
  type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
4
5
  interface SitemapConfig {
@@ -72,6 +73,12 @@ type PageModule = {
72
73
  generateStaticParams?: () => Promise<Record<string, string>[]>;
73
74
  };
74
75
 
76
+ /**
77
+ * Generate robots.txt content from configuration
78
+ * Compatible with Next.js MetadataRoute.Robots
79
+ */
80
+ declare function generateRobotsTxt(config: MetadataRoute.Robots): string;
81
+
75
82
  interface CreateSitemapApiHandlerOptions extends SitemapConfig {
76
83
  /**
77
84
  * The require.context result for page discovery
@@ -110,5 +117,23 @@ declare function getSitemapStaticPaths(options: CreateSitemapApiHandlerOptions):
110
117
  }[];
111
118
  fallback: boolean;
112
119
  }>;
120
+ /**
121
+ * Create API handler for robots.txt
122
+ * Use in: pages/api/robots.txt.ts or pages/robots.txt.ts (with rewrites)
123
+ *
124
+ * @example
125
+ * // pages/api/robots.txt.ts
126
+ * import { createRobotsApiHandler } from "@onruntime/next-sitemap/pages";
127
+ *
128
+ * export default createRobotsApiHandler({
129
+ * rules: {
130
+ * userAgent: "*",
131
+ * allow: "/",
132
+ * disallow: ["/admin", "/private"],
133
+ * },
134
+ * sitemap: "https://example.com/sitemap.xml",
135
+ * });
136
+ */
137
+ declare function createRobotsApiHandler(config: MetadataRoute.Robots): (_req: NextApiRequest, res: NextApiResponse) => void;
113
138
 
114
- export { type ChangeFrequency, type CreateSitemapApiHandlerOptions, type SitemapConfig, type SitemapEntry, createSitemapApiHandler, createSitemapIndexApiHandler, getSitemapStaticPaths };
139
+ export { type ChangeFrequency, type CreateSitemapApiHandlerOptions, type SitemapConfig, type SitemapEntry, createRobotsApiHandler, createSitemapApiHandler, createSitemapIndexApiHandler, generateRobotsTxt, getSitemapStaticPaths };
@@ -1,4 +1,5 @@
1
- import { NextApiRequest, NextApiResponse } from 'next';
1
+ import { MetadataRoute, NextApiRequest, NextApiResponse } from 'next';
2
+ export { MetadataRoute } from 'next';
2
3
 
3
4
  type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
4
5
  interface SitemapConfig {
@@ -72,6 +73,12 @@ type PageModule = {
72
73
  generateStaticParams?: () => Promise<Record<string, string>[]>;
73
74
  };
74
75
 
76
+ /**
77
+ * Generate robots.txt content from configuration
78
+ * Compatible with Next.js MetadataRoute.Robots
79
+ */
80
+ declare function generateRobotsTxt(config: MetadataRoute.Robots): string;
81
+
75
82
  interface CreateSitemapApiHandlerOptions extends SitemapConfig {
76
83
  /**
77
84
  * The require.context result for page discovery
@@ -110,5 +117,23 @@ declare function getSitemapStaticPaths(options: CreateSitemapApiHandlerOptions):
110
117
  }[];
111
118
  fallback: boolean;
112
119
  }>;
120
+ /**
121
+ * Create API handler for robots.txt
122
+ * Use in: pages/api/robots.txt.ts or pages/robots.txt.ts (with rewrites)
123
+ *
124
+ * @example
125
+ * // pages/api/robots.txt.ts
126
+ * import { createRobotsApiHandler } from "@onruntime/next-sitemap/pages";
127
+ *
128
+ * export default createRobotsApiHandler({
129
+ * rules: {
130
+ * userAgent: "*",
131
+ * allow: "/",
132
+ * disallow: ["/admin", "/private"],
133
+ * },
134
+ * sitemap: "https://example.com/sitemap.xml",
135
+ * });
136
+ */
137
+ declare function createRobotsApiHandler(config: MetadataRoute.Robots): (_req: NextApiRequest, res: NextApiResponse) => void;
113
138
 
114
- export { type ChangeFrequency, type CreateSitemapApiHandlerOptions, type SitemapConfig, type SitemapEntry, createSitemapApiHandler, createSitemapIndexApiHandler, getSitemapStaticPaths };
139
+ export { type ChangeFrequency, type CreateSitemapApiHandlerOptions, type SitemapConfig, type SitemapEntry, createRobotsApiHandler, createSitemapApiHandler, createSitemapIndexApiHandler, generateRobotsTxt, getSitemapStaticPaths };
@@ -2,7 +2,8 @@
2
2
  function calculateDepthPriority(pathname) {
3
3
  if (pathname === "/") return 1;
4
4
  const depth = pathname.split("/").filter(Boolean).length;
5
- return Math.max(0.1, 1 - depth * 0.2);
5
+ const priority = Math.max(0.1, 1 - depth * 0.2);
6
+ return Math.round(priority * 100) / 100;
6
7
  }
7
8
  function shouldExclude(pathname, exclude) {
8
9
  if (!exclude) return false;
@@ -33,11 +34,16 @@ function getChangeFreq(pathname, changeFreq) {
33
34
  }
34
35
  return changeFreq;
35
36
  }
37
+ function normalizePath(pathname) {
38
+ if (pathname === "/") return pathname;
39
+ return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
40
+ }
36
41
  function buildUrl(baseUrl, pathname, locale, defaultLocale) {
42
+ const normalizedPath = normalizePath(pathname);
37
43
  if (!locale || locale === defaultLocale) {
38
- return `${baseUrl}${pathname}`;
44
+ return `${baseUrl}${normalizedPath}`;
39
45
  }
40
- return `${baseUrl}/${locale}${pathname}`;
46
+ return `${baseUrl}/${locale}${normalizedPath}`;
41
47
  }
42
48
  function generateSitemapXml(entries) {
43
49
  const hasAlternates = entries.some((e) => e.alternates?.languages);
@@ -92,6 +98,44 @@ ${allEntries}
92
98
  </sitemapindex>`;
93
99
  }
94
100
 
101
+ // src/pages/robots.ts
102
+ function generateRobotsTxt(config) {
103
+ const lines = [];
104
+ const rules = Array.isArray(config.rules) ? config.rules : [config.rules];
105
+ for (const rule of rules) {
106
+ const userAgents = Array.isArray(rule.userAgent) ? rule.userAgent : [rule.userAgent];
107
+ for (const userAgent of userAgents) {
108
+ lines.push(`User-agent: ${userAgent}`);
109
+ }
110
+ if (rule.allow) {
111
+ const allows = Array.isArray(rule.allow) ? rule.allow : [rule.allow];
112
+ for (const allow of allows) {
113
+ lines.push(`Allow: ${allow}`);
114
+ }
115
+ }
116
+ if (rule.disallow) {
117
+ const disallows = Array.isArray(rule.disallow) ? rule.disallow : [rule.disallow];
118
+ for (const disallow of disallows) {
119
+ lines.push(`Disallow: ${disallow}`);
120
+ }
121
+ }
122
+ if (rule.crawlDelay !== void 0) {
123
+ lines.push(`Crawl-delay: ${rule.crawlDelay}`);
124
+ }
125
+ lines.push("");
126
+ }
127
+ if (config.sitemap) {
128
+ const sitemaps = Array.isArray(config.sitemap) ? config.sitemap : [config.sitemap];
129
+ for (const sitemap of sitemaps) {
130
+ lines.push(`Sitemap: ${sitemap}`);
131
+ }
132
+ }
133
+ if (config.host) {
134
+ lines.push(`Host: ${config.host}`);
135
+ }
136
+ return lines.join("\n").trim() + "\n";
137
+ }
138
+
95
139
  // src/pages/index.ts
96
140
  function extractRoutes(pagesContext, localeSegment) {
97
141
  const routes = [];
@@ -259,5 +303,12 @@ async function getSitemapStaticPaths(options) {
259
303
  fallback: false
260
304
  };
261
305
  }
306
+ function createRobotsApiHandler(config) {
307
+ return function handler(_req, res) {
308
+ const robotsTxt = generateRobotsTxt(config);
309
+ res.setHeader("Content-Type", "text/plain");
310
+ res.status(200).send(robotsTxt);
311
+ };
312
+ }
262
313
 
263
- export { createSitemapApiHandler, createSitemapIndexApiHandler, getSitemapStaticPaths };
314
+ export { createRobotsApiHandler, createSitemapApiHandler, createSitemapIndexApiHandler, generateRobotsTxt, getSitemapStaticPaths };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onruntime/next-sitemap",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Dynamic sitemap generation for Next.js with automatic route discovery",
5
5
  "author": "onRuntime Studio <contact@onruntime.com>",
6
6
  "repository": {
@@ -45,6 +45,7 @@
45
45
  "@types/node": "^22.0.0",
46
46
  "next": "^16.1.1",
47
47
  "tsup": "^8",
48
+ "tsx": "^4",
48
49
  "typescript": "^5"
49
50
  },
50
51
  "keywords": [
@@ -60,6 +61,7 @@
60
61
  "scripts": {
61
62
  "build": "tsup",
62
63
  "dev": "tsup --watch",
63
- "type-check": "tsc --noEmit"
64
+ "type-check": "tsc --noEmit",
65
+ "test": "tsx --test tests/index.ts"
64
66
  }
65
67
  }