Skip to content

Commit b496fe3

Browse files
Merge pull request #90 from MrDemonWolf/claude/landing-page-redesign-60fe0e
feat(web): redesign landing page and footer
2 parents 14a29cc + d3fbd78 commit b496fe3

3 files changed

Lines changed: 353 additions & 67 deletions

File tree

apps/web/src/app/page.tsx

Lines changed: 255 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,268 @@
1-
import { ArrowRight } from "lucide-react";
1+
import {
2+
ArrowRight,
3+
Bot,
4+
Disc3,
5+
Gift,
6+
Github,
7+
MonitorPlay,
8+
Radio,
9+
Ticket,
10+
Timer,
11+
Zap,
12+
} from "lucide-react";
213
import Link from "next/link";
314

415
import { DISCLAIMER, SiteFooter } from "@/components/site-footer";
516
import { WolfMark } from "@/components/wolf-mark";
617

18+
const GITHUB_URL = "https://github.com/MrDemonWolf/wolfathon";
19+
20+
// ── Numbered section kicker ──────────────────────────────────────────────
21+
// One consistent spine down the page: 01 · What's inside, 02 · How it runs …
22+
function Kicker({ index, children }: { index: string; children: React.ReactNode }) {
23+
return (
24+
<span className="inline-flex items-center gap-2.5">
25+
<span className="grid size-7 place-items-center rounded-md border border-primary/25 bg-primary/10 font-mono text-xs font-semibold text-primary">
26+
{index}
27+
</span>
28+
<span className="eyebrow text-xs">{children}</span>
29+
</span>
30+
);
31+
}
32+
33+
// What the toolkit actually does. Names map to the shipped domains (timer,
34+
// rewards, wheel, giveaway, bot, overlays) — no aspirational features.
35+
const FEATURES = [
36+
{
37+
icon: Timer,
38+
title: "Subathon timer",
39+
body: "A timestamp-driven countdown that keeps running while the pack keeps giving. Subs, gifts, bits, and channel points add time automatically over Twitch EventSub.",
40+
},
41+
{
42+
icon: Gift,
43+
title: "Reward tracker",
44+
body: "Names, never numbers. The pack sees exactly who unlocked the next reward, updating live on the overlay as goals fall.",
45+
},
46+
{
47+
icon: Disc3,
48+
title: "Wheel of dares",
49+
body: "Spin Howlwheel on stream for a random dare — on demand, or auto-spun every few subs. Hidden until it lands so nobody sees it coming.",
50+
},
51+
{
52+
icon: Ticket,
53+
title: "Giveaways",
54+
body: "Two-phase prize draws: confirm gift-sub winners, then open an !enter raffle with a fair CSPRNG draw, per-winner reroll, and a clean reset.",
55+
},
56+
{
57+
icon: Bot,
58+
title: "Chat bot",
59+
body: "A built-in Twitch chat bot with toggleable commands and cooldowns — reads chat free, replies through Helix. No separate bot to host.",
60+
},
61+
{
62+
icon: MonitorPlay,
63+
title: "OBS overlays",
64+
body: "Transparent, token-gated browser sources drop straight into OBS. Timer, rewards, and wheel — legible over any scene, no login required.",
65+
},
66+
] as const;
67+
68+
// The operator's three-step path from clone to live.
69+
const STEPS = [
70+
{
71+
icon: Radio,
72+
title: "Connect Twitch",
73+
body: "One OAuth redirect wires up EventSub. Subs, gifts, bits, and points start feeding the timer.",
74+
},
75+
{
76+
icon: MonitorPlay,
77+
title: "Drop overlays into OBS",
78+
body: "Copy the tokenized overlay URLs into browser sources. They render transparent, ready for any scene.",
79+
},
80+
{
81+
icon: Zap,
82+
title: "Go live",
83+
body: "Run everything from one private operator panel while time adds itself. The pack keeps the clock alive.",
84+
},
85+
] as const;
86+
787
export default function LandingPage() {
888
return (
989
<div className="app-bg flex min-h-svh flex-col text-foreground">
10-
<main className="mx-auto flex w-full max-w-6xl flex-1 flex-col items-center justify-center gap-8 px-4 py-16 text-center">
11-
<div className="flex flex-col items-center gap-4">
12-
<WolfMark className="size-16" />
13-
<p className="font-heading text-sm font-semibold uppercase tracking-[0.2em] text-primary">
14-
MrDemonWolf presents
15-
</p>
16-
<h1 className="font-heading text-5xl font-extrabold tracking-tight">
17-
The Wolf Pack Wolfathon
18-
</h1>
19-
<p className="max-w-md text-muted-foreground">
20-
Join the pack — every sub, cheer, and tip keeps the timer running. Live timers, rewards,
21-
giveaways, and overlays for MrDemonWolf&apos;s stream.
90+
<main className="flex-1">
91+
{/* ═══════════════ HERO ═══════════════ */}
92+
<section className="relative overflow-hidden">
93+
{/* Localized brand glow behind the hero copy. */}
94+
<div
95+
aria-hidden
96+
className="pointer-events-none absolute inset-x-0 -top-40 mx-auto h-[420px] max-w-4xl rounded-full bg-primary/15 blur-[120px]"
97+
/>
98+
<div className="relative mx-auto flex w-full max-w-5xl flex-col items-center gap-8 px-4 pb-20 pt-24 text-center sm:pt-32">
99+
<span
100+
className="animate-wolf-rise inline-flex items-center gap-2.5 rounded-full border border-border bg-card/60 px-3.5 py-1.5 backdrop-blur"
101+
style={{ animationDelay: "0ms" }}
102+
>
103+
<WolfMark className="size-5" />
104+
<span className="eyebrow text-[0.7rem]">MrDemonWolf presents</span>
105+
</span>
106+
107+
<h1
108+
className="animate-wolf-rise font-heading text-5xl font-extrabold leading-[1.05] tracking-tight sm:text-6xl md:text-7xl"
109+
style={{ animationDelay: "60ms" }}
110+
>
111+
The Wolf Pack
112+
<br />
113+
<span className="text-primary">Wolfathon.</span>
114+
</h1>
115+
116+
<p
117+
className="animate-wolf-rise max-w-xl text-lg leading-relaxed text-muted-foreground sm:text-xl"
118+
style={{ animationDelay: "120ms" }}
119+
>
120+
One subathon toolkit for MrDemonWolf&apos;s stream. A timer that never stops while the
121+
pack keeps giving — plus rewards, dares, giveaways, and OBS overlays, all run from a
122+
single operator panel.
123+
</p>
124+
125+
<div
126+
className="animate-wolf-rise flex flex-col items-center gap-3 sm:flex-row"
127+
style={{ animationDelay: "180ms" }}
128+
>
129+
<Link
130+
href="/dashboard"
131+
className="group inline-flex min-h-[48px] w-full items-center justify-center gap-2 rounded-xl bg-primary px-7 text-sm font-semibold text-primary-foreground shadow-lg shadow-primary/20 transition-all hover:shadow-xl hover:shadow-primary/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:w-auto"
132+
>
133+
Open the control panel
134+
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
135+
</Link>
136+
<a
137+
href={GITHUB_URL}
138+
target="_blank"
139+
rel="noopener noreferrer"
140+
className="inline-flex min-h-[48px] w-full items-center justify-center gap-2 rounded-xl border border-border bg-card px-7 text-sm font-semibold text-foreground transition-colors hover:border-primary/40 hover:bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:w-auto"
141+
>
142+
<Github className="size-4" />
143+
View on GitHub
144+
<span className="sr-only">(opens in a new tab)</span>
145+
</a>
146+
</div>
147+
148+
<p
149+
className="animate-wolf-rise text-xs text-muted-foreground/80"
150+
style={{ animationDelay: "220ms" }}
151+
>
152+
Stream operators only — viewers watch live on Twitch.
153+
</p>
154+
155+
<div
156+
className="animate-wolf-rise flex flex-wrap items-center justify-center gap-2"
157+
style={{ animationDelay: "260ms" }}
158+
>
159+
{["Twitch EventSub auto-time", "Transparent OBS overlays", "Open source"].map(
160+
(pill) => (
161+
<span
162+
key={pill}
163+
className="rounded-full border border-border bg-card/60 px-3 py-1.5 text-xs font-medium text-muted-foreground"
164+
>
165+
{pill}
166+
</span>
167+
),
168+
)}
169+
</div>
170+
</div>
171+
</section>
172+
173+
{/* ═══════════════ 01 · WHAT'S INSIDE ═══════════════ */}
174+
<section className="mx-auto w-full max-w-6xl px-4 py-20 sm:py-28">
175+
<div className="mx-auto max-w-2xl text-center">
176+
<div className="flex justify-center">
177+
<Kicker index="01">What&apos;s inside</Kicker>
178+
</div>
179+
<h2 className="mt-5 font-heading text-3xl font-bold tracking-tight sm:text-4xl">
180+
Everything a subathon needs, in one place.
181+
</h2>
182+
<p className="mt-4 text-base leading-relaxed text-muted-foreground">
183+
Six tools that share one Twitch connection and one live state — so the timer, the
184+
overlays, and the panel always agree.
185+
</p>
186+
</div>
187+
188+
<div className="mt-14 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
189+
{FEATURES.map(({ icon: Icon, title, body }) => (
190+
<div
191+
key={title}
192+
className="panel-card group flex flex-col rounded-2xl p-6 transition-colors hover:border-primary/40"
193+
>
194+
<div className="mb-5 inline-flex size-11 items-center justify-center rounded-xl border border-primary/20 bg-primary/10 text-primary transition-transform group-hover:scale-105">
195+
<Icon className="size-5" />
196+
</div>
197+
<h3 className="font-heading text-lg font-semibold">{title}</h3>
198+
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">{body}</p>
199+
</div>
200+
))}
201+
</div>
202+
</section>
203+
204+
{/* ═══════════════ 02 · HOW IT RUNS ═══════════════ */}
205+
<section className="border-y border-border/60 bg-card/30">
206+
<div className="mx-auto w-full max-w-6xl px-4 py-20 sm:py-28">
207+
<div className="mx-auto max-w-2xl text-center">
208+
<div className="flex justify-center">
209+
<Kicker index="02">How it runs</Kicker>
210+
</div>
211+
<h2 className="mt-5 font-heading text-3xl font-bold tracking-tight sm:text-4xl">
212+
Clone, connect, and let it run.
213+
</h2>
214+
<p className="mt-4 text-base leading-relaxed text-muted-foreground">
215+
The operator panel sits behind Cloudflare Access; overlays are gated by a secret
216+
token so OBS can read them without a login. Viewers never touch any of it — they
217+
just watch the count climb.
218+
</p>
219+
</div>
220+
221+
<div className="mt-14 grid gap-4 md:grid-cols-3">
222+
{STEPS.map(({ icon: Icon, title, body }, i) => (
223+
<div
224+
key={title}
225+
className="relative rounded-2xl border border-border bg-background/40 p-6"
226+
>
227+
<div className="flex items-center gap-3">
228+
<span className="grid size-8 place-items-center rounded-lg border border-primary/20 bg-primary/10 text-primary">
229+
<Icon className="size-4" />
230+
</span>
231+
<span className="font-mono text-xs font-semibold text-muted-foreground/70">
232+
0{i + 1}
233+
</span>
234+
</div>
235+
<h3 className="mt-4 font-heading text-lg font-semibold">{title}</h3>
236+
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">{body}</p>
237+
</div>
238+
))}
239+
</div>
240+
</div>
241+
</section>
242+
243+
{/* ═══════════════ CTA ═══════════════ */}
244+
<section className="mx-auto w-full max-w-4xl px-4 py-24 text-center sm:py-32">
245+
<WolfMark className="mx-auto size-14" />
246+
<h2 className="mt-6 font-heading text-4xl font-extrabold tracking-tight sm:text-5xl">
247+
Ready to run your subathon?
248+
</h2>
249+
<p className="mx-auto mt-4 max-w-lg text-base leading-relaxed text-muted-foreground">
250+
Fire up the control panel, connect Twitch, and drop the overlays into OBS. The pack
251+
takes it from there.
22252
</p>
23-
</div>
24-
<div className="flex flex-col items-center gap-2">
25-
<Link
26-
href="/dashboard"
27-
className="group inline-flex min-h-[44px] items-center gap-2 rounded-xl bg-primary px-6 py-3.5 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none"
28-
>
29-
Open the control panel
30-
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
31-
</Link>
32-
<p className="text-xs text-muted-foreground/80">
33-
Stream operators only — viewers watch live on Twitch.
253+
<div className="mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row">
254+
<Link
255+
href="/dashboard"
256+
className="group inline-flex min-h-[48px] w-full items-center justify-center gap-2 rounded-xl bg-primary px-7 text-sm font-semibold text-primary-foreground shadow-lg shadow-primary/20 transition-all hover:shadow-xl hover:shadow-primary/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:w-auto"
257+
>
258+
Open the control panel
259+
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
260+
</Link>
261+
</div>
262+
<p className="mx-auto mt-8 max-w-md text-xs leading-relaxed text-muted-foreground/80">
263+
{DISCLAIMER}
34264
</p>
35-
</div>
36-
<p className="max-w-md text-xs leading-relaxed text-muted-foreground/80">{DISCLAIMER}</p>
265+
</section>
37266
</main>
38267
<SiteFooter />
39268
</div>

0 commit comments

Comments
 (0)