Rename project: youtube-summarizer → recap
The product was always more than YouTube — it handles podcast feeds
too, and the upcoming multi-provider work makes it less Gemini-
specific. New name: Recap.
This is a coordinated identity change across:
• StartOS package id: youtube-summarizer → recap
(manifest.id; the .s9pk filename, Docker image namespace, and
install path under StartOS all derive from this automatically)
• Display name: "YouTube Summarizer" → "Recap"
(manifest title, activation screen heading, page <title>, console
log on boot, i18n strings, ABOUT.md, Dockerfile header,
docker_entrypoint banner)
• Keysat product slug: youtube-summarizer → recap
(server/license.js PRODUCT_SLUG; frontend fallback strings)
• Daemon subscription id: youtube-summarizer-sub → recap-sub
• Env var prefix: YT_SUMMARIZER_* → RECAP_*
(LICENSE_KEY, LICENSE_KEY_PATH, MAX_OFFLINE_DAYS,
VALIDATE_INTERVAL_MS)
• localStorage keys: yt-summarizer-* → recap-*
(gemini-key, activation-skipped, clips)
• Library export filename: youtube-summarizer-library.json →
recap-library.json
• npm package names: youtube-summarizer-{startos,server} → recap-*
• Deploy paths: youtube-summarizer_x86_64.s9pk → recap_x86_64.s9pk
(default values in bin/deploy.sh; .deploy.env on dev machine
needs the same update before next push)
• Self-hosted registry directory: startos-registry/packages/
youtube-summarizer → .../recap (with package.json + INSTRUCTIONS
rewritten)
What does NOT change:
• Filesystem repo path (still /Users/.../youtube-summarizer/)
• Git history / commit messages
• Existing version files in startos/versions/ (kept as-is — the
version chain belongs to the package's own history regardless of
its display name)
User-side follow-ups required:
1. Create "recap" product in Keysat admin, set up Core/Pro tier
policies (same entitlements as before), mint a fresh test
license. Old "youtube-summarizer" licenses won't activate
against the new slug.
2. Update .deploy.env (gitignored) so FILEBROWSER_PATH and
REGISTRY_PUBLIC_URL point at recap_x86_64.s9pk.
StartOS will treat this as a brand-new app on install — existing
youtube-summarizer installs will not auto-migrate (acknowledged
intentional given no real users yet).
This commit is contained in:
+15
-15
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>YouTube Transcript Summarizer</title>
|
||||
<title>Recap</title>
|
||||
<link rel="icon" type="image/png" href="/assets/icon.png">
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
@@ -1211,7 +1211,7 @@
|
||||
// ── State ────────────────────────────────────────────────────────────────
|
||||
const state = {
|
||||
url: "",
|
||||
apiKey: localStorage.getItem("yt-summarizer-gemini-key") || "",
|
||||
apiKey: localStorage.getItem("recap-gemini-key") || "",
|
||||
hasServerKey: false, // will be set by health check
|
||||
lanMode: null, // null = unknown, true = home, false = traveling
|
||||
serverStatus: "connecting", // "connected" | "sleeping" | "disconnected" | "connecting"
|
||||
@@ -1275,7 +1275,7 @@
|
||||
entitlements: [],
|
||||
expiresAt: null,
|
||||
isTrial: false,
|
||||
productSlug: "youtube-summarizer",
|
||||
productSlug: "recap",
|
||||
keysatBaseUrl: "",
|
||||
},
|
||||
licenseActivating: false,
|
||||
@@ -1284,7 +1284,7 @@
|
||||
// Free tier: once dismissed, the activation screen no longer
|
||||
// hard-gates the UI. Persisted so returning unlicensed users land
|
||||
// straight in the app.
|
||||
activationSkipped: localStorage.getItem("yt-summarizer-activation-skipped") === "1",
|
||||
activationSkipped: localStorage.getItem("recap-activation-skipped") === "1",
|
||||
};
|
||||
|
||||
const MODELS = ["gemini-3.1-pro-preview", "gemini-3-pro-preview", "gemini-3-flash-preview"];
|
||||
@@ -1624,7 +1624,7 @@
|
||||
return `
|
||||
<div class="activation-screen">
|
||||
<div class="activation-card">
|
||||
<h1>YouTube Summarizer</h1>
|
||||
<h1>Recap</h1>
|
||||
<p class="activation-sub">
|
||||
${loading
|
||||
? "Checking license…"
|
||||
@@ -1651,7 +1651,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="activation-meta">
|
||||
Product: <strong>${escHtml(lic.productSlug || "youtube-summarizer")}</strong>
|
||||
Product: <strong>${escHtml(lic.productSlug || "recap")}</strong>
|
||||
${lic.keysatBaseUrl ? ` · Issuer: <strong>${escHtml(lic.keysatBaseUrl.replace(/^https?:\/\//, ""))}</strong>` : ""}
|
||||
</div>
|
||||
`}
|
||||
@@ -1662,7 +1662,7 @@
|
||||
|
||||
function dismissActivation() {
|
||||
state.activationSkipped = true;
|
||||
try { localStorage.setItem("yt-summarizer-activation-skipped", "1"); } catch {}
|
||||
try { localStorage.setItem("recap-activation-skipped", "1"); } catch {}
|
||||
render();
|
||||
}
|
||||
|
||||
@@ -1730,7 +1730,7 @@
|
||||
function showActivationScreen() {
|
||||
// Take user back to the activation modal (e.g. from an upgrade banner).
|
||||
state.activationSkipped = false;
|
||||
try { localStorage.removeItem("yt-summarizer-activation-skipped"); } catch {}
|
||||
try { localStorage.removeItem("recap-activation-skipped"); } catch {}
|
||||
render();
|
||||
}
|
||||
|
||||
@@ -2057,7 +2057,7 @@
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "youtube-summarizer-library.json";
|
||||
a.download = "recap-library.json";
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
showToast("Library exported!", "✓");
|
||||
@@ -3492,7 +3492,7 @@
|
||||
function toggleShowKey() { state.showKey = !state.showKey; render(); }
|
||||
function setApiKey(v) {
|
||||
state.apiKey = v;
|
||||
localStorage.setItem("yt-summarizer-gemini-key", v);
|
||||
localStorage.setItem("recap-gemini-key", v);
|
||||
}
|
||||
function setModel(m) { state.model = m; render(); }
|
||||
function toggleExpandAll() {
|
||||
@@ -3921,12 +3921,12 @@
|
||||
}
|
||||
|
||||
function saveClipCollection() {
|
||||
localStorage.setItem("yt-summarizer-clips", JSON.stringify(state.clipCollection));
|
||||
localStorage.setItem("recap-clips", JSON.stringify(state.clipCollection));
|
||||
}
|
||||
|
||||
function loadClipCollection() {
|
||||
try {
|
||||
const saved = localStorage.getItem("yt-summarizer-clips");
|
||||
const saved = localStorage.getItem("recap-clips");
|
||||
if (saved) state.clipCollection = JSON.parse(saved);
|
||||
} catch {}
|
||||
}
|
||||
@@ -4112,7 +4112,7 @@
|
||||
entitlements: data.entitlements || [],
|
||||
expiresAt: data.expiresAt || null,
|
||||
isTrial: !!data.isTrial,
|
||||
productSlug: data.productSlug || "youtube-summarizer",
|
||||
productSlug: data.productSlug || "recap",
|
||||
keysatBaseUrl: data.keysatBaseUrl || "",
|
||||
};
|
||||
} catch {
|
||||
@@ -4150,7 +4150,7 @@
|
||||
entitlements: data.entitlements || [],
|
||||
expiresAt: data.expiresAt,
|
||||
isTrial: !!data.isTrial,
|
||||
productSlug: data.productSlug || "youtube-summarizer",
|
||||
productSlug: data.productSlug || "recap",
|
||||
keysatBaseUrl: data.keysatBaseUrl || "",
|
||||
};
|
||||
state.licenseActivationKey = "";
|
||||
@@ -4193,7 +4193,7 @@
|
||||
}
|
||||
function upgradeToProUrl() {
|
||||
const base = state.license.keysatBaseUrl || "https://licensing.keysat.xyz";
|
||||
return `${base.replace(/\/$/, "")}/buy/${state.license.productSlug || "youtube-summarizer"}`;
|
||||
return `${base.replace(/\/$/, "")}/buy/${state.license.productSlug || "recap"}`;
|
||||
}
|
||||
|
||||
function showToast(message, icon = "✓", duration = 4000) {
|
||||
|
||||
Reference in New Issue
Block a user