@publish.os/nextjs 0.0.1-alpha.3 → 0.0.1-alpha.4

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.
@@ -75,22 +75,28 @@ function cachedTextHeaders(contentType, options = {}) {
75
75
  headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy));
76
76
  headers.set("content-type", contentType);
77
77
  headers.set("x-content-type-options", "nosniff");
78
- if (options.etag) headers.set("etag", options.etag);
79
78
  if (options.noindex) headers.set("x-robots-tag", "noindex");
80
79
  return headers;
81
80
  }
82
81
  function createCachedTextResponse(options) {
83
82
  const status = options.status ?? 200;
84
- const method = options.method ?? options.request?.method ?? "GET";
83
+ const method = options.method ?? "GET";
85
84
  const headers = cachedTextHeaders(options.contentType, options);
86
- const isNotModified = status === 200 && options.etag && options.request?.headers.get("if-none-match") === options.etag;
87
- return new Response(
88
- method === "HEAD" || isNotModified ? null : options.body,
89
- {
90
- headers,
91
- status: isNotModified ? 304 : status
92
- }
93
- );
85
+ return new Response(method === "HEAD" ? null : options.body, {
86
+ headers,
87
+ status
88
+ });
89
+ }
90
+
91
+ // src/kernel/routes/metadata/canonical-url.ts
92
+ function canonicalUrl(manifest, path) {
93
+ const origin = manifest.site.url?.replace(/\/+$/, "");
94
+ if (!origin) return path;
95
+ try {
96
+ return new URL(path, `${origin}/`).toString();
97
+ } catch {
98
+ return path;
99
+ }
94
100
  }
95
101
 
96
102
  // src/kernel/routes/metadata/robots.ts
@@ -98,7 +104,11 @@ async function robotsTxt(manifest) {
98
104
  "use cache";
99
105
  cacheLife("page");
100
106
  cacheTag(tags.site(), tags.robots(), tags.manifest(manifest.contentHash));
101
- return "User-agent: *\nAllow: /\nSitemap: /sitemap.xml\n";
107
+ const sitemapUrl = canonicalUrl(manifest, "/sitemap.xml");
108
+ return `User-agent: *
109
+ Allow: /
110
+ Sitemap: ${sitemapUrl}
111
+ `;
102
112
  }
103
113
  function createRobotsTxtRoute(manifest) {
104
114
  return async function GET() {
@@ -100,22 +100,28 @@ function cachedTextHeaders(contentType, options = {}) {
100
100
  headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy));
101
101
  headers.set("content-type", contentType);
102
102
  headers.set("x-content-type-options", "nosniff");
103
- if (options.etag) headers.set("etag", options.etag);
104
103
  if (options.noindex) headers.set("x-robots-tag", "noindex");
105
104
  return headers;
106
105
  }
107
106
  function createCachedTextResponse(options) {
108
107
  const status = options.status ?? 200;
109
- const method = options.method ?? options.request?.method ?? "GET";
108
+ const method = options.method ?? "GET";
110
109
  const headers = cachedTextHeaders(options.contentType, options);
111
- const isNotModified = status === 200 && options.etag && options.request?.headers.get("if-none-match") === options.etag;
112
- return new Response(
113
- method === "HEAD" || isNotModified ? null : options.body,
114
- {
115
- headers,
116
- status: isNotModified ? 304 : status
117
- }
118
- );
110
+ return new Response(method === "HEAD" ? null : options.body, {
111
+ headers,
112
+ status
113
+ });
114
+ }
115
+
116
+ // src/kernel/routes/metadata/canonical-url.ts
117
+ function canonicalUrl(manifest, path) {
118
+ const origin = manifest.site.url?.replace(/\/+$/, "");
119
+ if (!origin) return path;
120
+ try {
121
+ return new URL(path, `${origin}/`).toString();
122
+ } catch {
123
+ return path;
124
+ }
119
125
  }
120
126
 
121
127
  // src/kernel/routes/metadata/sitemap.ts
@@ -132,7 +138,9 @@ async function sitemapXml(manifest) {
132
138
  ...manifest.pages.filter((page) => page.status === "published").map((page) => page.path)
133
139
  ];
134
140
  const uniqueUrls = [...new Set(urls)];
