diff --git a/README.md b/README.md index 1056543..424c031 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,15 @@ Optional feedback env vars: - `N8N_FEEDBACK_WEBHOOK_URL`: n8n webhook URL used to receive feedback submissions +Optional sponsor env vars: + +- `NEXT_PUBLIC_SPONSOR_ENABLED`: set to `false` to hide the sponsor slot +- `NEXT_PUBLIC_SPONSOR_NAME`: sponsor name shown in the slot +- `NEXT_PUBLIC_SPONSOR_TAGLINE`: short sponsor copy +- `NEXT_PUBLIC_SPONSOR_CTA`: sponsor button text +- `NEXT_PUBLIC_SPONSOR_URL`: outbound sponsor URL +- `NEXT_PUBLIC_SPONSOR_LABEL`: small label above the sponsor name + ## Production build ```bash @@ -73,6 +82,15 @@ To enable feedback submission, create a secret named `hidden11-feedback` in the - `N8N_FEEDBACK_WEBHOOK_URL` +To configure the sponsor slot in Kubernetes, create a secret named `hidden11-sponsor` in the `hidden11` namespace with any of: + +- `NEXT_PUBLIC_SPONSOR_ENABLED` +- `NEXT_PUBLIC_SPONSOR_NAME` +- `NEXT_PUBLIC_SPONSOR_TAGLINE` +- `NEXT_PUBLIC_SPONSOR_CTA` +- `NEXT_PUBLIC_SPONSOR_URL` +- `NEXT_PUBLIC_SPONSOR_LABEL` + ## ArgoCD ```bash diff --git a/app/page.tsx b/app/page.tsx index 185c624..23ad03a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,7 +1,8 @@ import HomeClient from "@/components/HomeClient"; +import { getSponsorConfig } from "@/lib/sponsor"; export const dynamic = "force-dynamic"; export default function Page() { - return ; + return ; } diff --git a/app/sponsor/page.tsx b/app/sponsor/page.tsx new file mode 100644 index 0000000..9c23875 --- /dev/null +++ b/app/sponsor/page.tsx @@ -0,0 +1,90 @@ +import type { Metadata } from "next"; +import Link from "next/link"; + +export const metadata: Metadata = { + title: "Sponsor hidden11", + description: "Sponsor the daily football puzzle played by sharp football fans.", + alternates: { + canonical: "https://hidden11.app/sponsor", + }, + openGraph: { + title: "Sponsor hidden11", + description: "Reach football fans inside a daily football puzzle with shareable results.", + url: "https://hidden11.app/sponsor", + siteName: "hidden11", + type: "website", + }, + twitter: { + card: "summary_large_image", + title: "Sponsor hidden11", + description: "Reach football fans inside a daily football puzzle with shareable results.", + }, +}; + +const sponsorEmail = "sponsors@hidden11.app"; + +export default function SponsorPage() { + const subject = encodeURIComponent("Sponsor hidden11"); + const body = encodeURIComponent( + "Hi hidden11,\n\nI am interested in sponsoring hidden11.\n\nBrand:\nWebsite:\nCampaign dates:\nGoal:\n", + ); + + return ( +
+
+
+ + hidden11 + + + Email us + +
+ +
+

Sponsorship

+

+ Reach football fans in a daily game they come back to. +

+

+ hidden11 is a daily football lineup puzzle with shareable results, streaks and football-history clues. + Sponsorship appears directly in the playing flow and result moment. +

