From 50f50b2672cd1cbbf5a1ac41f8d4a768058632bc Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Tue, 28 Jul 2026 08:56:43 +0200 Subject: [PATCH] fix(server): use public URL for homepage metadata --- apps/server/src/static/web.test.ts | 14 ++++++++++---- apps/server/src/static/web.ts | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/server/src/static/web.test.ts b/apps/server/src/static/web.test.ts index 334854047..1a8d14fe5 100644 --- a/apps/server/src/static/web.test.ts +++ b/apps/server/src/static/web.test.ts @@ -2,6 +2,7 @@ import fs from "node:fs/promises"; import { beforeEach, describe, expect, it, vi } from "vitest"; const mocks = vi.hoisted(() => ({ + env: { APP_URL: "https://rxresu.me" }, serveStatic: vi.fn((_options?: unknown) => vi.fn()), })); @@ -19,6 +20,10 @@ vi.mock("@hono/node-server/serve-static", () => ({ serveStatic: mocks.serveStatic, })); +vi.mock("@reactive-resume/env/server", () => ({ + env: mocks.env, +})); + type StaticOptions = { onFound?: ( path: string, @@ -62,15 +67,16 @@ describe("web app fallback classification", () => { `); - const response = await handleWebApp(new Request("https://example.com/?utm_source=search")); + const response = await handleWebApp(new Request("http://server.internal/?utm_source=search")); const html = await response.text(); - expect(html).toContain(''); + expect(html).toContain(''); expect(html).toContain(''); - expect(html).toContain(''); - expect(html).toContain(''); + expect(html).toContain(''); + expect(html).toContain(''); expect(html).toContain('id="reactive-resume-structured-data"'); expect(html).toContain('"@type":["SoftwareApplication","WebApplication"]'); + expect(html).toContain('"url":"https://rxresu.me/"'); expect(html).not.toContain("utm_source"); const dashboardResponse = await handleWebApp(new Request("https://example.com/dashboard")); diff --git a/apps/server/src/static/web.ts b/apps/server/src/static/web.ts index 9f4e0d68e..9833ed7d5 100644 --- a/apps/server/src/static/web.ts +++ b/apps/server/src/static/web.ts @@ -2,6 +2,7 @@ import { existsSync } from "node:fs"; import fs from "node:fs/promises"; import { fileURLToPath } from "node:url"; import { serveStatic } from "@hono/node-server/serve-static"; +import { env } from "@reactive-resume/env/server"; function resolveWebDistPath() { const candidates = [ @@ -193,8 +194,7 @@ function notFoundResponse(options: { head?: boolean; noindex?: boolean } = {}) { // ponytail: GET and HEAD share the same routing logic; method determines body presence export async function handleWebApp(request: Request) { const isHead = request.method === "HEAD"; - const requestUrl = new URL(request.url); - const pathname = requestUrl.pathname; + const pathname = new URL(request.url).pathname; if (!isNoindexShellPath(pathname) && isAssetPath(pathname)) { return new Response(isHead ? null : "Not Found", { status: 404 }); @@ -206,7 +206,7 @@ export async function handleWebApp(request: Request) { if (isHead) return new Response(null, { status: 200, headers }); const html = await fs.readFile(indexHtmlPath, "utf-8"); - const canonicalUrl = new URL("/", requestUrl.origin).toString(); + const canonicalUrl = new URL("/", env.APP_URL).toString(); const responseHtml = pathname === "/" ? html.replace("", `${createRootSeoMarkup(canonicalUrl)}`) : html; return new Response(responseHtml, { headers });