135
- const body = uniqueUrls.map((url) => ` <url><loc>${xmlEscape(url)}</loc></url>`).join("\n");
141
+ const body = uniqueUrls.map(
142
+ (url) => ` <url><loc>${xmlEscape(canonicalUrl(manifest, url))}</loc></url>`
143
+ ).join("\n");
136
144
  return `<?xml version="1.0" encoding="UTF-8"?>
137
145
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
138
146
  ${body}
@@ -148,22 +156,24 @@ function createSitemapXmlRoute(manifest) {
148
156
  };
149
157
  }
150
158
  async function sitemapMarkdown(manifest, artifactManifest) {
151
- const groups = Object.values(manifest.groups).sort((a, b) => a.path.localeCompare(b.path)).map((group) => `- [${group.title}](${group.path})`);
159
+ const groups = Object.values(manifest.groups).sort((a, b) => a.path.localeCompare(b.path)).map(
160
+ (group) => `- [${group.title}](${canonicalUrl(manifest, group.path)})`
161
+ );
152
162
  const pages = manifest.pages.filter((page) => page.status === "published").sort((a, b) => a.path.localeCompare(b.path)).map((page) => {
153
163
  const markdownPath = artifactManifest.byHtmlPath[page.path];
154
- const markdown = markdownPath ? ` ([Markdown](${markdownPath}))` : "";
155
- return `- [${page.title}](${page.path})${markdown}`;
164
+ const markdown = markdownPath ? ` ([Markdown](${canonicalUrl(manifest, markdownPath)}))` : "";
165
+ return `- [${page.title}](${canonicalUrl(manifest, page.path)})${markdown}`;
156
166
  });
157
167
  return [
158
168
  `# ${manifest.site.name} Sitemap`,
159
169
  "## Agent indexes",
160
- "- [LLMS index](/llms.txt)",
161
- "- [Full LLMS index](/llms-full.txt)",
162
- "- [XML sitemap](/sitemap.xml)",
170
+ `- [LLMS index](${canonicalUrl(manifest, "/llms.txt")})`,
171
+ `- [Full LLMS index](${canonicalUrl(manifest, "/llms-full.txt")})`,
172
+ `- [XML sitemap](${canonicalUrl(manifest, "/sitemap.xml")})`,
163
173
  "## Sections",
164
- groups.length ? groups.join("\n") : "- [Home](/)",
174
+ groups.length ? groups.join("\n") : `- [Home](${canonicalUrl(manifest, "/")})`,
165
175
  "## Pages",
166
- pages.length ? pages.join("\n") : "- [Home](/)",
176
+ pages.length ? pages.join("\n") : `- [Home](${canonicalUrl(manifest, "/")})`,
167
177
  ""
168
178
  ].join("\n\n");
169
179
  }
@@ -75,22 +75,28 @@ function cachedTextHeaders(contentType, options = {}) {
75
75
  headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy));
76
76
  headers.set("content-type", contentType);
77
77
  headers.set("x-content-type-options", "nosniff");
78
- if (options.etag) headers.set("etag", options.etag);
79
78
  if (options.noindex) headers.set("x-robots-tag", "noindex");
80
79
  return headers;
81
80
  }
82
81
  function createCachedTextResponse(options) {
83
82
  const status = options.status ?? 200;
84
- const method = options.method ?? options.request?.method ?? "GET";
83
+ const method = options.method ?? "GET";
85
84
  const headers = cachedTextHeaders(options.contentType, options);
86
- const isNotModified = status === 200 && options.etag && options.request?.headers.get("if-none-match") === options.etag;
87
- return new Response(
88
- method === "HEAD" || isNotModified ? null : options.body,
89
- {
90
- headers,
91
- status: isNotModified ? 304 : status
92
- }
93
- );
85
+ return new Response(method === "HEAD" ? null : options.body, {
86
+ headers,
87
+ status
88
+ });
89
+ }
90
+
91
+ // src/kernel/routes/metadata/canonical-url.ts
92
+ function canonicalUrl(manifest, path) {
93
+ const origin = manifest.site.url?.replace(/\/+$/, "");
94
+ if (!origin) return path;
95
+ try {
96
+ return new URL(path, `${origin}/`).toString();
97
+ } catch {
98
+ return path;
99
+ }
94
100
  }
95
101
 
96
102
  // src/kernel/routes/metadata/sitemap.ts
@@ -107,7 +113,9 @@ async function sitemapXml(manifest) {
107
113
  ...manifest.pages.filter((page) => page.status === "published").map((page) => page.path)
108
114
  ];
109
115
  const uniqueUrls = [...new Set(urls)];
110
- const body = uniqueUrls.map((url) => ` <url><loc>${xmlEscape(url)}</loc></url>`).join("\n");
116
+ const body = uniqueUrls.map(
117
+ (url) => ` <url><loc>${xmlEscape(canonicalUrl(manifest, url))}</loc></url>`
118
+ ).join("\n");
111
119
  return `<?xml version="1.0" encoding="UTF-8"?>
112
120
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
113
121
  ${body}
@@ -123,22 +131,24 @@ function createSitemapXmlRoute(manifest) {
123
131
  };
124
132
  }
125
133
  async function sitemapMarkdown(manifest, artifactManifest) {
126
- const groups = Object.values(manifest.groups).sort((a, b) => a.path.localeCompare(b.path)).map((group) => `- [${group.title}](${group.path})`);
134
+ const groups = Object.values(manifest.groups).sort((a, b) => a.path.localeCompare(b.path)).map(
135
+ (group) => `- [${group.title}](${canonicalUrl(manifest, group.path)})`
136
+ );
127
137
  const pages = manifest.pages.filter((page) => page.status === "published").sort((a, b) => a.path.localeCompare(b.path)).map((page) => {
128
138
  const markdownPath = artifactManifest.byHtmlPath[page.path];
129
- const markdown = markdownPath ? ` ([Markdown](${markdownPath}))` : "";
130
- return `- [${page.title}](${page.path})${markdown}`;
139
+ const markdown = markdownPath ? ` ([Markdown](${canonicalUrl(manifest, markdownPath)}))` : "";
140
+ return `- [${page.title}](${canonicalUrl(manifest, page.path)})${markdown}`;
131
141
  });
132
142
  return [
133
143
  `# ${manifest.site.name} Sitemap`,
