Skip to content

Commit eb23f1a

Browse files
feat(web): Enhance landing page with analytics and improvements
Add PostHog analytics, improve download button, and optimize routing for join waitlist and Discord links. Implement Zendesk script and remove unused components.
1 parent 2f41780 commit eb23f1a

32 files changed

+1092
-496
lines changed

apps/web/.env.sample

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ STRIPE_SECRET_KEY=""
1414
STRIPE_WEBHOOK_SECRET=""
1515

1616
VITE_STRIPE_PUBLISHABLE_KEY=""
17+
18+
VITE_POSTHOG_API_KEY=""
19+
VITE_POSTHOG_HOST="https://us.i.posthog.com"
20+
21+
LOOPS_KEY=""

apps/web/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@nangohq/frontend": "^0.69.7",
1818
"@nangohq/node": "^0.69.7",
1919
"@netlify/vite-plugin-tanstack-start": "^1.1.8",
20+
"@posthog/react": "^1.3.0",
2021
"@sentry/tanstackstart-react": "^10.22.0",
2122
"@stripe/stripe-js": "^8.2.0",
2223
"@supabase/ssr": "^0.7.0",
@@ -37,6 +38,7 @@
3738
"exa-js": "^1.10.2",
3839
"lucide-react": "^0.544.0",
3940
"postgres": "^3.4.7",
41+
"posthog-js": "^1.284.0",
4042
"react": "^19.2.0",
4143
"react-dom": "^19.2.0",
4244
"rehype-autolink-headings": "^7.1.0",
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { cn } from "@hypr/utils";
22

3+
import { Icon } from "@iconify-icon/react";
34
import { Link } from "@tanstack/react-router";
45

56
export function DownloadButton() {
@@ -13,21 +14,8 @@ export function DownloadButton() {
1314
"transition-all",
1415
])}
1516
>
16-
Download now
17-
<svg
18-
xmlns="http://www.w3.org/2000/svg"
19-
fill="none"
20-
viewBox="0 0 24 24"
21-
strokeWidth="1.5"
22-
stroke="currentColor"
23-
className="h-5 w-5 ml-2 group-hover:translate-x-1 transition-transform"
24-
>
25-
<path
26-
strokeLinecap="round"
27-
strokeLinejoin="round"
28-
d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
29-
/>
30-
</svg>
17+
<Icon icon="mdi:apple" className="text-xl mr-2" />
18+
Download for Mac
3119
</Link>
3220
);
3321
}

apps/web/src/components/github-open-source.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,10 @@ export function GitHubOpenSource() {
141141

142142
return (
143143
<section className="border-t border-neutral-100">
144-
<div className="border-b border-neutral-100 bg-neutral-50 h-4" />
144+
<div
145+
className="border-b border-neutral-100 bg-neutral-50 h-4"
146+
style={{ backgroundImage: "url(/patterns/slash.svg)" }}
147+
/>
145148
<div className="px-4 py-8">
146149
<div className="lg:hidden max-w-4xl mx-auto">
147150
<OpenSourceButton showStars={true} starCount={STARS_COUNT} />
@@ -277,7 +280,10 @@ export function GitHubOpenSource() {
277280
</div>
278281
</div>
279282
</div>
280-
<div className="border-t border-neutral-100 bg-neutral-50 h-4" />
283+
<div
284+
className="border-t border-neutral-100 bg-neutral-50 h-4"
285+
style={{ backgroundImage: "url(/patterns/slash.svg)" }}
286+
/>
281287
</section>
282288
);
283289
}

apps/web/src/components/join-waitlist-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { cn } from "@hypr/utils";
33
export function JoinWaitlistButton() {
44
return (
55
<a
6-
href="https://tally.so/r/mJaRDY"
6+
href="/join-waitlist"
77
target="_blank"
88
rel="noopener noreferrer"
99
className={cn([

apps/web/src/components/logo-cloud.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function LogoCloud() {
4646
/>
4747

4848
<LogoCard
49-
className="border-r border-b border-neutral-100"
49+
className="md:border-r border-b border-neutral-100"
5050
logo={{
5151
src: "/icons/meta.svg",
5252
alt: "Meta Logo",

apps/web/src/components/social-card.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ export function SocialCard({
5454
return (
5555
<div
5656
className={cn(
57-
"block border border-neutral-100 bg-white p-6 transition-all duration-200 text-left hover:bg-neutral-50",
58-
className,
57+
[
58+
"block border border-neutral-100 bg-white p-6 transition-all duration-200 text-left hover:bg-neutral-50",
59+
className,
60+
],
5961
)}
6062
>
6163
<div className="space-y-4 text-left">

apps/web/src/components/video-modal.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,16 @@ export function VideoModal({ playbackId, isOpen, onClose }: VideoModalProps) {
5858
className="relative w-full max-w-6xl aspect-video"
5959
onClick={(e) => e.stopPropagation()}
6060
>
61-
{/* Close button */}
6261
<button
6362
onClick={onClose}
6463
className={cn(
65-
"absolute -top-12 right-0 p-2",
66-
"text-white hover:text-neutral-300",
67-
"transition-colors duration-200",
64+
["absolute -top-12 right-0 p-2", "text-white hover:text-neutral-300", "transition-colors duration-200"],
6865
)}
6966
aria-label="Close video"
7067
>
7168
<Icon icon="mdi:close" className="text-3xl" />
7269
</button>
7370

74-
{/* Video */}
7571
<MuxPlayer
7672
ref={playerRef}
7773
playbackId={playbackId}

apps/web/src/hooks/use-platform.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,28 @@ export function getHeroCTA(platform: Platform): {
4343
buttonLabel: string;
4444
showInput: boolean;
4545
inputPlaceholder: string;
46+
subtext: string;
4647
} {
4748
if (platform === "mac") {
4849
return {
4950
buttonLabel: "Download",
5051
showInput: false,
5152
inputPlaceholder: "",
53+
subtext: "Free and open-source",
5254
};
5355
} else if (platform === "mobile") {
5456
return {
5557
buttonLabel: "Remind me",
5658
showInput: true,
5759
inputPlaceholder: "Enter your email",
60+
subtext: "Get an email reminder that you can check later",
5861
};
5962
}
60-
// windows, linux, unknown
63+
6164
return {
6265
buttonLabel: "Join",
6366
showInput: true,
6467
inputPlaceholder: "Enter your email",
68+
subtext: "Join the waitlist and get notified as soon as the app is released",
6569
};
6670
}

apps/web/src/hooks/use-posthog.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { usePostHog } from "@posthog/react";
2+
import { useCallback } from "react";
3+
4+
export { usePostHog };
5+
6+
/**
7+
* Hook for type-safe PostHog event tracking
8+
*/
9+
export function useAnalytics() {
10+
const posthog = usePostHog();
11+
12+
const track = useCallback(
13+
(eventName: string, properties?: Record<string, any>) => {
14+
if (!posthog) {
15+
return;
16+
}
17+
posthog.capture(eventName, properties);
18+
},
19+
[posthog],
20+
);
21+
22+
const identify = useCallback(
23+
(userId: string, properties?: Record<string, any>) => {
24+
if (!posthog) {
25+
return;
26+
}
27+
posthog.identify(userId, properties);
28+
},
29+
[posthog],
30+
);
31+
32+
const reset = useCallback(() => {
33+
if (!posthog) {
34+
return;
35+
}
36+
posthog.reset();
37+
}, [posthog]);
38+
39+
return {
40+
track,
41+
identify,
42+
reset,
43+
posthog,
44+
};
45+
}

0 commit comments

Comments
 (0)