@earlyseo/blog 1.0.6 → 1.0.7

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
@@ -26,8 +26,8 @@ npx @earlyseo/blog init
26
26
  The CLI will detect your Next.js project, ask for your site ID, and generate:
27
27
  - `app/blog/page.tsx` — Paginated blog listing
28
28
  - `app/blog/[slug]/page.tsx` — Article detail with full SEO metadata
29
- - `app/sitemap.ts` — Blog URLs added to sitemap automatically
30
- - `.env.local` — `EARLYSEO_SITE_ID` and `NEXT_PUBLIC_BASE_URL` added automatically
29
+ - `app/blog/sitemap.ts` — Blog sitemap at `/blog/sitemap.xml` (auto-detects base URL from Host header)
30
+ - `.env.local` — `EARLYSEO_SITE_ID` added automatically
31
31
 
32
32
  That's it — run `npm run dev` and visit `/blog`.
33
33
 
@@ -79,38 +79,39 @@ export const generateMetadata = createBlogPostMetadata({ siteId, siteName: "My S
79
79
 
80
80
  That's it! Articles published from EarlySEO automatically appear on your blog.
81
81
 
82
- ### 5. Add sitemap entries
82
+ ### 5. Add blog sitemap
83
83
 
84
- If you already have an existing `app/sitemap.ts`, merge blog entries into it:
84
+ The recommended approach a dedicated blog sitemap at `/blog/sitemap.xml`:
85
+
86
+ ```tsx
87
+ // app/blog/sitemap.ts
88
+ import { createBlogSitemap } from "@earlyseo/blog/next";
89
+
90
+ const siteId = process.env.EARLYSEO_SITE_ID!;
91
+
92
+ // baseUrl is auto-detected from NEXT_PUBLIC_BASE_URL or the request Host header
93
+ export default createBlogSitemap({ siteId });
94
+ ```
95
+
96
+ Or merge blog entries into your existing `app/sitemap.ts`:
85
97
 
86
98
  ```tsx
87
99
  import { getBlogSitemapEntries } from "@earlyseo/blog/next";
88
100
  import type { MetadataRoute } from "next";
89
101
 
90
102
  const siteId = process.env.EARLYSEO_SITE_ID!;
91
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? "https://example.com";
92
103
 
93
104
  export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
94
- const blogEntries = await getBlogSitemapEntries({ siteId, baseUrl });
105
+ const blogEntries = await getBlogSitemapEntries({ siteId });
95
106
 
96
107
  return [
97
- { url: baseUrl, lastModified: new Date() },
108
+ { url: "https://example.com", lastModified: new Date() },
98
109
  ...blogEntries,
99
110
  ];
100
111
  }
101
112
  ```
102
113
 
103
- Or create a dedicated blog sitemap:
104
-
105
- ```tsx
106
- // app/blog/sitemap.ts
107
- import { createBlogSitemap } from "@earlyseo/blog/next";
108
-
109
- const siteId = process.env.EARLYSEO_SITE_ID!;
110
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? "https://example.com";
111
-
112
- export default createBlogSitemap({ siteId, baseUrl });
113
- ```
114
+ `baseUrl` is resolved automatically: explicit option → `NEXT_PUBLIC_BASE_URL` env var → request `Host` header.
114
115
 
115
116
  ---
116
117
 
@@ -1,7 +1,11 @@
1
1
  import type { EarlySeoConfig } from "../types";
2
2
  export interface BlogSitemapOptions extends EarlySeoConfig {
3
- /** Your site's public base URL (e.g. "https://example.com") */
4
- baseUrl: string;
3
+ /**
4
+ * Your site's public base URL (e.g. "https://example.com").
5
+ * If omitted, falls back to NEXT_PUBLIC_BASE_URL env var,
6
+ * then to the request Host header (via next/headers).
7
+ */
8
+ baseUrl?: string;
5
9
  /** Blog base path (default: "/blog") */
6
10
  basePath?: string;
7
11
  /** Change frequency hint for sitemap (default: "weekly") */
@@ -24,7 +28,7 @@ export interface SitemapEntry {
24
28
  export declare function getBlogSitemapEntries(options: BlogSitemapOptions): Promise<SitemapEntry[]>;
25
29
  /**
26
30
  * Creates a Next.js App Router sitemap function that returns blog article entries.
27
- * Use as the default export of `app/blog/sitemap.ts` or merge into `app/sitemap.ts`.
31
+ * Use as the default export of `app/blog/sitemap.ts` (serves `/blog/sitemap.xml`).
28
32
  */
29
33
  export declare function createBlogSitemap(options: BlogSitemapOptions): () => Promise<SitemapEntry[]>;
30
34
  //# sourceMappingURL=sitemap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/next/sitemap.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,eAAe,CAAC,EACZ,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,CAAC;IACZ,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC7B,eAAe,CAAC,EACZ,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,YAAY,EAAE,CAAC,CA6CzB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,SAC1B,OAAO,CAAC,YAAY,EAAE,CAAC,CAGzD"}
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/next/sitemap.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,eAAe,CAAC,EACZ,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,CAAC;IACZ,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC7B,eAAe,CAAC,EACZ,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA2BD;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,YAAY,EAAE,CAAC,CA8CzB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,SAC1B,OAAO,CAAC,YAAY,EAAE,CAAC,CAGzD"}
@@ -2,15 +2,15 @@
2
2
  // @earlyseo/blog — Next.js Sitemap Helper
3
3
  // ─────────────────────────────────────────────────────────────────────────────
4
4
  // Generates sitemap entries for all published blog articles.
5
- // Designed for Next.js App Router `sitemap.ts` files.
5
+ // Designed for Next.js App Router `app/blog/sitemap.ts` files.
6
6
  //
7
7
  // Usage:
8
- // // app/sitemap.ts (or app/blog/sitemap.ts)
8
+ // // app/blog/sitemap.ts → serves /blog/sitemap.xml
9
9
  // import { createBlogSitemap } from "@earlyseo/blog/next";
10
10
  //
11
11
  // const siteId = process.env.EARLYSEO_SITE_ID!;
12
- // const blogSitemap = createBlogSitemap({ siteId, baseUrl: "https://example.com" });
13
- // export default blogSitemap;
12
+ // export default createBlogSitemap({ siteId });
13
+ // // baseUrl is auto-detected from NEXT_PUBLIC_BASE_URL or the request host
14
14
  //
15
15
  // // Or merge with your own sitemap entries:
16
16
  // import { getBlogSitemapEntries } from "@earlyseo/blog/next";
@@ -18,7 +18,6 @@
18
18
  // export default async function sitemap() {
19
19
  // const blogEntries = await getBlogSitemapEntries({
20
20
  // siteId: process.env.EARLYSEO_SITE_ID!,
21
- // baseUrl: "https://example.com",
22
21
  // });
23
22
  // return [
24
23
  // { url: "https://example.com", lastModified: new Date() },
@@ -27,12 +26,37 @@
27
26
  // }
28
27
  // ─────────────────────────────────────────────────────────────────────────────
29
28
  import { EarlySeoClient } from "../client";
29
+ /**
30
+ * Resolve the base URL from: explicit option → NEXT_PUBLIC_BASE_URL → Host header.
31
+ */
32
+ async function resolveBaseUrl(explicit) {
33
+ if (explicit)
34
+ return explicit;
35
+ const envUrl = process.env.NEXT_PUBLIC_BASE_URL;
36
+ if (envUrl)
37
+ return envUrl;
38
+ // Fallback: read host from the incoming request via next/headers
39
+ try {
40
+ const { headers } = await import("next/headers");
41
+ const headerStore = await headers();
42
+ const host = headerStore.get("host");
43
+ if (host) {
44
+ const proto = headerStore.get("x-forwarded-proto") ?? "https";
45
+ return `${proto}://${host}`;
46
+ }
47
+ }
48
+ catch {
49
+ // next/headers unavailable (e.g. build time) — fall through
50
+ }
51
+ return "https://localhost:3000";
52
+ }
30
53
  /**
31
54
  * Fetches all published blog articles and returns an array of sitemap entries.
32
55
  * Use this when you want to merge blog entries into an existing sitemap.
33
56
  */
34
57
  export async function getBlogSitemapEntries(options) {
35
- const { siteId, cdnBaseUrl, baseUrl, basePath = "/blog", changeFrequency = "weekly", priority = 0.7, fetchInit, } = options;
58
+ const { siteId, cdnBaseUrl, baseUrl: explicitBaseUrl, basePath = "/blog", changeFrequency = "weekly", priority = 0.7, fetchInit, } = options;
59
+ const baseUrl = await resolveBaseUrl(explicitBaseUrl);
36
60
  const client = new EarlySeoClient({ siteId, cdnBaseUrl }, fetchInit);
37
61
  const entries = [];
38
62
  const manifest = await client.getManifest();
@@ -66,7 +90,7 @@ export async function getBlogSitemapEntries(options) {
66
90
  }
67
91
  /**
68
92
  * Creates a Next.js App Router sitemap function that returns blog article entries.
69
- * Use as the default export of `app/blog/sitemap.ts` or merge into `app/sitemap.ts`.
93
+ * Use as the default export of `app/blog/sitemap.ts` (serves `/blog/sitemap.xml`).
70
94
  */
71
95
  export function createBlogSitemap(options) {
72
96
  return async function sitemap() {
@@ -1 +1 @@
1
- {"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../../src/next/sitemap.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,0CAA0C;AAC1C,gFAAgF;AAChF,6DAA6D;AAC7D,sDAAsD;AACtD,EAAE;AACF,SAAS;AACT,gDAAgD;AAChD,6DAA6D;AAC7D,EAAE;AACF,kDAAkD;AAClD,uFAAuF;AACvF,gCAAgC;AAChC,EAAE;AACF,+CAA+C;AAC/C,iEAAiE;AACjE,EAAE;AACF,8CAA8C;AAC9C,wDAAwD;AACxD,+CAA+C;AAC/C,wCAAwC;AACxC,UAAU;AACV,eAAe;AACf,kEAAkE;AAClE,wBAAwB;AACxB,SAAS;AACT,MAAM;AACN,gFAAgF;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAqC3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAA2B;IAE3B,MAAM,EACJ,MAAM,EACN,UAAU,EACV,OAAO,EACP,QAAQ,GAAG,OAAO,EAClB,eAAe,GAAG,QAAQ,EAC1B,QAAQ,GAAG,GAAG,EACd,SAAS,GACV,GAAG,OAAO,CAAC;IAEZ,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,SAAS,CAAC,CAAC;IACrE,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC;IAE9B,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEpD,gCAAgC;IAChC,OAAO,CAAC,IAAI,CAAC;QACX,GAAG,EAAE,GAAG,cAAc,GAAG,cAAc,EAAE;QACzC,YAAY,EAAE,QAAQ,CAAC,SAAS;QAChC,eAAe;QACf,QAAQ,EAAE,QAAQ,GAAG,GAAG;KACzB,CAAC,CAAC;IAEH,oDAAoD;IACpD,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;IACvC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC;gBACX,GAAG,EAAE,GAAG,cAAc,GAAG,cAAc,IAAI,OAAO,CAAC,IAAI,EAAE;gBACzD,YAAY,EAAE,OAAO,CAAC,SAAS;gBAC/B,eAAe;gBACf,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,OAAO,KAAK,UAAU,OAAO;QAC3B,OAAO,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../../src/next/sitemap.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earlyseo/blog",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Drop-in blog integration for React & Next.js — powered by EarlySEO. Articles are served from EarlySEO's CDN. Just add your site ID and render.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/init.mjs CHANGED
@@ -101,23 +101,13 @@ export const generateMetadata = createBlogPostMetadata({
101
101
  }
102
102
 
103
103
  function blogSitemapPage(siteId) {
104
- return `import { getBlogSitemapEntries } from "@earlyseo/blog/next";
105
- import type { MetadataRoute } from "next";
104
+ return `import { createBlogSitemap } from "@earlyseo/blog/next";
106
105
 
107
106
  const siteId = process.env.EARLYSEO_SITE_ID ?? "${siteId}";
108
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? "https://example.com";
109
107
 
110
- export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
111
- const blogEntries = await getBlogSitemapEntries({
112
- siteId,
113
- baseUrl,
114
- });
115
-
116
- return [
117
- { url: baseUrl, lastModified: new Date() },
118
- ...blogEntries,
119
- ];
120
- }
108
+ // baseUrl is auto-detected from NEXT_PUBLIC_BASE_URL or the request Host header.
109
+ // You can also pass it explicitly: createBlogSitemap({ siteId, baseUrl: "https://example.com" })
110
+ export default createBlogSitemap({ siteId });
121
111
  `;
122
112
  }
123
113
 
@@ -198,8 +188,8 @@ async function main() {
198
188
  await writeFileSafe(listPagePath, blogListPage(siteId));
199
189
  await writeFileSafe(postPagePath, blogPostPage(siteId));
200
190
 
201
- // 5b. Generate sitemap (at app root)
202
- const sitemapPath = `${appDir}/sitemap.ts`;
191
+ // 5b. Generate blog sitemap (scoped to /blog/sitemap.xml)
192
+ const sitemapPath = `${blogDir}/sitemap.ts`;
203
193
  await writeFileSafe(sitemapPath, blogSitemapPage(siteId));
204
194
 
205
195
  // 6. Add EARLYSEO_SITE_ID and NEXT_PUBLIC_BASE_URL to .env.local
@@ -229,10 +219,10 @@ async function main() {
229
219
  console.log(" ✓ Setup complete! Your blog is ready at /blog");
230
220
  console.log();
231
221
  console.log(" Next steps:");
232
- console.log(" 1. Update NEXT_PUBLIC_BASE_URL in .env.local with your site URL");
222
+ console.log(" 1. Optionally set NEXT_PUBLIC_BASE_URL in .env.local (auto-detected from Host if missing)");
233
223
  console.log(" 2. Start your dev server: npm run dev");
234
224
  console.log(" 3. Visit: http://localhost:3000/blog");
235
- console.log(" 4. Sitemap available at: http://localhost:3000/sitemap.xml");
225
+ console.log(" 4. Blog sitemap at: http://localhost:3000/blog/sitemap.xml");
236
226
  console.log(" 5. Publish articles from your EarlySEO dashboard");
237
227
  console.log();
238
228
  console.log(" Docs: https://www.npmjs.com/package/@earlyseo/blog");