3ce9ab7bf1
Build and push image / build (push) Successful in 3m13s
Localized home pages (/es, /fr, /de, /it, /pt) with server-rendered intro, how-to-play and FAQ plus FAQPage/WebApplication JSON-LD and hreflang. Puzzle archive at /archive with answer pages (/puzzle/N) for past days only and replays (/play/N) that never touch stats or the daily streak. Challenge loop: shared results link back as /?challenge=<code> and the result screen shows a head-to-head verdict. Also adds robots.txt, sitemap.xml, the PWA manifest and icons, a compact share text with WhatsApp/X/copy channels, a next-puzzle countdown, the social-proof play counter and a spoiler-free /api/teaser for daily posting. Refs #1 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QvQ1ErZNRUcWgCEkJ9uyrn
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
// Client helpers for the social-proof play counter (see app/api/plays/route.ts).
|
|
|
|
function countedKey(dateKey: string): string {
|
|
return `hidden11-plays-counted-${dateKey}`;
|
|
}
|
|
|
|
export async function fetchPlaysCount(dateKey: string): Promise<number | null> {
|
|
try {
|
|
const response = await fetch(`/api/plays?date=${encodeURIComponent(dateKey)}`, { cache: "no-store" });
|
|
if (!response.ok) return null;
|
|
const data = (await response.json()) as { count?: number | null };
|
|
return typeof data.count === "number" ? data.count : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Increments at most once per browser per day.
|
|
export async function registerPlay(dateKey: string): Promise<void> {
|
|
if (typeof window === "undefined") return;
|
|
if (window.localStorage.getItem(countedKey(dateKey)) === "true") return;
|
|
window.localStorage.setItem(countedKey(dateKey), "true");
|
|
|
|
try {
|
|
await fetch("/api/plays", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ date: dateKey }),
|
|
keepalive: true,
|
|
});
|
|
} catch {
|
|
// best-effort; the flag is already set so we don't double-count on retry
|
|
}
|
|
}
|