Skip to content

Commit 76a3782

Browse files
authored
feat: add PostHog add-on (#317)
1 parent f4c9e90 commit 76a3782

File tree

9 files changed

+171
-0
lines changed

9 files changed

+171
-0
lines changed

.changeset/wicked-paws-live.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/create': minor
3+
---
4+
5+
Add PostHog add-on
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Setting up PostHog
2+
3+
1. Create a PostHog account at [posthog.com](https://posthog.com)
4+
2. Get your Project API Key from [Project Settings](https://app.posthog.com/project/settings)
5+
3. Set `VITE_POSTHOG_KEY` in your `.env.local`
6+
7+
### Optional Configuration
8+
9+
- `VITE_POSTHOG_HOST` - Set this if you're using PostHog Cloud EU (`https://eu.i.posthog.com`) or self-hosting
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# PostHog configuration, get your key from https://app.posthog.com/project/settings
2+
VITE_POSTHOG_KEY=phc_xxx
3+
# Optional: PostHog API host (for self-hosted or EU cloud)
4+
# VITE_POSTHOG_HOST=https://us.i.posthog.com
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import posthog from 'posthog-js'
2+
import { PostHogProvider as BasePostHogProvider } from '@posthog/react'
3+
import type { ReactNode } from 'react'
4+
5+
if (typeof window !== 'undefined' && import.meta.env.VITE_POSTHOG_KEY) {
6+
posthog.init(import.meta.env.VITE_POSTHOG_KEY, {
7+
api_host: import.meta.env.VITE_POSTHOG_HOST || 'https://us.i.posthog.com',
8+
person_profiles: 'identified_only',
9+
capture_pageview: false,
10+
defaults: '2025-11-30',
11+
})
12+
}
13+
14+
interface PostHogProviderProps {
15+
children: ReactNode
16+
}
17+
18+
export default function PostHogProvider({ children }: PostHogProviderProps) {
19+
return <BasePostHogProvider client={posthog}>{children}</BasePostHogProvider>
20+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { createFileRoute, Link } from '@tanstack/react-router'
2+
import { usePostHog } from '@posthog/react'
3+
import { useState } from 'react'
4+
5+
export const Route = createFileRoute('/demo/posthog')({
6+
component: PostHogDemo,
7+
})
8+
9+
function PostHogDemo() {
10+
const posthog = usePostHog()
11+
const [eventCount, setEventCount] = useState(0)
12+
const posthogKey = import.meta.env.VITE_POSTHOG_KEY
13+
const isConfigured = Boolean(posthogKey) && posthogKey !== 'phc_xxx'
14+
15+
const trackEvent = (
16+
eventName: string,
17+
properties?: Record<string, unknown>,
18+
) => {
19+
posthog.capture(eventName, properties)
20+
setEventCount((c) => c + 1)
21+
}
22+
23+
return (
24+
<div className="min-h-screen bg-gray-900 text-white p-8">
25+
<div className="max-w-md mx-auto">
26+
<h1 className="text-3xl font-bold mb-6">PostHog Demo</h1>
27+
28+
{!isConfigured && (
29+
<div className="mb-4 p-4 bg-yellow-900/50 border border-yellow-600 rounded-lg">
30+
<p className="text-yellow-200 text-sm">
31+
<strong>Warning:</strong> VITE_POSTHOG_KEY is not configured.
32+
Events won't be sent to PostHog. Add it to your{' '}
33+
<code className="bg-yellow-900 px-1 rounded">.env</code> file.
34+
</p>
35+
</div>
36+
)}
37+
38+
<div className="bg-gray-800 rounded-lg p-6">
39+
<p className="text-gray-400 mb-4">
40+
Click the button below to send events to PostHog. Check your PostHog
41+
dashboard to see them appear in real-time.
42+
</p>
43+
44+
<button
45+
onClick={() => trackEvent('button_clicked', { button: 'demo' })}
46+
className="w-full bg-cyan-600 hover:bg-cyan-700 px-4 py-3 rounded font-medium"
47+
>
48+
Track Click
49+
</button>
50+
51+
{isConfigured && (
52+
<div className="mt-6 p-4 bg-gray-700 rounded">
53+
<p className="text-sm text-gray-400">Events sent this session:</p>
54+
<p className="text-4xl font-bold text-cyan-400">{eventCount}</p>
55+
</div>
56+
)}
57+
</div>
58+
59+
<p className="mt-4 text-sm text-gray-400">
60+
Open your{' '}
61+
<a
62+
href="https://app.posthog.com/events"
63+
target="_blank"
64+
rel="noopener noreferrer"
65+
className="text-cyan-400 hover:text-cyan-300 underline"
66+
>
67+
PostHog Events
68+
</a>{' '}
69+
page to see these events appear.
70+
</p>
71+
72+
<p className="mt-2 text-sm text-gray-400">
73+
Learn more in the{' '}
74+
<a
75+
href="https://posthog.com/docs/libraries/react"
76+
target="_blank"
77+
rel="noopener noreferrer"
78+
className="text-cyan-400 hover:text-cyan-300 underline"
79+
>
80+
PostHog React docs
81+
</a>
82+
.
83+
</p>
84+
85+
<div className="mt-8">
86+
<Link to="/" className="text-cyan-400 hover:text-cyan-300">
87+
&larr; Back to Home
88+
</Link>
89+
</div>
90+
</div>
91+
</div>
92+
)
93+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
"src/integrations/posthog/provider.tsx",
3+
"src/routes/demo/posthog.tsx",
4+
"_dot_env.local.append"
5+
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "PostHog",
3+
"description": "Product analytics, session replay, and feature flags",
4+
"phase": "add-on",
5+
"modes": ["file-router"],
6+
"type": "add-on",
7+
"category": "analytics",
8+
"color": "#1D4AFF",
9+
"priority": 20,
10+
"link": "https://posthog.com",
11+
"tailwind": true,
12+
"routes": [
13+
{
14+
"icon": "BarChart",
15+
"url": "/demo/posthog",
16+
"name": "PostHog",
17+
"path": "src/routes/demo/posthog.tsx",
18+
"jsName": "PostHogDemo"
19+
}
20+
],
21+
"integrations": [
22+
{
23+
"type": "provider",
24+
"jsName": "PostHogProvider",
25+
"path": "src/integrations/posthog/provider.tsx"
26+
}
27+
]
28+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"dependencies": {
3+
"posthog-js": "^1.335.4",
4+
"@posthog/react": "^1.7.0"
5+
}
6+
}

packages/create/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const AddOnBaseSchema = z.object({
5050
'monitoring',
5151
'cms',
5252
'api',
53+
'analytics',
5354
'i18n',
5455
'tooling',
5556
'other',

0 commit comments

Comments
 (0)