commit 5bc6a32f6b720d811de85b189233f1b72a1e99a1
parent 9bc1d42e8f9efac3afe4f95beb21832facce7cc3
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sun, 27 Sep 2026 01:02:11 -0400
homepage: HOMEPAGE_SUMMARY_FILE is ignored by a production build
Review fix. The e2e's override of the summary file was honoured by `next
build` too, so a variable left in a build shell could ship the fixture as the
homepage's numbers. summaryFile(env, publicFile) now reads it only when
NODE_ENV is not "production"; Playwright's `next dev` is development and keeps
it. summary.test.ts covers both, run by the homepage's new `test` script
(`tsx --test "app/**/*.test.ts"`, as the editor's unit tests).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
3 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/homepage/app/lib/summary.test.ts b/homepage/app/lib/summary.test.ts
@@ -0,0 +1,24 @@
+import { test } from "node:test";
+import assert from "node:assert/strict";
+import { summaryFile } from "./summary";
+
+// Run with:
+// pnpm --filter homepage test
+
+const PUBLIC = "/repo/homepage/public/homepage-summary.json";
+
+test("a production build never reads HOMEPAGE_SUMMARY_FILE", () => {
+ assert.equal(
+ summaryFile({ NODE_ENV: "production", HOMEPAGE_SUMMARY_FILE: "/tmp/fixture.json" }, PUBLIC),
+ PUBLIC,
+ );
+});
+
+test("outside production (the e2e's next dev) it names the file to read", () => {
+ assert.equal(
+ summaryFile({ NODE_ENV: "development", HOMEPAGE_SUMMARY_FILE: "/x/.e2e-summary.json" }, PUBLIC),
+ "/x/.e2e-summary.json",
+ );
+ assert.equal(summaryFile({ NODE_ENV: "development" }, PUBLIC), PUBLIC);
+ assert.equal(summaryFile({ NODE_ENV: "development", HOMEPAGE_SUMMARY_FILE: "" }, PUBLIC), PUBLIC);
+});
diff --git a/homepage/app/lib/summary.ts b/homepage/app/lib/summary.ts
@@ -16,14 +16,12 @@ import type { HomepageSummary } from "yt-dlp-transcript-common/lib/homepageSumma
// Read with `readFileSync` at module scope of a server component, mirroring
// export/app/changelog/page.tsx. `output: "export"` means this runs at build,
// never at request time.
-//
-// HOMEPAGE_SUMMARY_FILE names another file to read instead. Only the e2e sets
-// it, to a copy of this one with fixture accents (playwright.config.ts).
export function loadSummary(): HomepageSummary | null {
try {
- const file =
- process.env.HOMEPAGE_SUMMARY_FILE ||
- path.join(process.cwd(), "public", "homepage-summary.json");
+ const file = summaryFile(
+ process.env,
+ path.join(process.cwd(), "public", "homepage-summary.json"),
+ );
const parsed = JSON.parse(
fs.readFileSync(file, "utf8"),
) as HomepageSummary;
@@ -35,3 +33,16 @@ export function loadSummary(): HomepageSummary | null {
return null;
}
}
+
+// The file loadSummary reads: `public/homepage-summary.json`, or the file
+// HOMEPAGE_SUMMARY_FILE names — but ONLY outside a production build. The e2e's
+// `next dev` points it at a copy with fixture accents (playwright.config.ts);
+// `next build` runs with NODE_ENV=production and ignores it, so a variable left
+// in a build shell can never ship a fixture as the homepage's numbers.
+export function summaryFile(
+ env: Readonly<Record<string, string | undefined>>,
+ publicFile: string,
+): string {
+ const override = env.NODE_ENV !== "production" ? env.HOMEPAGE_SUMMARY_FILE : undefined;
+ return override || publicFile;
+}
diff --git a/homepage/package.json b/homepage/package.json
@@ -13,6 +13,7 @@
"build:nodata": "next build",
"start": "serve out -l ${HOMEPAGE_PORT:-3031}",
"lint": "eslint",
+ "test": "tsx --test \"app/**/*.test.ts\"",
"e2e": "node ../scripts/queue-lock.mjs --ports HOMEPAGE_E2E_PORT:3040 -- playwright test",
"e2e:ui": "playwright test --ui",
"deploy": "tsx ../common/bin/archilyzer.ts deploy homepage"