From ada83e03bb75554cbfd74074cb5e85bae8d104f2 Mon Sep 17 00:00:00 2001 From: itay Date: Sat, 25 Jul 2026 10:09:50 +0300 Subject: [PATCH] feat(site): PostHog analytics via npm bundle + CI site deploys - posthog-js bundled from npm (no external snippet load); init key read from PUBLIC_POSTHOG_KEY at build time so it never appears in git. Local builds read site/.env (gitignored); CI reads a repo variable. - Starlight Head override ships the same bundled script on every docs page; the landing page imports it directly. - New site deploy workflow: builds and wrangler-deploys on pushes to main touching site/ (needs the CLOUDFLARE_API_TOKEN repo secret). --- .github/workflows/site.yml | 42 +++++++++++ site/astro.config.mjs | 2 + site/package-lock.json | 129 +++++++++++++++++++++++++++++++++ site/package.json | 1 + site/src/components/Head.astro | 10 +++ site/src/pages/index.astro | 5 ++ site/src/scripts/analytics.ts | 12 +++ 7 files changed, 201 insertions(+) create mode 100644 .github/workflows/site.yml create mode 100644 site/src/components/Head.astro create mode 100644 site/src/scripts/analytics.ts diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml new file mode 100644 index 0000000..ea9a785 --- /dev/null +++ b/.github/workflows/site.yml @@ -0,0 +1,42 @@ +name: Deploy site + +on: + push: + branches: [main] + paths: ["site/**", ".github/workflows/site.yml"] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: deploy-site + cancel-in-progress: true + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + cache-dependency-path: site/package-lock.json + + - name: Install + working-directory: site + run: npm ci + + - name: Build + working-directory: site + env: + PUBLIC_POSTHOG_KEY: ${{ vars.PUBLIC_POSTHOG_KEY }} + run: npm run build + + - name: Deploy + working-directory: site + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + run: npx wrangler deploy diff --git a/site/astro.config.mjs b/site/astro.config.mjs index ea01ad9..955e4e7 100644 --- a/site/astro.config.mjs +++ b/site/astro.config.mjs @@ -12,6 +12,8 @@ export default defineConfig({ "Write an AI coding skill once, run it in every AI coding assistant.", logo: { src: "./src/assets/logo-mark.svg", alt: "adeptability" }, favicon: "/favicon.svg", + // Head override adds the bundled PostHog script to every docs page. + components: { Head: "./src/components/Head.astro" }, // Gold accent retheme, matching the landing page + neon-gold logo. customCss: ["./src/styles/starlight-gold.css"], // Social preview image on every docs page. Starlight already emits diff --git a/site/package-lock.json b/site/package-lock.json index 33a129f..81122f4 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -12,6 +12,7 @@ "@fontsource/jetbrains-mono": "^5.3.0", "@fontsource/space-grotesk": "^5.3.0", "astro": "^7.1.3", + "posthog-js": "^1.407.2", "sharp": "^0.33.5" }, "devDependencies": { @@ -728,6 +729,29 @@ "node": ">=14" } }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/runtime": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", @@ -1986,6 +2010,31 @@ "dev": true, "license": "MIT" }, + "node_modules/@posthog/browser-common": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@posthog/browser-common/-/browser-common-0.2.1.tgz", + "integrity": "sha512-FTVPsRw6GBKWvFwN26TNIQNNYPR9FsUj+B+CKhk/ht63IRzn4yYFtFOjcmW+bfXvNHuRADs6APbZ6Haz1kpoAw==", + "license": "MIT", + "dependencies": { + "@posthog/core": "^1.45.1", + "@posthog/types": "^1.398.0" + } + }, + "node_modules/@posthog/core": { + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.45.1.tgz", + "integrity": "sha512-tLtvzomavb2PPWdGYKsusyIzIeL2Px47v348Smibkay7sMy/83TyPk+Ptsp2NdeOgJsbuwSxWkR2+XA0aSCAaA==", + "license": "MIT", + "dependencies": { + "@posthog/types": "^1.398.0" + } + }, + "node_modules/@posthog/types": { + "version": "1.398.0", + "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.398.0.tgz", + "integrity": "sha512-sJMkl4k+u8yS/0fjHsKqE9xTdsAh30a2WvgChiptellnVoE0e8QJKFgqOMD2sk8FaEArPdeFklAhXvmENAt3Sg==", + "license": "MIT" + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", @@ -2500,6 +2549,13 @@ "@types/node": "*" } }, + "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/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -3343,6 +3399,17 @@ "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", "license": "MIT" }, + "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/crossws": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", @@ -3608,6 +3675,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.4.12", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz", + "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", @@ -3900,6 +3976,12 @@ } } }, + "node_modules/fflate": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.9.tgz", + "integrity": "sha512-zdxgIEddhfsyCaWpJ2SdXEP8ZMrKJ6+5jl4OupODcywU0IhRk6gdXuVGcPICyfx2H97hVK7xmJtRLPjkxAX8Vw==", + "license": "MIT" + }, "node_modules/flattie": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", @@ -6865,6 +6947,41 @@ "node": ">=4" } }, + "node_modules/posthog-js": { + "version": "1.407.2", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.407.2.tgz", + "integrity": "sha512-5deTvXopn+NJWEmCUw8Ix/ms3cv2+60WJ73Vgbvu2wSkZY/FIj2uqAgCnq7IewGpGC+tH7CAbPYFzH6hw8eW1w==", + "license": "(Apache-2.0 AND MIT)", + "dependencies": { + "@posthog/browser-common": "^0.2.0", + "@posthog/core": "^1.45.1", + "@posthog/types": "^1.398.0", + "core-js": "^3.49.0", + "dompurify": "^3.3.2", + "fflate": "^0.4.8", + "preact": "^10.29.3", + "query-selector-shadow-dom": "^1.0.1", + "web-vitals": "^5.3.0" + } + }, + "node_modules/preact": { + "version": "10.29.7", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.7.tgz", + "integrity": "sha512-DCHYrK/B10yUD3ZjLfhZ3WIE/9Vf9VFUODcRE2dRomTYDpJk6z6L9wecSfhfE6M9ZTHUdyQkoC46arIDhEV84Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } + } + }, "node_modules/prismjs": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", @@ -6893,6 +7010,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "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/radix3": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", @@ -8107,6 +8230,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "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" + }, "node_modules/workerd": { "version": "1.20260722.1", "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260722.1.tgz", diff --git a/site/package.json b/site/package.json index a982012..910e63a 100644 --- a/site/package.json +++ b/site/package.json @@ -17,6 +17,7 @@ "@fontsource/jetbrains-mono": "^5.3.0", "@fontsource/space-grotesk": "^5.3.0", "astro": "^7.1.3", + "posthog-js": "^1.407.2", "sharp": "^0.33.5" }, "devDependencies": { diff --git a/site/src/components/Head.astro b/site/src/components/Head.astro new file mode 100644 index 0000000..604d073 --- /dev/null +++ b/site/src/components/Head.astro @@ -0,0 +1,10 @@ +--- +// Starlight Head override: default head plus the bundled PostHog script, +// so every docs page ships analytics without an external snippet. +import Default from '@astrojs/starlight/components/Head.astro'; +--- + + + diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro index 239bbe8..5379ef5 100644 --- a/site/src/pages/index.astro +++ b/site/src/pages/index.astro @@ -83,6 +83,11 @@ const jsonLd = { diff --git a/site/src/scripts/analytics.ts b/site/src/scripts/analytics.ts new file mode 100644 index 0000000..984ed2c --- /dev/null +++ b/site/src/scripts/analytics.ts @@ -0,0 +1,12 @@ +// PostHog analytics, bundled from npm (no external script load). +// The key is injected at build time from PUBLIC_POSTHOG_KEY (site/.env +// locally, a GitHub Actions variable in CI). No key = analytics off. +import posthog from 'posthog-js'; + +const key = import.meta.env.PUBLIC_POSTHOG_KEY; +if (key) { + posthog.init(key, { + api_host: 'https://us.i.posthog.com', + defaults: '2025-05-24', + }); +}