Compare commits
5 Commits
7f67d123d6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4274d680e1 | ||
|
|
eb228ba50b | ||
|
|
8601119f64 | ||
|
|
f487189a19 | ||
|
|
0101447d84 |
@@ -1,10 +1,8 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
'use client'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Fittimo – Bewegung im Alltag | HyggeCraftery',
|
||||
description: 'Sanfte Bewegung und Atemübungen für Körper und Geist im Einklang.',
|
||||
}
|
||||
import Link from 'next/link'
|
||||
import { useEffect } from 'react'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
const accent = '#7DAF8A'
|
||||
|
||||
@@ -16,6 +14,10 @@ const features = [
|
||||
]
|
||||
|
||||
export default function FittimoPage() {
|
||||
useEffect(() => {
|
||||
posthog.capture('app_detail_viewed', { app: 'fittimo' })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div style={{ fontFamily: 'var(--font-mulish, Mulish, sans-serif)', color: '#3D2B1F', background: '#FAFAF7', overflow: 'hidden' }}>
|
||||
|
||||
@@ -98,7 +100,11 @@ export default function FittimoPage() {
|
||||
<p style={{ fontSize: 16, color: 'rgba(250,250,247,0.65)', margin: '0 0 40px', lineHeight: 1.7 }}>
|
||||
Fittimo erscheint bald. Trage dich in unseren Newsletter ein und erfahre als Erste davon.
|
||||
</p>
|
||||
<Link href="/#newsletter" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}>
|
||||
<Link
|
||||
href="/#newsletter"
|
||||
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'app_page', app_name: 'fittimo' })}
|
||||
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}
|
||||
>
|
||||
Benachrichtigen lassen →
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
'use client'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Apps – HyggeCraftery',
|
||||
description: 'Drei sanfte Apps für einen langsameren, bewussteren Alltag.',
|
||||
}
|
||||
import Link from 'next/link'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
const apps = [
|
||||
{
|
||||
@@ -56,6 +53,7 @@ export default function AppsPage() {
|
||||
<Link
|
||||
key={app.name}
|
||||
href={app.href}
|
||||
onClick={() => posthog.capture('app_card_clicked', { app_name: app.name })}
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
display: 'grid',
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
'use client'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Rezeptimo – Kochen mit Freude | HyggeCraftery',
|
||||
description: 'Saisonale Rezepte zum langsamen Kochen — ehrlich, einfach, nährend.',
|
||||
}
|
||||
import Link from 'next/link'
|
||||
import { useEffect } from 'react'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
const accent = '#C4896A'
|
||||
|
||||
@@ -16,6 +14,10 @@ const features = [
|
||||
]
|
||||
|
||||
export default function RezeptimoPage() {
|
||||
useEffect(() => {
|
||||
posthog.capture('app_detail_viewed', { app: 'rezeptimo' })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div style={{ fontFamily: 'var(--font-mulish, Mulish, sans-serif)', color: '#3D2B1F', background: '#FAFAF7', overflow: 'hidden' }}>
|
||||
|
||||
@@ -98,7 +100,11 @@ export default function RezeptimoPage() {
|
||||
<p style={{ fontSize: 16, color: 'rgba(250,250,247,0.65)', margin: '0 0 40px', lineHeight: 1.7 }}>
|
||||
Rezeptimo erscheint bald. Trage dich in unseren Newsletter ein und erfahre als Erste davon.
|
||||
</p>
|
||||
<Link href="/#newsletter" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}>
|
||||
<Link
|
||||
href="/#newsletter"
|
||||
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'app_page', app_name: 'rezeptimo' })}
|
||||
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}
|
||||
>
|
||||
Benachrichtigen lassen →
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
'use client'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Snakkimo – Sprachen lernen | HyggeCraftery',
|
||||
description: 'Sprachen lernen, das sich anfühlt wie durch einen schönen Feed scrollen. Kleine Lektionen, großer Effekt.',
|
||||
}
|
||||
import Link from 'next/link'
|
||||
import { useEffect } from 'react'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
const accent = '#7BA7BC'
|
||||
|
||||
@@ -16,6 +14,10 @@ const features = [
|
||||
]
|
||||
|
||||
export default function SnakkimoPage() {
|
||||
useEffect(() => {
|
||||
posthog.capture('app_detail_viewed', { app: 'snakkimo' })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div style={{ fontFamily: 'var(--font-mulish, Mulish, sans-serif)', color: '#3D2B1F', background: '#FAFAF7', overflow: 'hidden' }}>
|
||||
|
||||
@@ -98,7 +100,11 @@ export default function SnakkimoPage() {
|
||||
<p style={{ fontSize: 16, color: 'rgba(250,250,247,0.65)', margin: '0 0 40px', lineHeight: 1.7 }}>
|
||||
Snakkimo erscheint bald. Trage dich in unseren Newsletter ein und erfahre als Erste davon.
|
||||
</p>
|
||||
<Link href="/#newsletter" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}>
|
||||
<Link
|
||||
href="/#newsletter"
|
||||
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'app_page', app_name: 'snakkimo' })}
|
||||
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}
|
||||
>
|
||||
Benachrichtigen lassen →
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
14
app/layout.tsx
Normal file → Executable file
14
app/layout.tsx
Normal file → Executable file
@@ -3,6 +3,9 @@ import { Cormorant_Garamond, Mulish } from 'next/font/google'
|
||||
import './globals.css'
|
||||
import Nav from '@/components/ui/Nav'
|
||||
import Footer from '@/components/ui/Footer'
|
||||
import PostHogProvider from '@/components/PostHogProvider'
|
||||
import { PostHogPageView } from '@/components/PostHogPageView'
|
||||
import { Suspense } from 'react'
|
||||
|
||||
const cormorant = Cormorant_Garamond({
|
||||
subsets: ['latin'],
|
||||
@@ -45,9 +48,14 @@ export default function RootLayout({
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")`,
|
||||
}}
|
||||
/>
|
||||
<Nav />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
<PostHogProvider>
|
||||
<Suspense fallback={null}>
|
||||
<PostHogPageView />
|
||||
</Suspense>
|
||||
<Nav />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</PostHogProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
|
||||
36
app/page.tsx
36
app/page.tsx
@@ -1,6 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import NewsletterForm from '@/components/ui/NewsletterForm'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
@@ -21,11 +24,19 @@ export default function HomePage() {
|
||||
Handgemachte Stücke und sanfte Rituale für ein Zuhause, das zur Ruhe einlädt. Wir feiern das Langsame, das Echte, das Wesentliche.
|
||||
</p>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 22 }}>
|
||||
<Link href="/shop" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, background: '#C4896A', color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, letterSpacing: 0.3, padding: '16px 32px', borderRadius: 44 }}>
|
||||
<Link
|
||||
href="/shop"
|
||||
onClick={() => posthog.capture('hero_cta_clicked', { destination: '/shop', label: 'Entdecken' })}
|
||||
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, background: '#C4896A', color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, letterSpacing: 0.3, padding: '16px 32px', borderRadius: 44 }}
|
||||
>
|
||||
Entdecken
|
||||
<span style={{ display: 'inline-block', width: 18, height: 18, borderRadius: '50%', border: '1.5px solid rgba(250,250,247,0.6)' }} />
|
||||
</Link>
|
||||
<Link href="/#ueber" style={{ textDecoration: 'none', fontSize: 15, fontWeight: 600, color: '#3D2B1F', borderBottom: '1.5px solid #A8B89A', paddingBottom: 3 }}>
|
||||
<Link
|
||||
href="/#ueber"
|
||||
onClick={() => posthog.capture('hero_cta_clicked', { destination: '/#ueber', label: 'Unsere Geschichte' })}
|
||||
style={{ textDecoration: 'none', fontSize: 15, fontWeight: 600, color: '#3D2B1F', borderBottom: '1.5px solid #A8B89A', paddingBottom: 3 }}
|
||||
>
|
||||
Unsere Geschichte
|
||||
</Link>
|
||||
</div>
|
||||
@@ -68,14 +79,23 @@ export default function HomePage() {
|
||||
Stücke fürs Zuhause
|
||||
</h2>
|
||||
</div>
|
||||
<Link href="/shop" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, border: '1.5px solid #3D2B1F', color: '#3D2B1F', fontSize: 15, fontWeight: 600, padding: '14px 28px', borderRadius: 44 }}>
|
||||
<Link
|
||||
href="/shop"
|
||||
onClick={() => posthog.capture('hero_cta_clicked', { destination: '/shop', label: 'Zum Shop' })}
|
||||
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, border: '1.5px solid #3D2B1F', color: '#3D2B1F', fontSize: 15, fontWeight: 600, padding: '14px 28px', borderRadius: 44 }}
|
||||
>
|
||||
Zum Shop <span style={{ fontSize: 18, lineHeight: 1 }}>→</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 30 }}>
|
||||
{shopProducts.map((p) => (
|
||||
<Link key={p.name} href="/shop" style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}>
|
||||
<Link
|
||||
key={p.name}
|
||||
href="/shop"
|
||||
onClick={() => posthog.capture('product_teaser_clicked', { product_name: p.name, price: p.price })}
|
||||
style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}
|
||||
>
|
||||
<div style={{ position: 'relative', height: 360, borderRadius: 30, overflow: 'hidden', background: p.bg, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', padding: 18 }}>
|
||||
{p.badge && (
|
||||
<span style={{ position: 'absolute', top: 18, left: 18, background: '#A8B89A', color: '#FAFAF7', fontSize: 11.5, fontWeight: 700, letterSpacing: 0.6, padding: '6px 13px', borderRadius: 30 }}>
|
||||
@@ -117,7 +137,11 @@ export default function HomePage() {
|
||||
</div>
|
||||
<h3 style={{ fontFamily: 'var(--font-cormorant, "Cormorant Garamond", serif)', fontWeight: 600, fontSize: 27, margin: '0 0 10px', color: '#FAFAF7' }}>{app.name}</h3>
|
||||
<p style={{ fontSize: 14.5, color: 'rgba(250,250,247,0.6)', margin: '0 0 22px' }}>{app.desc}</p>
|
||||
<Link href={app.href} style={{ textDecoration: 'none', fontSize: 14.5, fontWeight: 600, color: app.linkColor, borderBottom: `1.5px solid ${app.linkColor}50`, paddingBottom: 2 }}>
|
||||
<Link
|
||||
href={app.href}
|
||||
onClick={() => posthog.capture('app_teaser_clicked', { app_name: app.name })}
|
||||
style={{ textDecoration: 'none', fontSize: 14.5, fontWeight: 600, color: app.linkColor, borderBottom: `1.5px solid ${app.linkColor}50`, paddingBottom: 2 }}
|
||||
>
|
||||
Mehr erfahren →
|
||||
</Link>
|
||||
</div>
|
||||
@@ -139,7 +163,7 @@ export default function HomePage() {
|
||||
<p style={{ fontSize: 16, color: '#8a7a68', margin: '0 auto 36px', maxWidth: 460 }}>
|
||||
Sanfte Geschichten, saisonale Rituale und stille Inspiration — etwa einmal im Monat, ganz ohne Eile.
|
||||
</p>
|
||||
<NewsletterForm />
|
||||
<NewsletterForm source="homepage" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
'use client'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Shop – HyggeCraftery',
|
||||
description: 'Handgemachte Stücke für ein langsameres, schöneres Zuhause.',
|
||||
}
|
||||
import Link from 'next/link'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
const products = [
|
||||
{ name: 'Leinen-Kissen «Fjord»', price: '€ 48', desc: 'Sanftes Leinen in gedämpftem Salbei.', badge: 'Neu', bg: 'repeating-linear-gradient(40deg,#F0E8DA,#F0E8DA 11px,#E7DDCC 11px,#E7DDCC 22px)' },
|
||||
@@ -46,7 +43,11 @@ export default function ShopPage() {
|
||||
{/* Product grid */}
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 30 }}>
|
||||
{products.map((p) => (
|
||||
<div key={p.name} style={{ display: 'block', color: 'inherit' }}>
|
||||
<div
|
||||
key={p.name}
|
||||
onClick={() => posthog.capture('product_viewed', { product_name: p.name, price: p.price })}
|
||||
style={{ display: 'block', color: 'inherit', cursor: 'pointer' }}
|
||||
>
|
||||
<div style={{ position: 'relative', height: 360, borderRadius: 30, overflow: 'hidden', background: p.bg, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', padding: 18 }}>
|
||||
{p.badge && (
|
||||
<span style={{ position: 'absolute', top: 18, left: 18, background: p.badge === 'Bald' ? '#C4896A' : '#A8B89A', color: '#FAFAF7', fontSize: 11.5, fontWeight: 700, letterSpacing: 0.6, padding: '6px 13px', borderRadius: 30 }}>
|
||||
|
||||
22
components/PostHogPageView.tsx
Normal file
22
components/PostHogPageView.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
'use client'
|
||||
|
||||
import { usePathname, useSearchParams } from 'next/navigation'
|
||||
import { usePostHog } from 'posthog-js/react'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export function PostHogPageView() {
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const posthog = usePostHog()
|
||||
|
||||
useEffect(() => {
|
||||
if (pathname && posthog) {
|
||||
let url = window.origin + pathname
|
||||
const search = searchParams.toString()
|
||||
if (search) url += `?${search}`
|
||||
posthog.capture('$pageview', { $current_url: url })
|
||||
}
|
||||
}, [pathname, searchParams, posthog])
|
||||
|
||||
return null
|
||||
}
|
||||
18
components/PostHogProvider.tsx
Normal file
18
components/PostHogProvider.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import posthog from 'posthog-js'
|
||||
import { PostHogProvider as PHProvider } from 'posthog-js/react'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export default function PostHogProvider({ children }: { children: React.ReactNode }) {
|
||||
useEffect(() => {
|
||||
posthog.init('phc_BHgg9S7CQqVShe7EMCdi86PxA49qcNaTsR9Nn5EGxRCT', {
|
||||
api_host: '/ingest',
|
||||
ui_host: 'https://analytics.hyggecraftery.com',
|
||||
capture_pageview: false,
|
||||
persistence: 'memory',
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <PHProvider client={posthog}>{children}</PHProvider>
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import Link from 'next/link'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
@@ -25,10 +28,10 @@ export default function Footer() {
|
||||
Entdecken
|
||||
</h4>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
<FooterLink href="/shop">Shop</FooterLink>
|
||||
<FooterLink href="/apps">Apps</FooterLink>
|
||||
<FooterLink href="/#ueber">Über uns</FooterLink>
|
||||
<FooterLink href="/#newsletter">Newsletter</FooterLink>
|
||||
<FooterLink href="/shop" section="Entdecken">Shop</FooterLink>
|
||||
<FooterLink href="/apps" section="Entdecken">Apps</FooterLink>
|
||||
<FooterLink href="/#ueber" section="Entdecken">Über uns</FooterLink>
|
||||
<FooterLink href="/#newsletter" section="Entdecken">Newsletter</FooterLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,10 +41,10 @@ export default function Footer() {
|
||||
Service
|
||||
</h4>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
<FooterLink href="#">Versand</FooterLink>
|
||||
<FooterLink href="#">Kontakt</FooterLink>
|
||||
<FooterLink href="#">Impressum</FooterLink>
|
||||
<FooterLink href="#">Datenschutz</FooterLink>
|
||||
<FooterLink href="#" section="Service">Versand</FooterLink>
|
||||
<FooterLink href="#" section="Service">Kontakt</FooterLink>
|
||||
<FooterLink href="#" section="Service">Impressum</FooterLink>
|
||||
<FooterLink href="#" section="Service">Datenschutz</FooterLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -56,6 +59,7 @@ export default function Footer() {
|
||||
key={abbr}
|
||||
href="#"
|
||||
title={label}
|
||||
onClick={() => posthog.capture('footer_link_clicked', { label, section: 'Folgen' })}
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
width: 42,
|
||||
@@ -86,9 +90,13 @@ export default function Footer() {
|
||||
)
|
||||
}
|
||||
|
||||
function FooterLink({ href, children }: { href: string; children: React.ReactNode }) {
|
||||
function FooterLink({ href, section, children }: { href: string; section: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<Link href={href} style={{ textDecoration: 'none', fontSize: 14.5, color: 'rgba(250,250,247,0.7)' }}>
|
||||
<Link
|
||||
href={href}
|
||||
onClick={() => posthog.capture('footer_link_clicked', { label: String(children), section })}
|
||||
style={{ textDecoration: 'none', fontSize: 14.5, color: 'rgba(250,250,247,0.7)' }}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
const apps = [
|
||||
{ name: 'Snakkimo', href: '/apps/snakkimo', accent: '#7BA7BC' },
|
||||
@@ -26,7 +27,7 @@ export default function Nav() {
|
||||
}}
|
||||
>
|
||||
{/* Logo */}
|
||||
<Link href="/" style={{ textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<Link href="/" onClick={() => posthog.capture('nav_link_clicked', { label: 'Logo', href: '/' })} style={{ textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 34,
|
||||
@@ -50,8 +51,8 @@ export default function Nav() {
|
||||
|
||||
{/* Nav links */}
|
||||
<nav style={{ display: 'flex', alignItems: 'center', gap: 38 }}>
|
||||
<Link href="/#ueber" style={navLinkStyle}>Über uns</Link>
|
||||
<Link href="/shop" style={navLinkStyle}>Shop</Link>
|
||||
<Link href="/#ueber" onClick={() => posthog.capture('nav_link_clicked', { label: 'Über uns', href: '/#ueber' })} style={navLinkStyle}>Über uns</Link>
|
||||
<Link href="/shop" onClick={() => posthog.capture('nav_link_clicked', { label: 'Shop', href: '/shop' })} style={navLinkStyle}>Shop</Link>
|
||||
|
||||
{/* Apps dropdown */}
|
||||
<div
|
||||
@@ -61,7 +62,11 @@ export default function Nav() {
|
||||
>
|
||||
<button
|
||||
style={{ ...navLinkStyle, background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}
|
||||
onClick={() => setAppsOpen((v) => !v)}
|
||||
onClick={() => {
|
||||
const next = !appsOpen
|
||||
setAppsOpen(next)
|
||||
if (next) posthog.capture('nav_apps_dropdown_opened')
|
||||
}}
|
||||
aria-expanded={appsOpen}
|
||||
>
|
||||
Apps
|
||||
@@ -98,7 +103,7 @@ export default function Nav() {
|
||||
fontSize: 14.5,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
onClick={() => setAppsOpen(false)}
|
||||
onClick={() => { setAppsOpen(false); posthog.capture('nav_link_clicked', { label: app.name, href: app.href }) }}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
@@ -118,6 +123,7 @@ export default function Nav() {
|
||||
|
||||
<Link
|
||||
href="/#newsletter"
|
||||
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'nav' })}
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
color: '#FAFAF7',
|
||||
|
||||
8
components/ui/NewsletterForm.tsx
Normal file → Executable file
8
components/ui/NewsletterForm.tsx
Normal file → Executable file
@@ -1,8 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { posthog } from '@/lib/posthog'
|
||||
|
||||
export default function NewsletterForm() {
|
||||
export default function NewsletterForm({ source = 'homepage' }: { source?: string }) {
|
||||
const [email, setEmail] = useState('')
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
|
||||
@@ -21,7 +22,10 @@ export default function NewsletterForm() {
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault()
|
||||
if (email.trim()) setSubmitted(true)
|
||||
if (email.trim()) {
|
||||
posthog.capture('newsletter_signup', { source })
|
||||
setSubmitted(true)
|
||||
}
|
||||
}}
|
||||
style={{ display: 'flex', gap: 12, maxWidth: 480, margin: '0 auto', flexWrap: 'wrap' }}
|
||||
>
|
||||
|
||||
3
lib/posthog.ts
Normal file
3
lib/posthog.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import posthog from 'posthog-js'
|
||||
export { posthog }
|
||||
export { usePostHog } from 'posthog-js/react'
|
||||
@@ -1,4 +1,22 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
const nextConfig = {
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/ingest/static/:path*',
|
||||
destination: 'https://analytics.hyggecraftery.com/static/:path*',
|
||||
},
|
||||
{
|
||||
source: '/ingest/:path*',
|
||||
destination: 'https://analytics.hyggecraftery.com/:path*',
|
||||
},
|
||||
{
|
||||
source: '/ingest/decide',
|
||||
destination: 'https://analytics.hyggecraftery.com/decide',
|
||||
},
|
||||
]
|
||||
},
|
||||
skipTrailingSlashRedirect: true,
|
||||
}
|
||||
|
||||
export default nextConfig;
|
||||
export default nextConfig
|
||||
|
||||
87
package-lock.json
generated
87
package-lock.json
generated
@@ -9,6 +9,7 @@
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"next": "14.2.35",
|
||||
"posthog-js": "^1.396.4",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
},
|
||||
@@ -273,6 +274,21 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@posthog/core": {
|
||||
"version": "1.39.3",
|
||||
"resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.39.3.tgz",
|
||||
"integrity": "sha512-oR+B8Q5O61N+W2+HVOBG9dbxAT/+OVxX+XvpNj6KYgptN2EB14JiKQ9Rm7DNpErNTLV7WApZEK/URkZgldOxfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@posthog/types": "^1.392.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@posthog/types": {
|
||||
"version": "1.392.0",
|
||||
"resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.392.0.tgz",
|
||||
"integrity": "sha512-nctNujXL3FC1v99FktaTMSugSD9ZOZekEpahUSafkU2TSvW+XGKNkQZbokuJtiWvPBK208dwMJva8UfBkChqpw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
@@ -327,6 +343,13 @@
|
||||
"@types/react": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/any-promise": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||
@@ -476,6 +499,17 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js": {
|
||||
"version": "3.49.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz",
|
||||
"integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
@@ -510,6 +544,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.4.11",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz",
|
||||
"integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
@@ -560,6 +603,12 @@
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.4.8",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
|
||||
"integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
@@ -1111,6 +1160,38 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/posthog-js": {
|
||||
"version": "1.396.4",
|
||||
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.396.4.tgz",
|
||||
"integrity": "sha512-PycBmwKQD1T7YFYrGRb8rjQET/UVnexgUy8gVe6UBEhwHXEIhZF4na5VakJbn4zu1wg4tzjt8r7PA4VLu6bDjg==",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"dependencies": {
|
||||
"@posthog/core": "^1.39.3",
|
||||
"@posthog/types": "^1.392.0",
|
||||
"core-js": "^3.38.1",
|
||||
"dompurify": "^3.3.2",
|
||||
"fflate": "^0.4.8",
|
||||
"preact": "^10.29.2",
|
||||
"query-selector-shadow-dom": "^1.0.1",
|
||||
"web-vitals": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.29.3",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.29.3.tgz",
|
||||
"integrity": "sha512-D9NL1GAnJZhc3RndVs4gDdxEeU9TcHgywMrhhOsnpdlvFjdbx0gAsLUnH6JEhlJH5giL7Tx5biWPUSEXE/HPzw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/query-selector-shadow-dom": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz",
|
||||
"integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
@@ -1484,6 +1565,12 @@
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/web-vitals": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-5.3.0.tgz",
|
||||
"integrity": "sha512-q6LWsLatGYZp5VGBIOvbTj6JBV2nOmC8KvWztXBmwJcfFAzhwKwbOxhUH306XY3CcaZDUlSmSuNPBsCn0bFu+g==",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
package.json
Normal file → Executable file
9
package.json
Normal file → Executable file
@@ -9,16 +9,17 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "14.2.35",
|
||||
"posthog-js": "^1.396.4",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"next": "14.2.35"
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1"
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user