@leadertechie/personal-site-kit 0.1.0-alpha.14 → 0.1.0-alpha.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"website-api.d.ts","sourceRoot":"","sources":["../../src/api/website-api.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE3E,qBAAa,UAAU;IACrB,OAAO,CAAC,cAAc,CAAiC;IAEhD,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IAIzD,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,UAAU;IAqBL,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;CA+FlE"}
1
+ {"version":3,"file":"website-api.d.ts","sourceRoot":"","sources":["../../src/api/website-api.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE3E,qBAAa,UAAU;IACrB,OAAO,CAAC,cAAc,CAAiC;IAEhD,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IAIzD,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,mBAAmB;IAmB3B,OAAO,CAAC,UAAU;IAqBL,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;CAgGlE"}
package/dist/api.js CHANGED
@@ -1,5 +1,5 @@
1
- import { W as WebsiteAPI } from "./chunks/website-api-CE2q2nt7.js";
2
- import { A, B, M, R, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-CE2q2nt7.js";
1
+ import { W as WebsiteAPI } from "./chunks/website-api-C3lGjXdD.js";
2
+ import { A, B, M, R, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-C3lGjXdD.js";
3
3
  const defaultAPI = new WebsiteAPI();
4
4
  export {
5
5
  A as AUTH_KV,
@@ -798,16 +798,20 @@ class WebsiteAPI {
798
798
  this.customHandlers.set(route, handler);
799
799
  }
800
800
  addCORSHeaders(response) {
801
- response.headers.set("Access-Control-Allow-Origin", "*");
801
+ if (!response.headers.has("Access-Control-Allow-Origin")) {
802
+ response.headers.set("Access-Control-Allow-Origin", "*");
803
+ }
802
804
  response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
803
805
  response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Session-Token");
804
806
  return response;
805
807
  }
806
808
  addAdminCORSHeaders(response, origin) {
807
809
  const isLocal = origin && (origin.includes("localhost") || origin.includes("127.0.0.1"));
808
- if (isLocal) {
809
- response.headers.set("Access-Control-Allow-Origin", origin);
810
- response.headers.set("Access-Control-Allow-Credentials", "true");
810
+ if (!response.headers.has("Access-Control-Allow-Origin")) {
811
+ if (isLocal) {
812
+ response.headers.set("Access-Control-Allow-Origin", origin);
813
+ response.headers.set("Access-Control-Allow-Credentials", "true");
814
+ }
811
815
  }
812
816
  response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
813
817
  response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Session-Token");
@@ -871,7 +875,7 @@ class WebsiteAPI {
871
875
  return this.addAdminCORSHeaders(createErrorResponse("Unauthorized", 401), origin);
872
876
  }
873
877
  clearContentCache$1();
874
- return this.addAdminCORSHeaders(new Response(JSON.stringify({ success: true, message: "Cache cleared" }), { status: 200 }), origin);
878
+ return this.addAdminCORSHeaders(new Response(JSON.stringify({ success: true, message: "Cache cleared" }), { status: 200, headers: { "Content-Type": "application/json" } }), origin);
875
879
  case "aboutme":
876
880
  return this.addAdminCORSHeaders(await handleAboutMe(env), origin);
877
881
  case "logo":
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A, B, M, R, W, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-CE2q2nt7.js";
1
+ import { A, B, M, R, W, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-C3lGjXdD.js";
2
2
  import { WebsitePrerender } from "./prerender.js";
3
3
  import { A as A2, a as a2, b as b2, c as c2, d as d2, e as e2, f, g as g2, h as h2, i, B as B2, F, M as M2, j, S, k } from "./chunks/index-B2jGIzSi.js";
4
4
  import { S as S2, g as g3, i as i2, r as r2 } from "./chunks/site-store-CGV9c2DI.js";
@@ -5,6 +5,8 @@ export interface TemplateProps {
5
5
  content: string;
6
6
  hydrationData?: string;
7
7
  baseSiteUrl?: string;
8
+ jsAsset?: string;
9
+ cssAsset?: string;
8
10
  }
9
- export declare const createHtmlTemplate: ({ title, description, canonicalUrl, content, hydrationData, baseSiteUrl }: TemplateProps) => Promise<string>;
11
+ export declare const createHtmlTemplate: ({ title, description, canonicalUrl, content, hydrationData, baseSiteUrl, jsAsset, cssAsset }: TemplateProps) => Promise<string>;
10
12
  //# sourceMappingURL=template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/prerender/template.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyBD,eAAO,MAAM,kBAAkB,GAAU,2EAOtC,aAAa,KAAG,OAAO,CAAC,MAAM,CA0BhC,CAAC"}
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/prerender/template.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAsDD,eAAO,MAAM,kBAAkB,GAAU,8FAStC,aAAa,KAAG,OAAO,CAAC,MAAM,CAmChC,CAAC"}
@@ -18,7 +18,9 @@ export declare class WebsitePrerender {
18
18
  private copyright;
19
19
  private templateRenderer;
20
20
  private apiHandler?;
21
+ private cachedAssets;
21
22
  constructor(options?: PrerenderOptions);
23
+ private discoverAssets;
22
24
  private fetchStaticDetails;
23
25
  private fetchAboutMeData;
24
26
  fetch(request: Request, env: any, ctx: any): Promise<Response>;
@@ -1 +1 @@
1
- {"version":3,"file":"website-prerender.d.ts","sourceRoot":"","sources":["../../src/prerender/website-prerender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAuB,MAAM,gBAAgB,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,CAAC,EAAE,WAAW,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACtE,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAA;KAAE,CAAC;CAChG;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,kBAAkB,CAAgB;IAC1C,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAqD;IAC7E,OAAO,CAAC,UAAU,CAAC,CAAoF;gBAE3F,OAAO,GAAE,gBAAqB;YAmB5B,kBAAkB;YAiClB,gBAAgB;IAajB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;CA4F5E"}
1
+ {"version":3,"file":"website-prerender.d.ts","sourceRoot":"","sources":["../../src/prerender/website-prerender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAuB,MAAM,gBAAgB,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,CAAC,EAAE,WAAW,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACtE,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAA;KAAE,CAAC;CAChG;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,kBAAkB,CAAgB;IAC1C,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAqD;IAC7E,OAAO,CAAC,UAAU,CAAC,CAAoF;IACvG,OAAO,CAAC,YAAY,CAA4C;gBAEpD,OAAO,GAAE,gBAAqB;YAmB5B,cAAc;YAuCd,kBAAkB;YAgClB,gBAAgB;IAajB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;CAiI5E"}
package/dist/prerender.js CHANGED
@@ -1,24 +1,42 @@
1
1
  import { R2ContentLoader } from "@leadertechie/r2tohtml";
2
+ let cachedAssets = null;
3
+ let isDiscovering = false;
2
4
  async function getAssetPaths(baseSiteUrl) {
3
- const assetsUrl = `${baseSiteUrl}/cdn-assets.json`;
5
+ if (cachedAssets) return cachedAssets;
6
+ if (isDiscovering) {
7
+ return { js: "/assets/index.js", css: "/assets/index.css" };
8
+ }
9
+ isDiscovering = true;
4
10
  try {
11
+ const assetsUrl = `${baseSiteUrl}/cdn-assets.json`;
5
12
  const res = await fetch(assetsUrl);
6
13
  if (res.ok) {
7
14
  const data = await res.json();
8
- return { js: data.js, css: data.css };
15
+ cachedAssets = { js: data.js, css: data.css };
16
+ isDiscovering = false;
17
+ return cachedAssets;
9
18
  }
10
19
  } catch (e) {
11
20
  }
12
21
  try {
13
- const res = await fetch(`${baseSiteUrl}/?t=${Date.now()}`);
14
- const html = await res.text();
15
- const jsMatch = html.match(/src="(\/assets\/index-[^"]+\.js)"/);
16
- const cssMatch = html.match(/href="(\/assets\/index-[^"]+\.css)"/);
17
- return {
18
- js: jsMatch ? jsMatch[1] : "/assets/index.js",
19
- css: cssMatch ? cssMatch[1] : "/assets/index.css"
20
- };
22
+ const res = await fetch(`${baseSiteUrl}/index.html`);
23
+ if (res.ok) {
24
+ const html = await res.text();
25
+ const jsMatch = html.match(/src="([^"]*assets\/index-[^"]+\.js)"/);
26
+ const cssMatch = html.match(/href="([^"]*assets\/index-[^"]+\.css)"/);
27
+ if (jsMatch || cssMatch) {
28
+ cachedAssets = {
29
+ js: jsMatch ? jsMatch[1].startsWith("/") ? jsMatch[1] : "/" + jsMatch[1] : "/assets/index.js",
30
+ css: cssMatch ? cssMatch[1].startsWith("/") ? cssMatch[1] : "/" + cssMatch[1] : "/assets/index.css"
31
+ };
32
+ isDiscovering = false;
33
+ return cachedAssets;
34
+ }
35
+ }
21
36
  } catch (e) {
37
+ console.warn("Asset discovery failed:", e);
38
+ } finally {
39
+ isDiscovering = false;
22
40
  }
23
41
  return { js: "/assets/index.js", css: "/assets/index.css" };
24
42
  }
@@ -28,9 +46,18 @@ const createHtmlTemplate = async ({
28
46
  canonicalUrl,
29
47
  content,
30
48
  hydrationData = "",
31
- baseSiteUrl = ""
49
+ baseSiteUrl = "",
50
+ jsAsset,
51
+ cssAsset
32
52
  }) => {
33
- const { js: jsAsset, css: cssAsset } = await getAssetPaths(baseSiteUrl);
53
+ let js = jsAsset;
54
+ let css = cssAsset;
55
+ if (!js || !css) {
56
+ const effectiveBaseUrl = baseSiteUrl || new URL(canonicalUrl).origin;
57
+ const discovered = await getAssetPaths(effectiveBaseUrl);
58
+ js = js || discovered.js;
59
+ css = css || discovered.css;
60
+ }
34
61
  return `<!doctype html>
35
62
  <html lang="en" data-theme="light">
36
63
  <head>
@@ -44,8 +71,8 @@ const createHtmlTemplate = async ({
44
71
  <meta property="og:description" content="${description}" />
45
72
  <meta property="og:url" content="${canonicalUrl}" />
46
73
  <link rel="canonical" href="${canonicalUrl}" />
47
- <link rel="stylesheet" crossorigin href="${cssAsset}" />
48
- <script type="module" crossorigin src="${jsAsset}"><\/script>
74
+ <link rel="stylesheet" crossorigin href="${css}" />
75
+ <script type="module" crossorigin src="${js}"><\/script>
49
76
  </head>
50
77
  <body>
51
78
  ${hydrationData}
@@ -138,7 +165,7 @@ async function fetchLatestStorySummaries(env, count = 3) {
138
165
  }
139
166
  }
140
167
  const generatePageContent = async (pathname, routes, footerLinks, env) => {
141
- const apiUrl = env?.API_URL || env?.apiUrl;
168
+ const apiUrl = env?.API_URL || env?.apiUrl || "https://api.example.com";
142
169
  const baseUrl = env?.BASE_URL || env?.baseUrl || "https://www.example.com";
143
170
  let staticDetails = {
144
171
  siteTitle: "My Personal Website",
@@ -286,6 +313,7 @@ const generatePageContent = async (pathname, routes, footerLinks, env) => {
286
313
  };
287
314
  class WebsitePrerender {
288
315
  constructor(options = {}) {
316
+ this.cachedAssets = null;
289
317
  this.routes = options.routes || [
290
318
  { link: "/", text: "Home" },
291
319
  { link: "/blogs", text: "Blogs" },
@@ -303,11 +331,41 @@ class WebsitePrerender {
303
331
  this.templateRenderer = options.templateRenderer || createHtmlTemplate;
304
332
  this.apiHandler = options.apiHandler;
305
333
  }
334
+ async discoverAssets(env, baseSiteUrl) {
335
+ if (this.cachedAssets) return this.cachedAssets;
336
+ try {
337
+ let html = "";
338
+ if (env.ASSETS) {
339
+ const res = await env.ASSETS.fetch(new Request("http://localhost/index.html"));
340
+ if (res.ok) html = await res.text();
341
+ }
342
+ if (!html) {
343
+ const res = await fetch(`${baseSiteUrl}/index.html`, {
344
+ headers: { "X-Asset-Discovery": "true" }
345
+ });
346
+ if (res.ok) html = await res.text();
347
+ }
348
+ if (html) {
349
+ const jsMatch = html.match(/src="([^"]*assets\/index-[^"]+\.js)"/);
350
+ const cssMatch = html.match(/href="([^"]*assets\/index-[^"]+\.css)"/);
351
+ if (jsMatch || cssMatch) {
352
+ this.cachedAssets = {
353
+ js: jsMatch ? jsMatch[1].startsWith("/") ? jsMatch[1] : "/" + jsMatch[1] : "/assets/index.js",
354
+ css: cssMatch ? cssMatch[1].startsWith("/") ? cssMatch[1] : "/" + cssMatch[1] : "/assets/index.css"
355
+ };
356
+ return this.cachedAssets;
357
+ }
358
+ }
359
+ } catch (e) {
360
+ console.warn("Asset discovery failed:", e);
361
+ }
362
+ return { js: "/assets/index.js", css: "/assets/index.css" };
363
+ }
306
364
  async fetchStaticDetails(apiUrl, env) {
307
365
  try {
308
366
  let data;
309
367
  if (this.apiHandler) {
310
- const res = await this.apiHandler.fetch(new Request(`${apiUrl}/api/static`), env, {});
368
+ const res = await this.apiHandler.fetch(new Request("http://localhost/api/static"), env, {});
311
369
  if (res.ok) data = await res.json();
312
370
  } else {
313
371
  const res = await fetch(`${apiUrl}/api/static`);
@@ -334,7 +392,7 @@ class WebsitePrerender {
334
392
  async fetchAboutMeData(apiUrl, env) {
335
393
  try {
336
394
  if (this.apiHandler) {
337
- const res = await this.apiHandler.fetch(new Request(`${apiUrl}/api/aboutme`), env, {});
395
+ const res = await this.apiHandler.fetch(new Request("http://localhost/api/aboutme"), env, {});
338
396
  if (res.ok) return await res.json();
339
397
  } else {
340
398
  const res = await fetch(`${apiUrl}/api/aboutme`);
@@ -345,15 +403,39 @@ class WebsitePrerender {
345
403
  return null;
346
404
  }
347
405
  async fetch(request, env, ctx) {
348
- const apiUrl = env?.API_URL || "https://api.example.com";
349
- const baseSiteUrl = env?.BASE_SITE_URL || "https://site.example.com";
350
- await this.fetchStaticDetails(apiUrl, env);
351
406
  const url = new URL(request.url);
407
+ const apiUrl = env?.API_URL || `${url.origin}/api`;
408
+ const baseSiteUrl = env?.BASE_SITE_URL || url.origin;
409
+ if (url.pathname === "/admin" || url.pathname.startsWith("/admin/")) {
410
+ if (env.ASSETS) {
411
+ const assetRes = await env.ASSETS.fetch(new Request("http://localhost/index.html"));
412
+ if (assetRes.ok) return assetRes;
413
+ }
414
+ const templateResponse = await fetch(`${baseSiteUrl}/index.html`);
415
+ if (templateResponse.ok) {
416
+ return new Response(templateResponse.body, {
417
+ headers: { "content-type": "text/html" }
418
+ });
419
+ }
420
+ }
421
+ if (request.headers.get("X-Asset-Discovery") === "true") {
422
+ if (env.ASSETS) {
423
+ return env.ASSETS.fetch(new Request("http://localhost/index.html"));
424
+ }
425
+ }
426
+ await this.fetchStaticDetails(apiUrl, env);
352
427
  if (url.pathname.startsWith("/api/")) {
353
428
  if (this.apiHandler) {
354
429
  return this.apiHandler.fetch(request, env, ctx);
355
430
  }
356
- return fetch(`${apiUrl}${url.pathname}${url.search}`);
431
+ return fetch(`${apiUrl}${url.pathname.replace(/^\/api/, "")}${url.search}`);
432
+ }
433
+ if (env.ASSETS && (url.pathname.startsWith("/assets/") || url.pathname === "/favicon.ico" || url.pathname === "/logo.png")) {
434
+ try {
435
+ const assetRes = await env.ASSETS.fetch(request);
436
+ if (assetRes.ok) return assetRes;
437
+ } catch (e) {
438
+ }
357
439
  }
358
440
  if (url.pathname.startsWith("/images/")) {
359
441
  const imageKey = url.pathname.slice(1);
@@ -390,6 +472,9 @@ class WebsitePrerender {
390
472
  ico: "image/x-icon"
391
473
  };
392
474
  const contentType = contentTypes[ext || ""] || "application/octet-stream";
475
+ if (baseSiteUrl === url.origin && !env.ASSETS) {
476
+ return new Response("Asset not found", { status: 404 });
477
+ }
393
478
  const response = await fetch(`${baseSiteUrl}${path}`);
394
479
  if (response.ok) {
395
480
  return new Response(response.body, {
@@ -414,8 +499,15 @@ class WebsitePrerender {
414
499
  hydrationScript = `<script>window.__HYDRATION_DATA__ = ${JSON.stringify(aboutMeData)};<\/script>`;
415
500
  }
416
501
  }
502
+ const assets = await this.discoverAssets(env, baseSiteUrl);
417
503
  const pageContent = await generatePageContent(url.pathname, this.routes, this.footerLinks, { ...env, apiUrl, siteTitle: this.siteTitle, copyright: this.copyright });
418
- const html = await this.templateRenderer({ ...pageContent, hydrationData: hydrationScript });
504
+ const html = await this.templateRenderer({
505
+ ...pageContent,
506
+ hydrationData: hydrationScript,
507
+ baseSiteUrl,
508
+ jsAsset: assets.js,
509
+ cssAsset: assets.css
510
+ });
419
511
  return new Response(html, {
420
512
  headers: {
421
513
  "content-type": "text/html",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leadertechie/personal-site-kit",
3
- "version": "0.1.0-alpha.14",
3
+ "version": "0.1.0-alpha.16",
4
4
  "type": "module",
5
5
  "description": "A high-performance personal website engine for Cloudflare Workers and R2",
6
6
  "repository": {