Files
hidden11/lib/types.ts
T
claude-code 0de85cbc51
Build and push image / build (push) Failing after 15m20s
Localize the archive, add reminders, named challenges and a funnel
Archive and answer pages now exist in all six languages and are prerendered
instead of rendered per request, and each answer page carries a sentence of
real context per player (club, league, nationality, former clubs, honours)
plus Article and BreadcrumbList JSON-LD. The sitemap grows from 121 to 691
URLs, every one with hreflang alternates.

Adds an optional display name to shared results, so a challenge link reads
"<name> challenges you" in the page, the OG image and the head-to-head
verdict; the name is sanitised both when written and when parsed back.

Adds an opt-in daily reminder (Web Push without payload, so no content
encryption) and a PWA install prompt shown once the day is finished, plus
first-party event ingestion at /api/events that mirrors GA4 so the funnel
survives ad blockers.

Wires the missing N8N_PLAYS_WEBHOOK_URL into the deployment along with the
new events, push and search-verification secrets, and ships the n8n
workflows, the Postgres schema with funnel/retention views, and an IndexNow
submitter.

Refs #2 #3 #5 #6 #7 #8 #9 #10

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QvQ1ErZNRUcWgCEkJ9uyrn
2026-08-26 12:41:28 +00:00

64 lines
1.3 KiB
TypeScript

export type Position = "GK" | "DEF" | "MID" | "WING" | "ST";
export type Difficulty = "easy" | "medium" | "hard";
export type Feedback = "correct" | "partial" | "wrong" | "empty";
export type Player = {
id: string;
name: string;
position: Position;
nationality: string;
club: string;
league: string;
formerClubs?: string[];
championsLeagueTitles?: number;
leagueTitles?: number;
leagueTitleCountries?: string[];
ballonDOr?: number;
goldenBoot?: number;
worldCupWinner?: boolean;
copaAmericaWinner?: boolean;
eurocupWinner?: boolean;
};
export type Puzzle = {
id: string;
date: string;
difficulty: Difficulty;
solution: Record<Position, string>;
fixedPosition: Position;
clues: string[];
};
export type SlotGuess = {
position: Position;
playerId: string | null;
feedback: Feedback;
};
export type Guess = {
slots: SlotGuess[];
};
export type PuzzleProgress = {
attempts: Guess[];
elapsedSeconds: number;
solved: boolean;
locked: boolean;
};
export type DailyProgress = Record<Difficulty, PuzzleProgress>;
export type GlobalStats = {
averageSeconds: number;
bestSeconds: number | null;
currentStreak: number;
gamesPlayed: number;
lastCompletedDate: string | null;
maxStreak: number;
perfectDays: number;
totalSeconds: number;
winDistribution: Record<number, number>;
};