+ +
+ + + +
+ +
+ + Sponsor hidden11 + + + View game + +
+
+
+
+ ); +} + +function Metric({ label, value }: { label: string; value: string }) { + return ( +
+

{label}

+

{value}

+
+ ); +} diff --git a/components/HomeClient.tsx b/components/HomeClient.tsx index 437e598..1524c04 100644 --- a/components/HomeClient.tsx +++ b/components/HomeClient.tsx @@ -8,9 +8,11 @@ import Pitch from "@/components/Pitch"; import PlayerSearch from "@/components/PlayerSearch"; import FeedbackModal from "@/components/FeedbackModal"; import ShareResult from "@/components/ShareResult"; +import SponsorSlot from "@/components/SponsorSlot"; import StatsPanel from "@/components/StatsPanel"; import { trackEvent } from "@/lib/analytics-events"; import { buildGlobalStatsShareText } from "@/lib/share"; +import type { SponsorConfig } from "@/lib/sponsor"; import { DIFFICULTIES, MAX_ATTEMPTS, @@ -37,7 +39,11 @@ import { } from "@/lib/storage"; import type { DailyProgress, Difficulty, GlobalStats, Position } from "@/lib/types"; -export default function Home() { +type HomeProps = { + sponsor: SponsorConfig; +}; + +export default function Home({ sponsor }: HomeProps) { const dateKey = useMemo(() => getTodayKey(), []); const dailyPuzzles = useMemo(() => getDailyPuzzles(dateKey), [dateKey]); const [locale, setLocale] = useState("en"); @@ -316,6 +322,10 @@ export default function Home() {

+
+ +
+
setStatsOpen(true)} + sponsor={sponsor} /> ) : null} diff --git a/components/ShareResult.tsx b/components/ShareResult.tsx index 995b970..238b074 100644 --- a/components/ShareResult.tsx +++ b/components/ShareResult.tsx @@ -4,8 +4,10 @@ import type { Dictionary } from "@/lib/i18n"; import type { Locale } from "@/lib/i18n"; import { DIFFICULTIES, MAX_ATTEMPTS, getPuzzleNumber } from "@/lib/game-engine"; import { buildChallengeShareText, buildShareText, buildShareUrl } from "@/lib/share"; +import type { SponsorConfig } from "@/lib/sponsor"; import { formatElapsed } from "@/lib/time"; import type { DailyProgress, GlobalStats } from "@/lib/types"; +import SponsorSlot from "./SponsorSlot"; import StatsPanel from "./StatsPanel"; type ShareResultProps = { @@ -15,11 +17,12 @@ type ShareResultProps = { locale: Locale; onOpenStats: () => void; quote: { author: string; text: Record }; + sponsor: SponsorConfig; stats: GlobalStats; t: Dictionary; }; -export default function ShareResult({ dateKey, locale, onClose, onOpenStats, progress, quote, stats, t }: ShareResultProps) { +export default function ShareResult({ dateKey, locale, onClose, onOpenStats, progress, quote, sponsor, stats, t }: ShareResultProps) { const [shared, setShared] = useState(false); const [origin, setOrigin] = useState("https://hidden11.app"); const shareUrl = useMemo(() => buildShareUrl(dateKey, progress, origin), [dateKey, origin, progress]); @@ -143,6 +146,9 @@ export default function ShareResult({ dateKey, locale, onClose, onOpenStats, pro
+
+ +

“{quote.text[locale]}” diff --git a/components/SponsorSlot.tsx b/components/SponsorSlot.tsx new file mode 100644 index 0000000..fecc8fe --- /dev/null +++ b/components/SponsorSlot.tsx @@ -0,0 +1,44 @@ +"use client"; + +import { trackEvent } from "@/lib/analytics-events"; +import type { SponsorConfig } from "@/lib/sponsor"; + +type SponsorSlotProps = { + placement: "home" | "result"; + sponsor: SponsorConfig; +}; + +export default function SponsorSlot({ placement, sponsor }: SponsorSlotProps) { + if (!sponsor.enabled) { + return null; + } + + function trackClick() { + trackEvent("sponsor_click", { + placement, + sponsor_name: sponsor.name, + sponsor_url: sponsor.url, + }); + } + + return ( +

+ ); +} diff --git a/deploy/k8s/deployment.yaml b/deploy/k8s/deployment.yaml index e6d05b5..53b7939 100644 --- a/deploy/k8s/deployment.yaml +++ b/deploy/k8s/deployment.yaml @@ -40,6 +40,42 @@ spec: name: hidden11-feedback key: N8N_FEEDBACK_WEBHOOK_URL optional: true + - name: NEXT_PUBLIC_SPONSOR_ENABLED + valueFrom: + secretKeyRef: + name: hidden11-sponsor + key: NEXT_PUBLIC_SPONSOR_ENABLED + optional: true + - name: NEXT_PUBLIC_SPONSOR_NAME + valueFrom: + secretKeyRef: + name: hidden11-sponsor + key: NEXT_PUBLIC_SPONSOR_NAME + optional: true + - name: NEXT_PUBLIC_SPONSOR_TAGLINE + valueFrom: + secretKeyRef: + name: hidden11-sponsor + key: NEXT_PUBLIC_SPONSOR_TAGLINE + optional: true + - name: NEXT_PUBLIC_SPONSOR_CTA + valueFrom: + secretKeyRef: + name: hidden11-sponsor + key: NEXT_PUBLIC_SPONSOR_CTA + optional: true + - name: NEXT_PUBLIC_SPONSOR_URL + valueFrom: + secretKeyRef: + name: hidden11-sponsor + key: NEXT_PUBLIC_SPONSOR_URL + optional: true + - name: NEXT_PUBLIC_SPONSOR_LABEL + valueFrom: + secretKeyRef: + name: hidden11-sponsor + key: NEXT_PUBLIC_SPONSOR_LABEL + optional: true ports: - name: http containerPort: 3000 diff --git a/lib/i18n.ts b/lib/i18n.ts index 7886efc..03d9db0 100644 --- a/lib/i18n.ts +++ b/lib/i18n.ts @@ -636,9 +636,324 @@ export function getDictionary(locale: Locale): Dictionary { return { ...fallback, ...dictionary, - clue: { + clue: createClueDictionary(locale, { ...fallback.clue, ...dictionary.clue, - }, + }), }; } + +function createClueDictionary(locale: Locale, overrides: Record): Record { + return new Proxy(overrides, { + get(target, property) { + if (typeof property !== "string") { + return undefined; + } + + return target[property] ?? translateGeneratedClue(property, locale); + }, + }); +} + +function translateGeneratedClue(clue: string, locale: Locale): string { + if (locale === "en") { + return clue; + } + + const sharedClub = clue.match(/^(\d+|Two) players share the same club\.$/); + if (sharedClub) { + const count = sharedClub[1] === "Two" ? 2 : Number(sharedClub[1]); + return tSharedClub(locale, count); + } + + const leagueCount = clue.match(/^(\d+) players? play in (.+)\.$/); + if (leagueCount) { + return tLeagueCount(locale, Number(leagueCount[1]), leagueCount[2]); + } + + const differentClubs = clue.match(/^All five players come from different clubs\.$/); + if (differentClubs) { + return tAllDifferentClubs(locale); + } + + const moreChampions = clue.match(/^The (.+) has more Champions League titles than the (.+)\.$/); + if (moreChampions) { + return tMoreChampions(locale, moreChampions[1], moreChampions[2]); + } + + const sameChampions = clue.match(/^The (.+) and (.+) have won the same number of Champions League titles\.$/); + if (sameChampions) { + return tSameChampions(locale, sameChampions[1], sameChampions[2]); + } + + const wonLeagueTitles = clue.match(/^The (.+) has won (\d+) league titles\.$/); + if (wonLeagueTitles) { + return tWonLeagueTitles(locale, wonLeagueTitles[1], Number(wonLeagueTitles[2])); + } + + const wonCountries = clue.match(/^The (.+) has won league titles in (.+)\.$/); + if (wonCountries) { + return tWonCountries(locale, wonCountries[1], wonCountries[2]); + } + + const bothTopFlight = clue.match(/^The (.+) and (.+) both have played in top-flight football\.$/); + if (bothTopFlight) { + return tBothTopFlight(locale, bothTopFlight[1], bothTopFlight[2]); + } + + const teammates = clue.match(/^The (.+) and (.+) were once teammates at (.+)\.$/); + if (teammates) { + return tTeammates(locale, teammates[1], teammates[2], teammates[3]); + } + + const sameLeagueTitles = clue.match(/^The (.+) and (.+) have won the same number of league titles\.$/); + if (sameLeagueTitles) { + return tSameLeagueTitles(locale, sameLeagueTitles[1], sameLeagueTitles[2]); + } + + const moreLeagueTitles = clue.match(/^The (.+) has more league titles than the (.+)\.$/); + if (moreLeagueTitles) { + return tMoreLeagueTitles(locale, moreLeagueTitles[1], moreLeagueTitles[2]); + } + + const nationality = clue.match(/^The (.+) is from (.+)\.$/); + if (nationality) { + return tNationality(locale, nationality[1], nationality[2]); + } + + return clue; +} + +const positionTranslations: Record> = { + en: { defender: "defender", goalkeeper: "goalkeeper", midfielder: "midfielder", striker: "striker", winger: "winger" }, + es: { defender: "defensa", goalkeeper: "portero", midfielder: "centrocampista", striker: "delantero", winger: "extremo" }, + fr: { defender: "défenseur", goalkeeper: "gardien", midfielder: "milieu", striker: "attaquant", winger: "ailier" }, + de: { defender: "Verteidiger", goalkeeper: "Torwart", midfielder: "Mittelfeldspieler", striker: "Stürmer", winger: "Flügelspieler" }, + it: { defender: "difensore", goalkeeper: "portiere", midfielder: "centrocampista", striker: "attaccante", winger: "ala" }, + pt: { defender: "defesa", goalkeeper: "guarda-redes", midfielder: "médio", striker: "avançado", winger: "extremo" }, +}; + +const countryTranslations: Record> = { + en: {}, + es: { + Argentina: "Argentina", + Austria: "Austria", + Belgium: "Bélgica", + Brazil: "Brasil", + Canada: "Canadá", + Croatia: "Croacia", + England: "Inglaterra", + France: "Francia", + Georgia: "Georgia", + Germany: "Alemania", + Italy: "Italia", + Netherlands: "Países Bajos", + Norway: "Noruega", + Poland: "Polonia", + Portugal: "Portugal", + Scotland: "Escocia", + Spain: "España", + Sweden: "Suecia", + Switzerland: "Suiza", + Ukraine: "Ucrania", + }, + fr: { + Argentina: "Argentine", + Austria: "Autriche", + Belgium: "Belgique", + Brazil: "Brésil", + Canada: "Canada", + Croatia: "Croatie", + England: "Angleterre", + France: "France", + Georgia: "Géorgie", + Germany: "Allemagne", + Italy: "Italie", + Netherlands: "Pays-Bas", + Norway: "Norvège", + Poland: "Pologne", + Portugal: "Portugal", + Scotland: "Écosse", + Spain: "Espagne", + Sweden: "Suède", + Switzerland: "Suisse", + Ukraine: "Ukraine", + }, + de: { + Argentina: "Argentinien", + Austria: "Österreich", + Belgium: "Belgien", + Brazil: "Brasilien", + Canada: "Kanada", + Croatia: "Kroatien", + England: "England", + France: "Frankreich", + Georgia: "Georgien", + Germany: "Deutschland", + Italy: "Italien", + Netherlands: "Niederlande", + Norway: "Norwegen", + Poland: "Polen", + Portugal: "Portugal", + Scotland: "Schottland", + Spain: "Spanien", + Sweden: "Schweden", + Switzerland: "Schweiz", + Ukraine: "Ukraine", + }, + it: { + Argentina: "Argentina", + Austria: "Austria", + Belgium: "Belgio", + Brazil: "Brasile", + Canada: "Canada", + Croatia: "Croazia", + England: "Inghilterra", + France: "Francia", + Georgia: "Georgia", + Germany: "Germania", + Italy: "Italia", + Netherlands: "Paesi Bassi", + Norway: "Norvegia", + Poland: "Polonia", + Portugal: "Portogallo", + Scotland: "Scozia", + Spain: "Spagna", + Sweden: "Svezia", + Switzerland: "Svizzera", + Ukraine: "Ucraina", + }, + pt: { + Argentina: "Argentina", + Austria: "Áustria", + Belgium: "Bélgica", + Brazil: "Brasil", + Canada: "Canadá", + Croatia: "Croácia", + England: "Inglaterra", + France: "França", + Georgia: "Geórgia", + Germany: "Alemanha", + Italy: "Itália", + Netherlands: "Países Baixos", + Norway: "Noruega", + Poland: "Polónia", + Portugal: "Portugal", + Scotland: "Escócia", + Spain: "Espanha", + Sweden: "Suécia", + Switzerland: "Suíça", + Ukraine: "Ucrânia", + }, +}; + +function pos(locale: Locale, position: string): string { + return positionTranslations[locale][position] ?? position; +} + +function countries(locale: Locale, value: string): string { + return value + .split(" and ") + .map((country) => countryTranslations[locale][country] ?? country) + .join(tAnd(locale)); +} + +function tAnd(locale: Locale): string { + return locale === "de" ? " und " : locale === "it" ? " e " : locale === "pt" ? " e " : locale === "fr" ? " et " : " y "; +} + +function tSharedClub(locale: Locale, count: number): string { + if (locale === "es") return count === 2 ? "Dos jugadores comparten club." : `${count} jugadores comparten club.`; + if (locale === "fr") return count === 2 ? "Deux joueurs partagent le même club." : `${count} joueurs partagent le même club.`; + if (locale === "de") return count === 2 ? "Zwei Spieler haben denselben Klub." : `${count} Spieler haben denselben Klub.`; + if (locale === "it") return count === 2 ? "Due giocatori condividono lo stesso club." : `${count} giocatori condividono lo stesso club.`; + return count === 2 ? "Dois jogadores partilham o mesmo clube." : `${count} jogadores partilham o mesmo clube.`; +} + +function tLeagueCount(locale: Locale, count: number, league: string): string { + if (locale === "es") return `${count} ${count === 1 ? "jugador juega" : "jugadores juegan"} en ${league}.`; + if (locale === "fr") return `${count} ${count === 1 ? "joueur évolue" : "joueurs évoluent"} en ${league}.`; + if (locale === "de") return `${count} ${count === 1 ? "Spieler spielt" : "Spieler spielen"} in der ${league}.`; + if (locale === "it") return `${count} ${count === 1 ? "giocatore gioca" : "giocatori giocano"} in ${league}.`; + return `${count} ${count === 1 ? "jogador joga" : "jogadores jogam"} na ${league}.`; +} + +function tAllDifferentClubs(locale: Locale): string { + if (locale === "es") return "Los cinco jugadores son de clubes diferentes."; + if (locale === "fr") return "Les cinq joueurs viennent de clubs différents."; + if (locale === "de") return "Alle fünf Spieler kommen aus unterschiedlichen Klubs."; + if (locale === "it") return "Tutti e cinque i giocatori vengono da club diversi."; + return "Os cinco jogadores vêm de clubes diferentes."; +} + +function tMoreChampions(locale: Locale, left: string, right: string): string { + if (locale === "es") return `El ${pos(locale, left)} tiene más Champions League que el ${pos(locale, right)}.`; + if (locale === "fr") return `Le ${pos(locale, left)} a plus de Ligues des champions que le ${pos(locale, right)}.`; + if (locale === "de") return `Der ${pos(locale, left)} hat mehr Champions-League-Titel als der ${pos(locale, right)}.`; + if (locale === "it") return `Il ${pos(locale, left)} ha più Champions League del ${pos(locale, right)}.`; + return `O ${pos(locale, left)} tem mais Champions League do que o ${pos(locale, right)}.`; +} + +function tSameChampions(locale: Locale, left: string, right: string): string { + if (locale === "es") return `El ${pos(locale, left)} y el ${pos(locale, right)} han ganado el mismo número de Champions League.`; + if (locale === "fr") return `Le ${pos(locale, left)} et le ${pos(locale, right)} ont gagné le même nombre de Ligues des champions.`; + if (locale === "de") return `Der ${pos(locale, left)} und der ${pos(locale, right)} haben gleich viele Champions-League-Titel gewonnen.`; + if (locale === "it") return `Il ${pos(locale, left)} e il ${pos(locale, right)} hanno vinto lo stesso numero di Champions League.`; + return `O ${pos(locale, left)} e o ${pos(locale, right)} ganharam o mesmo número de Champions League.`; +} + +function tWonLeagueTitles(locale: Locale, position: string, count: number): string { + if (locale === "es") return `El ${pos(locale, position)} ha ganado ${count} ${count === 1 ? "liga" : "ligas"}.`; + if (locale === "fr") return `Le ${pos(locale, position)} a gagné ${count} ${count === 1 ? "championnat" : "championnats"}.`; + if (locale === "de") return `Der ${pos(locale, position)} hat ${count} Ligatitel gewonnen.`; + if (locale === "it") return `Il ${pos(locale, position)} ha vinto ${count} ${count === 1 ? "campionato" : "campionati"}.`; + return `O ${pos(locale, position)} ganhou ${count} ${count === 1 ? "campeonato" : "campeonatos"}.`; +} + +function tWonCountries(locale: Locale, position: string, value: string): string { + if (locale === "es") return `El ${pos(locale, position)} ha ganado ligas en ${countries(locale, value)}.`; + if (locale === "fr") return `Le ${pos(locale, position)} a gagné des championnats en ${countries(locale, value)}.`; + if (locale === "de") return `Der ${pos(locale, position)} hat Ligatitel in ${countries(locale, value)} gewonnen.`; + if (locale === "it") return `Il ${pos(locale, position)} ha vinto campionati in ${countries(locale, value)}.`; + return `O ${pos(locale, position)} ganhou campeonatos em ${countries(locale, value)}.`; +} + +function tBothTopFlight(locale: Locale, left: string, right: string): string { + if (locale === "es") return `El ${pos(locale, left)} y el ${pos(locale, right)} han jugado en primera división.`; + if (locale === "fr") return `Le ${pos(locale, left)} et le ${pos(locale, right)} ont joué en première division.`; + if (locale === "de") return `Der ${pos(locale, left)} und der ${pos(locale, right)} haben erstklassig gespielt.`; + if (locale === "it") return `Il ${pos(locale, left)} e il ${pos(locale, right)} hanno giocato in massima serie.`; + return `O ${pos(locale, left)} e o ${pos(locale, right)} jogaram na primeira divisão.`; +} + +function tTeammates(locale: Locale, left: string, right: string, club: string): string { + if (locale === "es") return `El ${pos(locale, left)} y el ${pos(locale, right)} fueron compañeros en ${club}.`; + if (locale === "fr") return `Le ${pos(locale, left)} et le ${pos(locale, right)} ont été coéquipiers à ${club}.`; + if (locale === "de") return `Der ${pos(locale, left)} und der ${pos(locale, right)} waren einst Teamkollegen bei ${club}.`; + if (locale === "it") return `Il ${pos(locale, left)} e il ${pos(locale, right)} sono stati compagni al ${club}.`; + return `O ${pos(locale, left)} e o ${pos(locale, right)} foram colegas no ${club}.`; +} + +function tSameLeagueTitles(locale: Locale, left: string, right: string): string { + if (locale === "es") return `El ${pos(locale, left)} y el ${pos(locale, right)} han ganado el mismo número de ligas.`; + if (locale === "fr") return `Le ${pos(locale, left)} et le ${pos(locale, right)} ont gagné le même nombre de championnats.`; + if (locale === "de") return `Der ${pos(locale, left)} und der ${pos(locale, right)} haben gleich viele Ligatitel gewonnen.`; + if (locale === "it") return `Il ${pos(locale, left)} e il ${pos(locale, right)} hanno vinto lo stesso numero di campionati.`; + return `O ${pos(locale, left)} e o ${pos(locale, right)} ganharam o mesmo número de campeonatos.`; +} + +function tMoreLeagueTitles(locale: Locale, left: string, right: string): string { + if (locale === "es") return `El ${pos(locale, left)} tiene más ligas que el ${pos(locale, right)}.`; + if (locale === "fr") return `Le ${pos(locale, left)} a plus de championnats que le ${pos(locale, right)}.`; + if (locale === "de") return `Der ${pos(locale, left)} hat mehr Ligatitel als der ${pos(locale, right)}.`; + if (locale === "it") return `Il ${pos(locale, left)} ha più campionati del ${pos(locale, right)}.`; + return `O ${pos(locale, left)} tem mais campeonatos do que o ${pos(locale, right)}.`; +} + +function tNationality(locale: Locale, position: string, country: string): string { + if (locale === "es") return `El ${pos(locale, position)} es de ${countries(locale, country)}.`; + if (locale === "fr") return `Le ${pos(locale, position)} vient de ${countries(locale, country)}.`; + if (locale === "de") return `Der ${pos(locale, position)} kommt aus ${countries(locale, country)}.`; + if (locale === "it") return `Il ${pos(locale, position)} viene da ${countries(locale, country)}.`; + return `O ${pos(locale, position)} é de ${countries(locale, country)}.`; +} diff --git a/lib/sponsor.ts b/lib/sponsor.ts new file mode 100644 index 0000000..1741aae --- /dev/null +++ b/lib/sponsor.ts @@ -0,0 +1,28 @@ +export type SponsorConfig = { + cta: string; + enabled: boolean; + label: string; + name: string; + tagline: string; + url: string; +}; + +export function getSponsorConfig(): SponsorConfig { + const name = process.env.NEXT_PUBLIC_SPONSOR_NAME?.trim() || "Sponsor hidden11"; + const url = process.env.NEXT_PUBLIC_SPONSOR_URL?.trim() || "https://hidden11.app/sponsor"; + const tagline = + process.env.NEXT_PUBLIC_SPONSOR_TAGLINE?.trim() || + "Reach football fans inside a daily puzzle they actually finish."; + const cta = process.env.NEXT_PUBLIC_SPONSOR_CTA?.trim() || "Become a sponsor"; + const label = process.env.NEXT_PUBLIC_SPONSOR_LABEL?.trim() || "Today's sponsor"; + const enabled = process.env.NEXT_PUBLIC_SPONSOR_ENABLED !== "false"; + + return { + cta, + enabled, + label, + name, + tagline, + url, + }; +}