mirror of
https://github.com/tuono-labs/tuono
synced 2026-07-25 12:52:47 -07:00
docs: enable posthog analytics (#519)
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
VITE_PUBLIC_POSTHOG_KEY=phc_wqyze0qQlWutAwL5RL1Bv83D8bdySCkhcFw9MkTVuI8
|
||||
VITE_PUBLIC_POSTHOG_HOST=https://eu.i.posthog.com
|
||||
VITE_ENV=development
|
||||
VITE_ENABLE_POSTHOG=false
|
||||
@@ -0,0 +1,4 @@
|
||||
VITE_PUBLIC_POSTHOG_KEY=phc_wqyze0qQlWutAwL5RL1Bv83D8bdySCkhcFw9MkTVuI8
|
||||
VITE_PUBLIC_POSTHOG_HOST=https://eu.i.posthog.com
|
||||
VITE_ENV=production
|
||||
VITE_ENABLE_POSTHOG=true
|
||||
@@ -17,6 +17,7 @@
|
||||
"@mdx-js/react": "3.1.0",
|
||||
"@tabler/icons-react": "3.28.1",
|
||||
"clsx": "2.1.1",
|
||||
"posthog-js": "^1.215.5",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"remark-gfm": "4.0.0",
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
import type { ReactNode, JSX } from 'react'
|
||||
|
||||
import { createTheme, MantineProvider, AppShell } from '@mantine/core'
|
||||
|
||||
import type { CSSVariablesResolver } from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
|
||||
import PageWithTOC from '@/components/PageWithTOC'
|
||||
import Navbar from '@/components/Navbar'
|
||||
import Sidebar from '@/components/Sidebar'
|
||||
import MdxProvider from '@/components/MdxProvider'
|
||||
|
||||
import '@mantine/core/styles.css'
|
||||
import '@mantine/code-highlight/styles.css'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
interface RootRouteProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const theme = createTheme({
|
||||
primaryColor: 'violet',
|
||||
primaryShade: { light: 6, dark: 9 },
|
||||
fontFamily: 'Inter',
|
||||
fontFamilyMonospace: 'Menlo',
|
||||
respectReducedMotion: true,
|
||||
radius: {
|
||||
xs: '4px',
|
||||
sm: '4px',
|
||||
lg: '8px',
|
||||
xl: '8px',
|
||||
md: '8px',
|
||||
},
|
||||
fontSizes: {
|
||||
// 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
xs: '14px',
|
||||
sm: '14px',
|
||||
},
|
||||
colors: {
|
||||
dark: [
|
||||
'#d5d7e0',
|
||||
'#acaebf',
|
||||
'#8c8fa3',
|
||||
'#666980',
|
||||
'#4d4f66',
|
||||
'#34354a',
|
||||
'#2b2c3d',
|
||||
'#1d1e30',
|
||||
'#0c0d21',
|
||||
'#01010a',
|
||||
],
|
||||
},
|
||||
headings: {
|
||||
sizes: {
|
||||
h1: {
|
||||
fontSize: '48px',
|
||||
},
|
||||
},
|
||||
},
|
||||
other: {
|
||||
sidebarGrayLight: '#495057',
|
||||
sidebarGrayDark: '#adb5bd',
|
||||
sidebarTextHoverLight: '#212529',
|
||||
sidebarTextHoverDark: '#f8f9fa',
|
||||
},
|
||||
})
|
||||
|
||||
const resolver: CSSVariablesResolver = (th) => {
|
||||
const {
|
||||
sidebarGrayLight,
|
||||
sidebarTextHoverLight,
|
||||
sidebarGrayDark,
|
||||
sidebarTextHoverDark,
|
||||
} = th.other as Record<string, string>
|
||||
|
||||
return {
|
||||
variables: {},
|
||||
light: {
|
||||
'--mantine-color-footer-bg': th.colors.gray[1],
|
||||
'--mantine-color-sidebar-gray': sidebarGrayLight,
|
||||
'--mantine-color-sidebar-text-hover': sidebarTextHoverLight,
|
||||
'--mantine-color-quote-border': th.colors.violet[1],
|
||||
},
|
||||
dark: {
|
||||
'--mantine-color-footer-bg': th.colors.dark[6],
|
||||
'--mantine-color-sidebar-gray': sidebarGrayDark,
|
||||
'--mantine-color-sidebar-text-hover': sidebarTextHoverDark,
|
||||
'--mantine-color-quote-border': th.colors.violet[9],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default function App({ children }: RootRouteProps): JSX.Element {
|
||||
const [opened, { toggle }] = useDisclosure()
|
||||
|
||||
return (
|
||||
<MantineProvider theme={theme} cssVariablesResolver={resolver}>
|
||||
<AppShell
|
||||
layout="alt"
|
||||
header={{ height: 60 }}
|
||||
navbar={{
|
||||
width: 300,
|
||||
breakpoint: 'sm',
|
||||
collapsed: { mobile: !opened },
|
||||
}}
|
||||
>
|
||||
<Navbar toggle={toggle} />
|
||||
<Sidebar close={toggle} />
|
||||
<AppShell.Main pt={0} px="auto">
|
||||
<MdxProvider>
|
||||
<PageWithTOC>{children}</PageWithTOC>
|
||||
</MdxProvider>
|
||||
</AppShell.Main>
|
||||
<Footer />
|
||||
</AppShell>
|
||||
</MantineProvider>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import App from './App'
|
||||
|
||||
export default App
|
||||
@@ -0,0 +1,20 @@
|
||||
import { useEffect } from 'react'
|
||||
import { usePostHog } from 'posthog-js/react'
|
||||
import { useRouter } from 'tuono'
|
||||
|
||||
export default function PostHogPageView(): null {
|
||||
const { pathname } = useRouter()
|
||||
const posthog = usePostHog()
|
||||
|
||||
// Track pageviews
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (pathname && posthog) {
|
||||
const url = window.origin + pathname
|
||||
|
||||
posthog.capture('$pageview', { $current_url: url })
|
||||
}
|
||||
}, [pathname, posthog])
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { JSX, ReactNode } from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import { PostHogProvider as PostHogLibraryProvider } from 'posthog-js/react'
|
||||
import posthogJs from 'posthog-js'
|
||||
|
||||
interface PostHogProviderProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export default function PostHogProvider({
|
||||
children,
|
||||
}: PostHogProviderProps): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (import.meta.env.VITE_ENABLE_POSTHOG === 'true') {
|
||||
posthogJs.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, {
|
||||
api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
|
||||
persistence: 'memory', // Cookieless tracking
|
||||
disable_persistence: true, // Disable persistence
|
||||
loaded: (ph) => {
|
||||
if (import.meta.env.VITE_ENV === 'development') ph.debug()
|
||||
},
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<PostHogLibraryProvider client={posthogJs}>
|
||||
{children}
|
||||
</PostHogLibraryProvider>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import PostHogProvider from './PostHogProvider'
|
||||
import PostHogPageView from './PostHogPageView'
|
||||
|
||||
export { PostHogProvider, PostHogPageView }
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_PUBLIC_POSTHOG_KEY: string
|
||||
readonly VITE_PUBLIC_POSTHOG_HOST: string
|
||||
readonly VITE_ENV: 'production' | 'development'
|
||||
readonly VITE_ENABLE_POSTHOG: 'true' | 'false'
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
||||
@@ -1,104 +1,20 @@
|
||||
import type { ReactNode, JSX } from 'react'
|
||||
import { TuonoScripts } from 'tuono'
|
||||
|
||||
import {
|
||||
ColorSchemeScript,
|
||||
createTheme,
|
||||
MantineProvider,
|
||||
AppShell,
|
||||
mantineHtmlProps,
|
||||
type CSSVariablesResolver,
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { ColorSchemeScript, mantineHtmlProps } from '@mantine/core'
|
||||
|
||||
import PageWithTOC from '@/components/PageWithTOC'
|
||||
import Navbar from '@/components/Navbar'
|
||||
import Sidebar from '@/components/Sidebar'
|
||||
import MdxProvider from '@/components/MdxProvider'
|
||||
import { PostHogProvider, PostHogPageView } from '@/components/PostHog'
|
||||
|
||||
import '@mantine/core/styles.css'
|
||||
import '@mantine/code-highlight/styles.css'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
import App from '@/components/App'
|
||||
|
||||
interface RootRouteProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const theme = createTheme({
|
||||
primaryColor: 'violet',
|
||||
primaryShade: { light: 6, dark: 9 },
|
||||
fontFamily: 'Inter',
|
||||
fontFamilyMonospace: 'Menlo',
|
||||
respectReducedMotion: true,
|
||||
radius: {
|
||||
xs: '4px',
|
||||
sm: '4px',
|
||||
lg: '8px',
|
||||
xl: '8px',
|
||||
md: '8px',
|
||||
},
|
||||
fontSizes: {
|
||||
// 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
xs: '14px',
|
||||
sm: '14px',
|
||||
},
|
||||
colors: {
|
||||
dark: [
|
||||
'#d5d7e0',
|
||||
'#acaebf',
|
||||
'#8c8fa3',
|
||||
'#666980',
|
||||
'#4d4f66',
|
||||
'#34354a',
|
||||
'#2b2c3d',
|
||||
'#1d1e30',
|
||||
'#0c0d21',
|
||||
'#01010a',
|
||||
],
|
||||
},
|
||||
headings: {
|
||||
sizes: {
|
||||
h1: {
|
||||
fontSize: '48px',
|
||||
},
|
||||
},
|
||||
},
|
||||
other: {
|
||||
sidebarGrayLight: '#495057',
|
||||
sidebarGrayDark: '#adb5bd',
|
||||
sidebarTextHoverLight: '#212529',
|
||||
sidebarTextHoverDark: '#f8f9fa',
|
||||
},
|
||||
})
|
||||
|
||||
const resolver: CSSVariablesResolver = (th) => {
|
||||
const {
|
||||
sidebarGrayLight,
|
||||
sidebarTextHoverLight,
|
||||
sidebarGrayDark,
|
||||
sidebarTextHoverDark,
|
||||
} = th.other as Record<string, string>
|
||||
|
||||
return {
|
||||
variables: {},
|
||||
light: {
|
||||
'--mantine-color-footer-bg': th.colors.gray[1],
|
||||
'--mantine-color-sidebar-gray': sidebarGrayLight,
|
||||
'--mantine-color-sidebar-text-hover': sidebarTextHoverLight,
|
||||
'--mantine-color-quote-border': th.colors.violet[1],
|
||||
},
|
||||
dark: {
|
||||
'--mantine-color-footer-bg': th.colors.dark[6],
|
||||
'--mantine-color-sidebar-gray': sidebarGrayDark,
|
||||
'--mantine-color-sidebar-text-hover': sidebarTextHoverDark,
|
||||
'--mantine-color-quote-border': th.colors.violet[9],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default function RootRoute({ children }: RootRouteProps): JSX.Element {
|
||||
const [opened, { toggle }] = useDisclosure()
|
||||
|
||||
return (
|
||||
<html lang="en" {...mantineHtmlProps}>
|
||||
<head>
|
||||
@@ -125,26 +41,10 @@ export default function RootRoute({ children }: RootRouteProps): JSX.Element {
|
||||
<ColorSchemeScript />
|
||||
</head>
|
||||
<body>
|
||||
<MantineProvider theme={theme} cssVariablesResolver={resolver}>
|
||||
<AppShell
|
||||
layout="alt"
|
||||
header={{ height: 60 }}
|
||||
navbar={{
|
||||
width: 300,
|
||||
breakpoint: 'sm',
|
||||
collapsed: { mobile: !opened },
|
||||
}}
|
||||
>
|
||||
<Navbar toggle={toggle} />
|
||||
<Sidebar close={toggle} />
|
||||
<AppShell.Main pt={0} px="auto">
|
||||
<MdxProvider>
|
||||
<PageWithTOC>{children}</PageWithTOC>
|
||||
</MdxProvider>
|
||||
</AppShell.Main>
|
||||
<Footer />
|
||||
</AppShell>
|
||||
</MantineProvider>
|
||||
<PostHogProvider>
|
||||
<PostHogPageView />
|
||||
<App>{children}</App>
|
||||
</PostHogProvider>
|
||||
<TuonoScripts />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Generated
+33
@@ -62,6 +62,9 @@ importers:
|
||||
clsx:
|
||||
specifier: 2.1.1
|
||||
version: 2.1.1
|
||||
posthog-js:
|
||||
specifier: ^1.215.5
|
||||
version: 1.215.5
|
||||
react:
|
||||
specifier: 19.0.0
|
||||
version: 19.0.0
|
||||
@@ -1430,6 +1433,9 @@ packages:
|
||||
convert-source-map@2.0.0:
|
||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||
|
||||
core-js@3.40.0:
|
||||
resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==}
|
||||
|
||||
cross-spawn@5.1.0:
|
||||
resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
|
||||
|
||||
@@ -1764,6 +1770,9 @@ packages:
|
||||
fastq@1.17.1:
|
||||
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
|
||||
|
||||
fflate@0.4.8:
|
||||
resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
|
||||
|
||||
file-entry-cache@8.0.0:
|
||||
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
@@ -2685,6 +2694,12 @@ packages:
|
||||
resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
posthog-js@1.215.5:
|
||||
resolution: {integrity: sha512-42lPur+xvkp51pHz2FQ7Y+KHdZ4eQSNIhUO03EECvc2UsmnM0FiVTrF1bcLwHZMaWfR26gOeuOAAjTUV9tinJg==}
|
||||
|
||||
preact@10.25.4:
|
||||
resolution: {integrity: sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==}
|
||||
|
||||
prelude-ls@1.2.1:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -3394,6 +3409,9 @@ packages:
|
||||
resolution: {integrity: sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
web-vitals@4.2.4:
|
||||
resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
|
||||
|
||||
webidl-conversions@7.0.0:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -4633,6 +4651,8 @@ snapshots:
|
||||
|
||||
convert-source-map@2.0.0: {}
|
||||
|
||||
core-js@3.40.0: {}
|
||||
|
||||
cross-spawn@5.1.0:
|
||||
dependencies:
|
||||
lru-cache: 4.1.5
|
||||
@@ -5119,6 +5139,8 @@ snapshots:
|
||||
dependencies:
|
||||
reusify: 1.0.4
|
||||
|
||||
fflate@0.4.8: {}
|
||||
|
||||
file-entry-cache@8.0.0:
|
||||
dependencies:
|
||||
flat-cache: 4.0.1
|
||||
@@ -6306,6 +6328,15 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
posthog-js@1.215.5:
|
||||
dependencies:
|
||||
core-js: 3.40.0
|
||||
fflate: 0.4.8
|
||||
preact: 10.25.4
|
||||
web-vitals: 4.2.4
|
||||
|
||||
preact@10.25.4: {}
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
prettier@3.4.2: {}
|
||||
@@ -7140,6 +7171,8 @@ snapshots:
|
||||
|
||||
web-streams-polyfill@4.0.0: {}
|
||||
|
||||
web-vitals@4.2.4: {}
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
whatwg-mimetype@3.0.0: {}
|
||||
|
||||
Reference in New Issue
Block a user