diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 5c9ff81..da03f45 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -13,10 +13,12 @@ export default defineConfig({ }, ], customCss: ["./src/styles/custom.css"], - // Component overrides for custom design + // Component overrides for custom design and analytics components: { Sidebar: "./src/components/overrides/Sidebar.astro", EditLink: "./src/components/overrides/EditLink.astro", + Head: "./src/components/overrides/Head.astro", + Search: "./src/components/overrides/Search.astro", }, // Autogenerate sidebar from directory structure // Contributors only need to add frontmatter to control ordering diff --git a/docs/src/components/PostHog.astro b/docs/src/components/PostHog.astro new file mode 100644 index 0000000..9d73320 --- /dev/null +++ b/docs/src/components/PostHog.astro @@ -0,0 +1,113 @@ +--- +/** + * PostHog Analytics Component + * + * Initializes PostHog for: + * - Page view tracking + * - Autocapture (clicks, form submits) + * - Session replay + * - Custom event tracking + * + * Uses a reverse proxy through Vercel to bypass ad-blockers. + * + * Environment Variables: + * - PUBLIC_POSTHOG_KEY: Your PostHog project API key (required) + * + * @see https://posthog.com/docs/libraries/astro + */ + +// Get PostHog key from environment variable +// In Astro, PUBLIC_ prefixed env vars are available on the client +const posthogKey = import.meta.env.PUBLIC_POSTHOG_KEY || ""; +--- + + diff --git a/docs/src/components/overrides/Head.astro b/docs/src/components/overrides/Head.astro new file mode 100644 index 0000000..21a8744 --- /dev/null +++ b/docs/src/components/overrides/Head.astro @@ -0,0 +1,20 @@ +--- +/** + * Custom Head Component with PostHog Analytics + * + * Extends Starlight's default Head component to inject PostHog analytics. + * PostHog is loaded early in the head to capture all page interactions. + * + * @see https://starlight.astro.build/guides/overriding-components/ + */ +import PostHog from "../PostHog.astro"; + +const { head } = Astro.locals.starlightRoute; +--- + +{ + head.map(({ tag: Tag, attrs, content }) => ( + + )) +} + diff --git a/docs/src/components/overrides/Search.astro b/docs/src/components/overrides/Search.astro new file mode 100644 index 0000000..bce5c6b --- /dev/null +++ b/docs/src/components/overrides/Search.astro @@ -0,0 +1,649 @@ +--- +/** + * Custom Search Component with PostHog Analytics + * + * Extends Starlight's default Search component to track: + * - Search queries (debounced) + * - Search result clicks + * - Searches with no results + * + * @see https://starlight.astro.build/guides/overriding-components/ + */ +import project from "virtual:starlight/project-context"; + +const pagefindTranslations = { + placeholder: Astro.locals.t("search.label"), + ...Object.fromEntries( + Object.entries(Astro.locals.t.all()) + .filter(([key]) => key.startsWith("pagefind.")) + .map(([key, value]) => [key.replace("pagefind.", ""), value]), + ), +}; + +const dataAttributes: DOMStringMap = { + "data-translations": JSON.stringify(pagefindTranslations), +}; +if (project.trailingSlash === "never") + dataAttributes["data-strip-trailing-slash"] = ""; +--- + + + + + +
+ { + /* TODO: Make the layout of this button flexible to accommodate different word lengths. Currently hard-coded for English: "Cancel" */ + } + + { + import.meta.env.DEV ? ( +
+

{Astro.locals.t("search.devWarning")}

+
+ ) : ( +
+ + ) + } +
+
+
+ +{ + /** + * This is intentionally inlined to avoid briefly showing an invalid shortcut. + * Purposely using the deprecated `navigator.platform` property to detect Apple devices, as the + * user agent is spoofed by some browsers when opening the devtools. + */ +} + + + + + + + diff --git a/docs/src/env.d.ts b/docs/src/env.d.ts new file mode 100644 index 0000000..03ee87f --- /dev/null +++ b/docs/src/env.d.ts @@ -0,0 +1,23 @@ +/// +/// +/// +/// +/// + +declare module "@pagefind/default-ui" { + export class PagefindUI { + constructor(options: { + element?: string; + baseUrl?: string; + bundlePath?: string; + showImages?: boolean; + translations?: Record; + showSubResults?: boolean; + processResult?: (result: { + url: string; + sub_results: Array<{ url: string }>; + }) => void; + [key: string]: unknown; + }); + } +} diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000..f81698d --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "astro/tsconfigs/strict", + "compilerOptions": { + "types": ["@astrojs/starlight"], + "baseUrl": ".", + "paths": { + "virtual:starlight/*": [ + "./node_modules/@astrojs/starlight/virtual.d.ts", + "./node_modules/@astrojs/starlight/virtual-internal.d.ts" + ] + } + }, + "include": [ + "src/**/*", + ".astro/types.d.ts", + "node_modules/@astrojs/starlight/*.d.ts" + ] +} diff --git a/docs/vercel.json b/docs/vercel.json index e37495e..eddacfc 100644 --- a/docs/vercel.json +++ b/docs/vercel.json @@ -2,5 +2,15 @@ "$schema": "https://openapi.vercel.sh/vercel.json", "framework": "astro", "buildCommand": "npm run build", - "outputDirectory": "dist" + "outputDirectory": "dist", + "rewrites": [ + { + "source": "/ingest/static/:path*", + "destination": "https://eu-assets.i.posthog.com/static/:path*" + }, + { + "source": "/ingest/:path*", + "destination": "https://eu.i.posthog.com/:path*" + } + ] }