diff --git a/scripts/build-dist.mjs b/scripts/build-dist.mjs
index c19d684d..1aa36a6f 100644
--- a/scripts/build-dist.mjs
+++ b/scripts/build-dist.mjs
@@ -2,6 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { execSync } from 'node:child_process';
import crypto from 'node:crypto';
+import { buildHashState } from './hash-dist.mjs';
const DIST = 'dist';
const FILES_TO_COPY = [
@@ -154,6 +155,38 @@ function rewriteEntryHtmlAssetPaths(manifest) {
}
}
+function injectVersionInfo() {
+ console.log('Injecting version hash and date...');
+ try {
+ const hashState = buildHashState(DIST);
+ const hash = hashState.combined;
+ const date = new Date().toISOString().split('T')[0];
+
+ const indexHtmlPath = path.join(DIST, 'index.html');
+ if (fs.existsSync(indexHtmlPath)) {
+ let content = fs.readFileSync(indexHtmlPath, 'utf8');
+
+ const versionHtml = `
+
+ v: ${hash.slice(0, 8)} • ${date}
+
`;
+
+ // Fallback search if whitespace differs
+ const taglineRegex = /(seed\. zap\. subscribe\.\s*<\/h2>)/;
+ if (taglineRegex.test(content)) {
+ content = content.replace(taglineRegex, '$1' + versionHtml);
+ fs.writeFileSync(indexHtmlPath, content);
+ console.log(`Injected version: ${hash.slice(0, 8)} • ${date}`);
+ } else {
+ console.warn('Could not find tagline to inject version info.');
+ }
+ }
+ } catch (error) {
+ console.error('Failed to inject version info:', error);
+ // Continue even if injection fails, as it's not critical for functionality
+ }
+}
+
function main() {
console.log('Validating service worker compatibility guard...');
try {
@@ -209,6 +242,8 @@ function main() {
console.log('Rewriting HTML entry points with hashed assets...');
rewriteEntryHtmlAssetPaths(manifest);
+ injectVersionInfo();
+
console.log('Build complete.');
}
diff --git a/scripts/hash-dist.mjs b/scripts/hash-dist.mjs
index 8637c776..dc41b53e 100644
--- a/scripts/hash-dist.mjs
+++ b/scripts/hash-dist.mjs
@@ -2,6 +2,7 @@
import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
+import { fileURLToPath } from 'node:url';
function parseArgs(argv) {
const args = {
@@ -72,7 +73,7 @@ function hashBuffer(buffer) {
return crypto.createHash('sha256').update(buffer).digest('hex');
}
-function buildHashState(distDir) {
+export function buildHashState(distDir) {
const resolvedDistDir = path.resolve(distDir);
if (!fs.existsSync(resolvedDistDir)) {
throw new Error(`Dist directory does not exist: ${resolvedDistDir}`);
@@ -112,4 +113,6 @@ function main() {
console.log(serialized);
}
-main();
+if (process.argv[1] === fileURLToPath(import.meta.url)) {
+ main();
+}
diff --git a/verification.png b/verification.png
new file mode 100644
index 00000000..fda37f88
Binary files /dev/null and b/verification.png differ
diff --git a/verify_version.py b/verify_version.py
new file mode 100644
index 00000000..0130aaff
--- /dev/null
+++ b/verify_version.py
@@ -0,0 +1,29 @@
+from playwright.sync_api import sync_playwright
+
+def run():
+ with sync_playwright() as p:
+ browser = p.chromium.launch()
+ page = browser.new_page()
+ page.goto("http://localhost:3000")
+
+ # Locate the tagline
+ tagline = page.get_by_text("seed. zap. subscribe.")
+
+ # Locate the version info which should be nearby
+ # The tagline is an h2 inside a div.
+ container = tagline.locator("..")
+
+ # Wait for fade-in to settle or just force visibility?
+ # The container has "fade-in" class. It might take time.
+ # I'll wait for the version text to be visible.
+ version_locator = container.locator("div.text-xs")
+ version_locator.wait_for()
+
+ print("Version text found:", version_locator.inner_text())
+
+ # Screenshot the container
+ container.screenshot(path="verification.png")
+ browser.close()
+
+if __name__ == "__main__":
+ run()