Skip to content

Commit 72a9d02

Browse files
Merge pull request #5 from 0xPlaygrounds/adm-1039-add-posthog-to-new-pg-website
ADM-1039 Add posthog to new pg website
2 parents 3d7c8e3 + 7c30fae commit 72a9d02

File tree

8 files changed

+462
-22
lines changed

8 files changed

+462
-22
lines changed

next.config.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
import type { NextConfig } from 'next';
22

33
const nextConfig: NextConfig = {
4-
/* config options here */
4+
async rewrites() {
5+
const posthogHost =
6+
process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com';
7+
8+
try {
9+
const url = new URL(posthogHost);
10+
const target = `${url.origin}/`;
11+
12+
return [
13+
{
14+
source: '/panopticon/:path*',
15+
destination: `${target}:path*`,
16+
},
17+
];
18+
} catch (error) {
19+
console.error('Invalid PostHog URL:', posthogHost);
20+
return [];
21+
}
22+
},
523
};
624

725
export default nextConfig;

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"pre-commit": "lint-staged"
1515
},
1616
"dependencies": {
17+
"@posthog/nextjs": "^0.0.2",
1718
"next": "15.4.6",
19+
"posthog-js": "^1.260.2",
1820
"react": "19.1.0",
1921
"react-dom": "19.1.0"
2022
},

pnpm-lock.yaml

Lines changed: 316 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/layout.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { Metadata } from 'next';
22
import './globals.css';
33
import localFont from 'next/font/local';
4+
import { PostHogClientProvider } from '@/components/analytics/PostHogProvider';
5+
import { Suspense } from 'react';
46