134
144
  "## Agent indexes",
135
- "- [LLMS index](/llms.txt)",
136
- "- [Full LLMS index](/llms-full.txt)",
137
- "- [XML sitemap](/sitemap.xml)",
145
+ `- [LLMS index](${canonicalUrl(manifest, "/llms.txt")})`,
146
+ `- [Full LLMS index](${canonicalUrl(manifest, "/llms-full.txt")})`,
147
+ `- [XML sitemap](${canonicalUrl(manifest, "/sitemap.xml")})`,
138
148
  "## Sections",
139
- groups.length ? groups.join("\n") : "- [Home](/)",
149
+ groups.length ? groups.join("\n") : `- [Home](${canonicalUrl(manifest, "/")})`,
140
150
  "## Pages",
141
- pages.length ? pages.join("\n") : "- [Home](/)",
151
+ pages.length ? pages.join("\n") : `- [Home](${canonicalUrl(manifest, "/")})`,
142
152
  ""
143
153
  ].join("\n\n");
144
154
  }
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@publish.os/nextjs",
3
- "version": "0.0.1-alpha.3",
3
+ "version": "0.0.1-alpha.4",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
+ "engines": {
7
+ "node": ">=22.13"
8
+ },
6
9
  "repository": {
7
10
  "type": "git",
8
11
  "url": "git+https://github.com/PublishOS/publishOS.git",
@@ -10,6 +13,7 @@
10
13
  },
11
14
  "files": [
12
15
  "dist/**",
16
+ "release/**",
13
17
  "package.json",
14
18
  "README.md"
15
19
  ],
@@ -54,6 +58,26 @@
54
58
  "types": "./dist/kernel/defaults.registry.d.ts",
55
59
  "default": "./dist/kernel/defaults.registry.js"
56
60
  },
61
+ "./kernel/routes/agent/*": {
62
+ "types": "./dist/kernel/routes/agent/*.d.ts",
63
+ "default": "./dist/kernel/routes/agent/*.js"
64
+ },
65
+ "./kernel/routes/layouts/*": {
66
+ "types": "./dist/kernel/routes/layouts/*.d.ts",
67
+ "default": "./dist/kernel/routes/layouts/*.js"
68
+ },
69
+ "./kernel/routes/metadata/*": {
70
+ "types": "./dist/kernel/routes/metadata/*.d.ts",
71
+ "default": "./dist/kernel/routes/metadata/*.js"
72
+ },
73
+ "./kernel/routes/pages/*": {
74
+ "types": "./dist/kernel/routes/pages/*.d.ts",
75
+ "default": "./dist/kernel/routes/pages/*.js"
76
+ },
77
+ "./kernel/routes/*": {
78
+ "types": "./dist/kernel/routes/*.d.ts",
79
+ "default": "./dist/kernel/routes/*.js"
80
+ },
57
81
  "./kernel/*": {
58
82
  "types": "./dist/kernel/*.d.ts",
59
83
  "default": "./dist/kernel/*.js"
@@ -99,4 +123,4 @@
99
123
  "registry": "https://registry.npmjs.org",
100
124
  "access": "public"
101
125
  }
102
- }
126
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "publish-os-nextjs-release-base",
3
+ "private": true,
4
+ "type": "module",
5
+ "engines": {
6
+ "node": ">=22.13"
7
+ },
8
+ "dependencies": {
9
+ "@base-ui/react": "1.5.0",
10
+ "@tailwindcss/postcss": "4.3.0",
11
+ "@types/node": "22.19.17",
12
+ "@types/react": "19.2.2",
13
+ "@types/react-dom": "19.2.2",
14
+ "class-variance-authority": "0.7.1",
15
+ "next": "16.2.6",
16
+ "next-themes": "0.4.6",
17
+ "pagefind": "1.5.2",
18
+ "react": "19.2.0",
19
+ "react-dom": "19.2.0",
20
+ "tailwindcss": "4.3.0",
21
+ "typescript": "5.9.2"
22
+ }
23
+ }