- Production now runs from ~/freezmo-prod/current (release symlink) as a standalone server on :3207; releases are exported by scripts/deploy.sh, built and e2e-verified on a temp port, switched atomically, health- checked via the new /api/healthz (commit + build time) and rolled back automatically on failure. Last 5 releases kept; scripts/rollback.sh for manual rollback. Shared env + data live in ~/freezmo-prod/shared/ and are symlinked into every release (existing sync/push data migrated and verified identical). - Dev runs from ~/freezmo via freezmo-dev.service: next dev on :3217 (LAN only), its own build folder (.next-dev via NEXT_DIST_DIR), its own data (~/freezmo/.freezmo-dev), DEV badge, dev favicon/theme colour, "Freezmo Dev" PWA identity and never the production service worker. - /api/healthz + the Settings Details version row (short commit + build time). output: standalone in next.config (next start still works). - AGENTS.md documents the workflow rules: only dev updates during a task, temporary dirs/ports for test builds, and deploy-at-the-end as the only production path. README gains an Environments and deploy section. - Fix found by the rehearsal: lib/dev-mode.ts must not be a client module (a server component importing a constant from a "use client" module gets a truthy proxy, which baked dev metadata into production builds). - SW -> freezmo-v34.
35 lines
880 B
TypeScript
35 lines
880 B
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
export type RunningVersion = {
|
|
commit: string;
|
|
short: string;
|
|
builtAt: string | null;
|
|
release: string | null;
|
|
dev: boolean;
|
|
};
|
|
|
|
/** Which release is running (from /api/healthz), for the Settings details. */
|
|
export function useVersion(): RunningVersion | null {
|
|
const [version, setVersion] = useState<RunningVersion | null>(null);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
void (async () => {
|
|
try {
|
|
const response = await fetch("/api/healthz", { cache: "no-store" });
|
|
if (!response.ok) return;
|
|
const body = (await response.json()) as RunningVersion;
|
|
if (!cancelled) setVersion(body);
|
|
} catch {
|
|
/* offline or old server — the row stays hidden */
|
|
}
|
|
})();
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, []);
|
|
|
|
return version;
|
|
}
|