57
export const metadata: Metadata = {
68
title: 'Plagrounds',
@@ -73,7 +75,9 @@ export default function RootLayout({
7375
<link rel="stylesheet" href="https://use.typekit.net/hml2duc.css" />
7476
</head>
7577
<body className={`antialiased ${neueHaas.variable} font-sans`}>
76-
{children}
78+
<Suspense fallback={null}>
79+
<PostHogClientProvider>{children}</PostHogClientProvider>
80+
</Suspense>
7781
</body>
7882
</html>
7983
);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use client';
2+
3+
import posthog from 'posthog-js';
4+
import { useEffect, useState } from 'react';
5+
import { usePathname, useSearchParams } from 'next/navigation';
6+
7+
type Props = {
8+
children: React.ReactNode;
9+
};
10+
11+
export function PostHogClientProvider({ children }: Props) {
12+
const [isInitialized, setIsInitialized] = useState(false);
13+
const pathname = usePathname();
14+
const searchParams = useSearchParams();
15+
16+
useEffect(() => {
17+
if (typeof window === 'undefined' || isInitialized) return;
18+
19+
const key = process.env.NEXT_PUBLIC_POSTHOG_KEY;
20+
if (!key) return;
21+
22+
posthog.init(key, {
23+
api_host: '/panopticon',
24+
capture_pageview: true,
25+
autocapture: true,
26+
});
27+
setIsInitialized(true);
28+
posthog.capture('$pageview');
29+
}, [isInitialized]);
30+
31+
useEffect(() => {
32+
if (!isInitialized) return;
33+
posthog.capture('$pageview');
34+
}, [pathname, searchParams, isInitialized]);
35+
36+
return <>{children}</>;
37+
}

src/components/footer.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
'use client';
2+
13
import Image from 'next/image';
4+
import posthog from 'posthog-js';
25

36
export const Footer = () => {
47
const currentYear = new Date().getFullYear();
@@ -62,6 +65,12 @@ export const Footer = () => {
6265
<a
6366
href="mailto:info@playgrounds.com"
6467
className="hover:underline"
68+
onClick={() => {
69+
posthog.capture('cta_click', {
70+
cta: 'footer_email',
71+
href: 'mailto:info@playgrounds.com',
72+
});
73+
}}
6574
>
6675
info@playgrounds.com
6776
</a>
@@ -80,20 +89,38 @@ export const Footer = () => {
8089
href="https://github.com/0xPlaygrounds"
8190
target="_blank"
8291
className="hover:underline"
92+
onClick={() => {
93+
posthog.capture('cta_click', {
94+
cta: 'footer_github',
95+
href: 'https://github.com/0xPlaygrounds',
96+
});
97+
}}
8398
>
8499
Github
85100
</a>
86101
<a
87102
href="https://www.youtube.com/@arcdotfun"
88103
target="_blank"
89104
className="hover:underline"
105+
onClick={() => {
106+
posthog.capture('cta_click', {
107+
cta: 'footer_youtube',
108+
href: 'https://www.youtube.com/@arcdotfun',
109+
});
110+
}}
90111
>
91112
Youtube
92113
</a>
93114
<a
94115
href="https://x.com/Playgrounds0x"
95116
target="_blank"
96117
className="hover:underline"
118+
onClick={() => {
119+
posthog.capture('cta_click', {
120+
cta: 'footer_x',
121+
href: 'https://x.com/Playgrounds0x',
122+
});
123+
}}
97124
>
98125
X
99126
</a>

src/components/navbar.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client';
22

33
import Image from 'next/image';
4+
import posthog from 'posthog-js';
45

56
export const Navbar = () => {
67
return (
@@ -18,12 +19,19 @@ export const Navbar = () => {
1819
target="_blank"
1920
rel="noopener noreferrer"
2021
className="h-8 cursor-pointer flex border bg-black border-[#333333] hover:border-white/50 transition duration-300 ease-in-out rounded items-center px-3 text-[13px] justify-center"
22+
onClick={() => {
23+
posthog.capture('cta_click', {
24+
cta: 'navbar_github',
25+
href: 'https://github.com/0xPlaygrounds',
26+
});
27+
}}
2128
>
2229
Github
2330
</a>
2431
<div
2532
className="h-8 cursor-pointer transition duration-300 ease-in-out hover:bg-white/80 flex bg-white px-3 text-[13px] rounded text-[#030304] items-center justify-center"
2633
onClick={() => {
34+
posthog.capture('cta_click', { cta: 'navbar_products_scroll' });
2735
const element = document.getElementById('products');
2836
if (element) {
2937
element.scrollIntoView({ behavior: 'smooth' });

src/components/threePlatforms.tsx

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,37 @@
11
import Image from 'next/image';
22

33
export const ThreePlatforms = () => {
4+
const buildUtmUrl = (base: string, content: string) => {
5+
const url = new URL(base);
6+
url.searchParams.set('utm_source', 'playgrounds.network');
7+
url.searchParams.set('utm_medium', 'referral');
8+
url.searchParams.set('utm_campaign', 'homepage');
9+
url.searchParams.set('utm_content', content);
10+
return url.toString();
11+
};
12+
413
const platforms = [
514
{
615
name: 'Rig',
716
logo: '/assets/projects/rig-logo.webp',
817
bgImage: '/assets/projects/rig-bg.webp',
18+
href: buildUtmUrl('https://rig.rs/', 'three_platforms_rig'),
919
description:
1020
'Open-source Rust LLM framework providing high-performance, modular APIs for building scalable AI applications with type safety and lightning-fast execution.',
1121
},
1222
{
1323
name: 'Arc',
1424
logo: '/assets/projects/arc-logo.webp',
1525
bgImage: '/assets/projects/arc-bg.webp',
26+
href: buildUtmUrl('https://arc.fun/', 'three_platforms_arc'),
1627
description:
1728
'AI Rig Complex - A thriving community ecosystem fostering partnerships, side projects, and collaborative innovation built around the Rig framework.',
1829
},
1930
{
2031
name: 'Ryzome',
2132
logo: '/assets/projects/ryzome-logo.webp',
2233
bgImage: '/assets/projects/ryzome-bg.webp',
34+
href: buildUtmUrl('https://ryzome.ai/', 'three_platforms_ryzome'),
2335
description:
2436
'AI-powered workspace platform that transforms how teams collaborate, create, and innovate. The user-facing canvas that brings AI capabilities to everyday workflows.',
2537
},
@@ -41,30 +53,46 @@ export const ThreePlatforms = () => {
4153
Pick and choose what you want to create.
4254
</span>
4355
<div className="max-w-[1216px] flex-col gap-y-6 md:flex-row pt-12 md:pt-16 flex gap-x-4">
44-
{platforms.map((platform, index) => (
45-
<div key={index} className="flex flex-col gap-y-6">
46-
<div className="relative w-full h-[296px] border border-[#333333] rounded-lg overflow-hidden group">
47-
<Image
48-
src={platform.bgImage}
49-
alt=""
50-
fill
51-
className="object-cover transition-opacity duration-[1000ms] opacity-0 group-hover:opacity-100"
52-
/>
53-
<div className="absolute inset-0 bg-black/20" />
54-
<div className="relative z-10 flex items-center justify-center w-full h-full">
56+
{platforms.map((platform, index) => {
57+
const Card = (
58+
<div className="flex flex-col gap-y-6">
59+
<div className="relative w-full h-[296px] border border-[#333333] rounded-lg overflow-hidden group">
5560
<Image
56-
src={platform.logo}
57-
alt={platform.name}
58-
width={250}
59-
height={250}
60-
className="transition-transform duration-500 group-hover:scale-105"
61+
src={platform.bgImage}
62+
alt=""
63+
fill
64+
className="object-cover transition-opacity duration-[1000ms] opacity-0 group-hover:opacity-100"
6165
/>
66+
<div className="absolute inset-0 bg-black/20" />
67+
<div className="relative z-10 flex items-center justify-center w-full h-full">
68+
<Image
69+
src={platform.logo}
70+
alt={platform.name}
71+
width={250}
72+
height={250}
73+
className="transition-transform duration-500 group-hover:scale-105"
74+
/>
75+
</div>
6276
</div>
77+
<span className="text-[18px]">{platform.name}</span>
78+
<span className="text-[#808080]">{platform.description}</span>
6379
</div>
64-
<span className="text-[18px]">{platform.name}</span>
65-
<span className="text-[#808080]">{platform.description}</span>
66-
</div>
67-
))}
80+
);
81+
82+
return platform.href ? (
83+
<a
84+
key={index}
85+
href={platform.href}
86+
target="_blank"
87+
rel="noopener noreferrer"
88+
className="group"
89+
>
90+
{Card}
91+
</a>
92+
) : (
93+
<div key={index}>{Card}</div>
94+
);
95+
})}
6896
</div>
6997
</div>
7098
);

0 commit comments

Comments
 (0)