Skip to content

Feat/oss readiness and analytics#39

Merged
jpdevhub merged 6 commits into
mainfrom
feat/oss-readiness-and-analytics
May 27, 2026
Merged

Feat/oss readiness and analytics#39
jpdevhub merged 6 commits into
mainfrom
feat/oss-readiness-and-analytics

Conversation

@jpdevhub
Copy link
Copy Markdown
Owner

@jpdevhub jpdevhub commented May 27, 2026

Summary by cubic

Adds PostHog analytics with SPA pageviews, user identification, and a Vercel proxy for ingestion; also streamlines OSS setup, docs, and templates to make contributions easier.

  • New Features

    • Integrated posthog-js; initializes only when VITE_POSTHOG_KEY is set and opts out in dev.
    • Tracks $pageview on route changes via PostHogPageView; app wrapped in PostHogProvider.
    • Identifies users from JWT sub after auth; resets analytics on logout to avoid session carry-over.
    • Added Vercel rewrites for /ingest/* and /ingest/static/* to US PostHog endpoints.
    • .env.example: added VITE_POSTHOG_KEY and VITE_POSTHOG_HOST (defaults to https://us.i.posthog.com).
  • Refactors and Fixes

    • Simplified GitHub issue templates, removed the stale workflow, and added a PR size labeler.
    • Updated CONTRIBUTING and README to reference .env.local; clarified setup and removed emojis in docs and scripts/dev-setup.sh.
    • Fixed lint by adding PostHog to useEffect dependency arrays.
    • Synced package-lock.json with package.json.

Written for commit ad6a9a6. Summary will update on new commits. Review in cubic

@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fresh-scan-ai Ready Ready Preview, Comment May 27, 2026 9:10am

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 18 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="vercel.json">

<violation number="1" location="vercel.json:9">
P1: Missing required `/ingest/array/` rewrite for PostHog remote config. Without it, remote config requests (e.g., `/ingest/array/{token}/config.js`) fall through to the main API, which strips cache-control headers and can cause browsers to use stale SDK configuration.

Add a third rewrite before the catch-all `/ingest/:path*` rule:
```json
{
  "source": "/ingest/array/:path*",
  "destination": "https://us-assets.i.posthog.com/array/:path*"
}
```</violation>
</file>

<file name=".github/workflows/pr-size-labeler.yml">

<violation number="1" location=".github/workflows/pr-size-labeler.yml:9">
P2: Missing `contents: read` permission required by the action. Add `contents: read` to the permissions block.</violation>

<violation number="2" location=".github/workflows/pr-size-labeler.yml:14">
P2: Pin to the latest release v0.5.7 instead of v0.5.5 to get the Node 24 runtime update, security fixes, and updated dependencies.</violation>
</file>

<file name="src/components/PostHogPageView.tsx">

<violation number="1" location="src/components/PostHogPageView.tsx:14">
P1: This component duplicates PostHog's built-in SPA pageview tracking because `defaults: '2026-01-30'` in main.tsx already sets `capture_pageview: 'history_change'`. Every SPA navigation fires two `$pageview` events — one from PostHog's auto-capture and one from this useEffect — inflating pageview counts by 2x.

Either:
1. Remove this component and rely on PostHog's automatic `history_change` tracking (already active), or
2. Add `capture_pageview: false` to the PostHog init config in main.tsx to keep only this manual capture.</violation>
</file>

<file name="src/pages/AuthPage.tsx">

<violation number="1" location="src/pages/AuthPage.tsx:39">
P2: JWT payload decoding uses `atob` directly on a base64url segment, which fails for valid tokens and silently drops PostHog identification.</violation>

<violation number="2" location="src/pages/AuthPage.tsx:40">
P2: `posthog` is used inside `useEffect` but omitted from its dependency array, which can cause user identification to be missed when the client initializes after first render.</violation>
</file>

<file name="src/main.tsx">

<violation number="1" location="src/main.tsx:27">
P2: `PostHogProvider` is always rendered even when `posthog.init` is skipped, so it can receive an uninitialized client when `VITE_POSTHOG_KEY` is absent.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread vercel.json
},
{
"source": "/ingest/:path*",
"destination": "https://us.i.posthog.com/:path*"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Missing required /ingest/array/ rewrite for PostHog remote config. Without it, remote config requests (e.g., /ingest/array/{token}/config.js) fall through to the main API, which strips cache-control headers and can cause browsers to use stale SDK configuration.

Add a third rewrite before the catch-all /ingest/:path* rule:

{
  "source": "/ingest/array/:path*",
  "destination": "https://us-assets.i.posthog.com/array/:path*"
}
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vercel.json, line 9:

<comment>Missing required `/ingest/array/` rewrite for PostHog remote config. Without it, remote config requests (e.g., `/ingest/array/{token}/config.js`) fall through to the main API, which strips cache-control headers and can cause browsers to use stale SDK configuration.

Add a third rewrite before the catch-all `/ingest/:path*` rule:
```json
{
  "source": "/ingest/array/:path*",
  "destination": "https://us-assets.i.posthog.com/array/:path*"
}
```</comment>

<file context>
@@ -1,5 +1,13 @@
+    },
+    {
+      "source": "/ingest/:path*",
+      "destination": "https://us.i.posthog.com/:path*"
+    },
     { "source": "/(.*)", "destination": "/" }
</file context>

const location = useLocation();
const posthog = usePostHog();

useEffect(() => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This component duplicates PostHog's built-in SPA pageview tracking because defaults: '2026-01-30' in main.tsx already sets capture_pageview: 'history_change'. Every SPA navigation fires two $pageview events — one from PostHog's auto-capture and one from this useEffect — inflating pageview counts by 2x.

Either:

  1. Remove this component and rely on PostHog's automatic history_change tracking (already active), or
  2. Add capture_pageview: false to the PostHog init config in main.tsx to keep only this manual capture.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/PostHogPageView.tsx, line 14:

<comment>This component duplicates PostHog's built-in SPA pageview tracking because `defaults: '2026-01-30'` in main.tsx already sets `capture_pageview: 'history_change'`. Every SPA navigation fires two `$pageview` events — one from PostHog's auto-capture and one from this useEffect — inflating pageview counts by 2x.

Either:
1. Remove this component and rely on PostHog's automatic `history_change` tracking (already active), or
2. Add `capture_pageview: false` to the PostHog init config in main.tsx to keep only this manual capture.</comment>

<file context>
@@ -0,0 +1,21 @@
+  const location = useLocation();
+  const posthog = usePostHog();
+
+  useEffect(() => {
+    posthog?.capture('$pageview', {
+      $current_url: window.location.href,
</file context>

pull-requests: write
steps:
- name: Add PR Size Label
uses: pascalgn/size-label-action@v0.5.5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Pin to the latest release v0.5.7 instead of v0.5.5 to get the Node 24 runtime update, security fixes, and updated dependencies.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/pr-size-labeler.yml, line 14:

<comment>Pin to the latest release v0.5.7 instead of v0.5.5 to get the Node 24 runtime update, security fixes, and updated dependencies.</comment>

<file context>
@@ -0,0 +1,23 @@
+      pull-requests: write
+    steps:
+      - name: Add PR Size Label
+        uses: pascalgn/size-label-action@v0.5.5
+        env:
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
</file context>

jobs:
size-label:
runs-on: ubuntu-latest
permissions:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Missing contents: read permission required by the action. Add contents: read to the permissions block.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/pr-size-labeler.yml, line 9:

<comment>Missing `contents: read` permission required by the action. Add `contents: read` to the permissions block.</comment>

<file context>
@@ -0,0 +1,23 @@
+jobs:
+  size-label:
+    runs-on: ubuntu-latest
+    permissions:
+      issues: write
+      pull-requests: write
</file context>

Comment thread src/pages/AuthPage.tsx
// Identify the user in PostHog using their JWT sub claim as the ID.
// The token is a JWT; we decode the payload to get the user ID.
try {
const payload = JSON.parse(atob(accessToken.split('.')[1]));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: JWT payload decoding uses atob directly on a base64url segment, which fails for valid tokens and silently drops PostHog identification.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/pages/AuthPage.tsx, line 39:

<comment>JWT payload decoding uses `atob` directly on a base64url segment, which fails for valid tokens and silently drops PostHog identification.</comment>

<file context>
@@ -31,6 +33,14 @@ export default function AuthPage() {
+      // Identify the user in PostHog using their JWT sub claim as the ID.
+      // The token is a JWT; we decode the payload to get the user ID.
+      try {
+        const payload = JSON.parse(atob(accessToken.split('.')[1]));
+        posthog?.identify(payload.sub, { email: payload.email });
+      } catch {
</file context>
Suggested change
const payload = JSON.parse(atob(accessToken.split('.')[1]));
const base64Url = accessToken.split('.')[1];
const payload = JSON.parse(atob(base64Url.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(base64Url.length / 4) * 4, '=')));

Comment thread src/pages/AuthPage.tsx
// The token is a JWT; we decode the payload to get the user ID.
try {
const payload = JSON.parse(atob(accessToken.split('.')[1]));
posthog?.identify(payload.sub, { email: payload.email });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: posthog is used inside useEffect but omitted from its dependency array, which can cause user identification to be missed when the client initializes after first render.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/pages/AuthPage.tsx, line 40:

<comment>`posthog` is used inside `useEffect` but omitted from its dependency array, which can cause user identification to be missed when the client initializes after first render.</comment>

<file context>
@@ -31,6 +33,14 @@ export default function AuthPage() {
+      // The token is a JWT; we decode the payload to get the user ID.
+      try {
+        const payload = JSON.parse(atob(accessToken.split('.')[1]));
+        posthog?.identify(payload.sub, { email: payload.email });
+      } catch {
+        // Not a JWT or malformed — skip identification silently
</file context>

Comment thread src/main.tsx
Comment on lines +27 to +29
<PostHogProvider client={posthog}>
<App />
</PostHogProvider>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: PostHogProvider is always rendered even when posthog.init is skipped, so it can receive an uninitialized client when VITE_POSTHOG_KEY is absent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/main.tsx, line 27:

<comment>`PostHogProvider` is always rendered even when `posthog.init` is skipped, so it can receive an uninitialized client when `VITE_POSTHOG_KEY` is absent.</comment>

<file context>
@@ -1,10 +1,31 @@
 createRoot(document.getElementById('root')!).render(
   <StrictMode>
-    <App />
+    <PostHogProvider client={posthog}>
+      <App />
+    </PostHogProvider>
</file context>
Suggested change
<PostHogProvider client={posthog}>
<App />
</PostHogProvider>
{POSTHOG_KEY ? (
<PostHogProvider client={posthog}>
<App />
</PostHogProvider>
) : (
<App />
)}

@jpdevhub jpdevhub merged commit 2a9ce00 into main May 27, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant