Skip to content

Commit bc55082

Browse files
committed
feat: sponsors and contributors
1 parent b3d9f31 commit bc55082

File tree

6 files changed

+395
-19
lines changed

6 files changed

+395
-19
lines changed
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
'use client';
2+
3+
import { HeartIcon, PaletteIcon } from '@phosphor-icons/react';
4+
import { motion } from 'motion/react';
5+
import Image from 'next/image';
6+
import Link from 'next/link';
7+
8+
interface Sponsor {
9+
id: string;
10+
name: string;
11+
logo: string;
12+
website: string;
13+
tier: 'platinum' | 'gold' | 'silver' | 'bronze';
14+
}
15+
16+
interface NonCodeContributor {
17+
id: string;
18+
name: string;
19+
role: string;
20+
contribution: string;
21+
avatar?: string;
22+
website?: string;
23+
}
24+
25+
const sponsors: Sponsor[] = [
26+
{
27+
id: 'neon',
28+
name: 'Neon',
29+
logo: '/neon.svg',
30+
website: 'https://neon.tech',
31+
tier: 'bronze',
32+
},
33+
{
34+
id: 'upstash',
35+
name: 'Upstash',
36+
logo: '/upstash.svg',
37+
website: 'https://upstash.com',
38+
tier: 'silver',
39+
},
40+
];
41+
42+
const nonCodeContributors: NonCodeContributor[] = [
43+
{
44+
id: 'dazai',
45+
name: 'Dazai',
46+
role: 'design engineer @ searchable',
47+
contribution: 'Design systems, UI/UX, and more',
48+
avatar:
49+
'https://pbs.twimg.com/profile_images/1945002665005416448/8m0GEHLP_400x400.jpg',
50+
website: 'https://deewakar.info',
51+
},
52+
{
53+
id: 'aaron-mahlke',
54+
name: 'Aaron Mahlke',
55+
role: 'Founding Design Engineer @ mail0',
56+
contribution: 'Branding, Designs, and more',
57+
avatar:
58+
'https://pbs.twimg.com/profile_images/1900513355447603200/mDqwmkZT_400x400.jpg',
59+
website: 'https://mahlke.design',
60+
},
61+
{
62+
id: 'dominik-content',
63+
name: 'Dominik Koch',
64+
role: 'SWE @ MarbleCMS',
65+
contribution: 'Content, Blogs, Social Media, and more',
66+
avatar:
67+
'https://pbs.twimg.com/profile_images/1933961142457581568/i2Y0u0lV_400x400.jpg',
68+
website: '#',
69+
},
70+
];
71+
72+
function FlipCard() {
73+
return (
74+
<motion.div
75+
className="group relative h-80 w-full"
76+
initial="initial"
77+
style={{ perspective: 1000 }}
78+
whileHover="flipped"
79+
>
80+
<motion.div
81+
className="relative h-full w-full"
82+
style={{ transformStyle: 'preserve-3d' }}
83+
transition={{ duration: 0.7, ease: 'easeInOut' }}
84+
variants={{
85+
initial: { rotateY: 0 },
86+
flipped: { rotateY: 180 },
87+
}}
88+
>
89+
{/* Front Side - Sponsors */}
90+
<motion.div
91+
className="absolute inset-0 rounded border border-border bg-card/50 backdrop-blur-sm transition-all duration-300 hover:border-border/80 hover:bg-card/70"
92+
style={{ backfaceVisibility: 'hidden' }}
93+
>
94+
<div className="flex h-full flex-col items-center justify-center p-6">
95+
<motion.div
96+
animate={{ scale: 1, opacity: 1 }}
97+
className="mb-4 rounded-full bg-purple-500/10 p-3"
98+
initial={{ scale: 0.8, opacity: 0 }}
99+
transition={{ delay: 0.2, duration: 0.5 }}
100+
>
101+
<HeartIcon className="h-8 w-8 text-purple-500" weight="duotone" />
102+
</motion.div>
103+
104+
<motion.h3
105+
animate={{ y: 0, opacity: 1 }}
106+
className="mb-3 text-center font-semibold text-2xl sm:text-3xl lg:text-4xl"
107+
initial={{ y: 20, opacity: 0 }}
108+
transition={{ delay: 0.3, duration: 0.5 }}
109+
>
110+
Our Sponsors
111+
</motion.h3>
112+
113+
<motion.p
114+
animate={{ y: 0, opacity: 1 }}
115+
className="mb-6 max-w-2xl text-center text-muted-foreground text-sm sm:text-base lg:text-lg"
116+
initial={{ y: 20, opacity: 0 }}
117+
transition={{ delay: 0.4, duration: 0.5 }}
118+
>
119+
Companies supporting our mission to build privacy-first analytics
120+
</motion.p>
121+
122+
<motion.div
123+
animate={{ y: 0, opacity: 1 }}
124+
className="mb-6 flex flex-wrap items-center justify-center gap-6"
125+
initial={{ y: 20, opacity: 0 }}
126+
transition={{ delay: 0.5, duration: 0.5 }}
127+
>
128+
{sponsors.map((sponsor, index) => (
129+
<motion.div
130+
animate={{ scale: 1, opacity: 1 }}
131+
initial={{ scale: 0, opacity: 0 }}
132+
key={sponsor.id}
133+
transition={{ delay: 0.6 + index * 0.1, duration: 0.3 }}
134+
>
135+
<Link
136+
className="group/sponsor block"
137+
href={sponsor.website}
138+
rel="noopener noreferrer"
139+
target="_blank"
140+
>
141+
<motion.div
142+
className="flex h-16 w-24 items-center justify-center rounded bg-background/50 p-3 transition-all duration-300 hover:bg-background/70"
143+
whileHover={{ scale: 1.05 }}
144+
whileTap={{ scale: 0.95 }}
145+
>
146+
<Image
147+
alt={`${sponsor.name} logo`}
148+
className="max-h-full max-w-full object-contain dark:brightness-0 dark:invert"
149+
height={48}
150+
src={sponsor.logo}
151+
width={80}
152+
/>
153+
</motion.div>
154+
</Link>
155+
</motion.div>
156+
))}
157+
</motion.div>
158+
159+
<motion.div
160+
animate={{ y: 0, opacity: 1 }}
161+
initial={{ y: 20, opacity: 0 }}
162+
transition={{ delay: 0.8, duration: 0.5 }}
163+
>
164+
<Link
165+
className="text-primary text-sm hover:underline"
166+
href="/sponsors"
167+
>
168+
View all sponsors →
169+
</Link>
170+
</motion.div>
171+
</div>
172+
173+
{/* Sci-fi corners */}
174+
<div className="pointer-events-none absolute inset-0">
175+
<div className="absolute top-0 left-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
176+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
177+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
178+
</div>
179+
<div className="-scale-x-[1] absolute top-0 right-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
180+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
181+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
182+
</div>
183+
<div className="-scale-y-[1] absolute bottom-0 left-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
184+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
185+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
186+
</div>
187+
<div className="-scale-[1] absolute right-0 bottom-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
188+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
189+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
190+
</div>
191+
</div>
192+
</motion.div>
193+
194+
{/* Back Side - Non-Code Contributors */}
195+
<motion.div
196+
className="absolute inset-0 rounded border border-border bg-card/50 backdrop-blur-sm transition-all duration-300 hover:border-border/80 hover:bg-card/70"
197+
style={{ backfaceVisibility: 'hidden', transform: 'rotateY(180deg)' }}
198+
>
199+
<div className="flex h-full flex-col p-4">
200+
{/* Header - Compact */}
201+
<div className="mb-4 text-center">
202+
<motion.div
203+
animate={{ scale: 1, opacity: 1 }}
204+
className="mb-2 inline-flex rounded-full bg-blue-500/10 p-1.5"
205+
initial={{ scale: 0.8, opacity: 0 }}
206+
transition={{ delay: 0.2, duration: 0.5 }}
207+
>
208+
<PaletteIcon
209+
className="h-5 w-5 text-blue-500"
210+
weight="duotone"
211+
/>
212+
</motion.div>
213+
214+
<motion.h3
215+
animate={{ y: 0, opacity: 1 }}
216+
className="mb-1 font-semibold text-lg sm:text-xl"
217+
initial={{ y: 20, opacity: 0 }}
218+
transition={{ delay: 0.3, duration: 0.5 }}
219+
>
220+
Beyond Code
221+
</motion.h3>
222+
223+
<motion.p
224+
animate={{ y: 0, opacity: 1 }}
225+
className="text-muted-foreground text-xs"
226+
initial={{ y: 20, opacity: 0 }}
227+
transition={{ delay: 0.4, duration: 0.5 }}
228+
>
229+
Amazing people making Databuddy better
230+
</motion.p>
231+
</div>
232+
233+
{/* Contributors Grid - Constrained Height */}
234+
<motion.div
235+
animate={{ y: 0, opacity: 1 }}
236+
className="grid flex-1 grid-cols-1 gap-2 overflow-hidden sm:grid-cols-3"
237+
initial={{ y: 20, opacity: 0 }}
238+
transition={{ delay: 0.5, duration: 0.5 }}
239+
>
240+
{nonCodeContributors.map((contributor, index) => (
241+
<motion.div
242+
animate={{ scale: 1, opacity: 1 }}
243+
className="group/contributor relative flex flex-col items-center rounded border border-border/30 bg-background/20 p-4 transition-all duration-300 hover:border-border/60 hover:bg-background/40"
244+
initial={{ scale: 0.8, opacity: 0 }}
245+
key={contributor.id}
246+
transition={{ delay: 0.6 + index * 0.1, duration: 0.3 }}
247+
whileHover={{ scale: 1.02 }}
248+
>
249+
{/* Avatar - Bigger */}
250+
<motion.div
251+
className="mb-3 overflow-hidden rounded-full border-2 border-border/50"
252+
whileHover={{ scale: 1.05 }}
253+
>
254+
<Image
255+
alt={contributor.name}
256+
className="h-12 w-12 object-cover"
257+
height={48}
258+
src={contributor.avatar || '/placeholder-avatar.png'}
259+
width={48}
260+
/>
261+
</motion.div>
262+
263+
{/* Name - Bigger */}
264+
<h4 className="mb-2 text-center font-semibold text-foreground text-sm transition-colors group-hover/contributor:text-primary">
265+
{contributor.name}
266+
</h4>
267+
268+
{/* Role - Bigger */}
269+
<div className="mb-2 text-center font-medium text-blue-500 text-xs">
270+
{contributor.role}
271+
</div>
272+
273+
{/* Contribution - Bigger */}
274+
<p className="text-center text-muted-foreground text-xs leading-relaxed">
275+
{contributor.contribution}
276+
</p>
277+
278+
{/* Mini sci-fi corners - Smaller */}
279+
<div className="pointer-events-none absolute inset-0">
280+
<div className="absolute top-0 left-0 h-0.5 w-0.5 group-hover/contributor:animate-[cornerGlitch_0.6s_ease-in-out]">
281+
<div className="absolute top-0 left-0.5 h-0.5 w-0.5 origin-left bg-foreground" />
282+
<div className="absolute top-0 left-0 h-0.5 w-0.5 origin-top bg-foreground" />
283+
</div>
284+
<div className="-scale-x-[1] absolute top-0 right-0 h-0.5 w-0.5 group-hover/contributor:animate-[cornerGlitch_0.6s_ease-in-out]">
285+
<div className="absolute top-0 left-0.5 h-0.5 w-0.5 origin-left bg-foreground" />
286+
<div className="absolute top-0 left-0 h-0.5 w-0.5 origin-top bg-foreground" />
287+
</div>
288+
<div className="-scale-y-[1] absolute bottom-0 left-0 h-0.5 w-0.5 group-hover/contributor:animate-[cornerGlitch_0.6s_ease-in-out]">
289+
<div className="absolute top-0 left-0.5 h-0.5 w-0.5 origin-left bg-foreground" />
290+
<div className="absolute top-0 left-0 h-0.5 w-0.5 origin-top bg-foreground" />
291+
</div>
292+
<div className="-scale-[1] absolute right-0 bottom-0 h-0.5 w-0.5 group-hover/contributor:animate-[cornerGlitch_0.6s_ease-in-out]">
293+
<div className="absolute top-0 left-0.5 h-0.5 w-0.5 origin-left bg-foreground" />
294+
<div className="absolute top-0 left-0 h-0.5 w-0.5 origin-top bg-foreground" />
295+
</div>
296+
</div>
297+
</motion.div>
298+
))}
299+
</motion.div>
300+
</div>
301+
302+
{/* Sci-fi corners */}
303+
<div className="pointer-events-none absolute inset-0">
304+
<div className="absolute top-0 left-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
305+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
306+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
307+
</div>
308+
<div className="-scale-x-[1] absolute top-0 right-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
309+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
310+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
311+
</div>
312+
<div className="-scale-y-[1] absolute bottom-0 left-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
313+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
314+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
315+
</div>
316+
<div className="-scale-[1] absolute right-0 bottom-0 h-2 w-2 group-hover:animate-[cornerGlitch_0.6s_ease-in-out]">
317+
<div className="absolute top-0 left-0.5 h-0.5 w-1.5 origin-left bg-foreground" />
318+
<div className="absolute top-0 left-0 h-2 w-0.5 origin-top bg-foreground" />
319+
</div>
320+
</div>
321+
</motion.div>
322+
</motion.div>
323+
</motion.div>
324+
);
325+
}
326+
327+
export default function AppreciationFlipCards() {
328+
return (
329+
<div className="text-center">
330+
<div className="mb-8">
331+
<h2 className="mb-4 font-semibold text-2xl sm:text-3xl lg:text-4xl">
332+
Appreciation Corner
333+
</h2>
334+
<p className="mx-auto max-w-2xl text-muted-foreground text-sm sm:text-base lg:text-lg">
335+
Recognizing everyone who makes Databuddy possible
336+
</p>
337+
</div>
338+
339+
<div className="flex justify-center">
340+
<FlipCard />
341+
</div>
342+
343+
<p className="mt-6 text-muted-foreground text-sm">
344+
Hover to flip the card and discover more contributors
345+
</p>
346+
</div>
347+
);
348+
}

apps/docs/app/(home)/contributors/page.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Section from '@/components/landing/section';
55
import { Spotlight } from '@/components/landing/spotlight';
66
import { StructuredData } from '@/components/structured-data';
77
import ActivityStats from './activity-stats';
8+
import AppreciationFlipCards from './appreciation-flip-cards';
89
import CodeChurnChart from './code-churn-chart';
910
import CommitActivityChart from './commit-activity-chart';
1011
import ContributorsGrid from './contributors-grid';
@@ -191,7 +192,7 @@ function fetchPullRequestsData(
191192
): Promise<GitHubPullRequest[]> {
192193
const cachedPrsResponse = cache(async () => {
193194
const prsResponse = await fetch(
194-
'https://api.github.com/repos/databuddy-analytics/Databuddy/pulls?state=all&per_page=100',
195+
'https://api.github.com/repos/databuddy-analytics/Databuddy/pulls?state=all&per_page=50',
195196
requestInit
196197
);
197198
if (!prsResponse.ok) {
@@ -501,9 +502,19 @@ export default async function ContributorsPage() {
501502
</div>
502503
</Section>
503504

504-
{/* Commit Activity Section */}
505+
{/* Appreciation Section */}
505506
<Section
506507
className="border-border border-b bg-background/30"
508+
id="appreciation"
509+
>
510+
<div className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8">
511+
<AppreciationFlipCards />
512+
</div>
513+
</Section>
514+
515+
{/* Commit Activity Section */}
516+
<Section
517+
className="border-border border-b bg-background/50"
507518
id="commit-activity"
508519
>
509520
<div className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8">

0 commit comments

Comments
 (0)