Skip to content

[CI] (gpt54-trial) next-js/15-pages-router-saas#2399

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-gpt54-trial-next-js-15-pages-router-saas
Closed

[CI] (gpt54-trial) next-js/15-pages-router-saas#2399
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-gpt54-trial-next-js-15-pages-router-saas

Conversation

@wizard-ci-bot

@wizard-ci-bot wizard-ci-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

Automated wizard CI run

Source: manual
Trigger ID: gpt54-trial
App: next-js/15-pages-router-saas
App directory: apps/next-js/15-pages-router-saas
Workbench branch: wizard-ci-gpt54-trial-next-js-15-pages-router-saas
Wizard branch: 543fbd70b7d834c9bb2bf5afe28fc0a5761ced5d
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-03T16:11:13.989Z
Duration: 446.5s

YARA Scanner

✓ 180 tool calls scanned, 1 violation detected

  [BLOCKED] pii_in_capture_call (HIGH) — PostToolUse:Edit

No violations: ✓ 179 clean scans

⚠️ YARA violations detected — see report above

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown
Author

Now I have all the context I need. Let me produce the full evaluation report.


PR Evaluation Report

Summary

This PR integrates PostHog into a Next.js 15 Pages Router SaaS app with both client-side (posthog-js) and server-side (posthog-node) SDKs. Client initialization is done via instrumentation-client.ts imported in _app.tsx, a reverse proxy is configured via Next.js rewrites, and event capture is instrumented across authentication, billing, account management, and team management API routes. A server-side singleton helper is created in lib/posthog-server.ts.

Files changed Lines added Lines removed
21 +299 -8

Confidence score: 4/5 👍

  • Client-side identify uses raw email as distinct_id while server-side uses user.id.toString(). This mismatch will cause fragmented user data in PostHog — client events and server events won't be associated with the same person without additional merging. The client should use the user ID returned from the sign-in/sign-up API response. [CRITICAL]
  • Duplicate sign-out events: user_signed_out is captured both client-side (header.tsx) and server-side (sign-out.ts) with the same event name, causing double-counting. [MEDIUM]
  • Stripe webhook uses Stripe customer ID as distinctId (String(subscription.customer)), which won't link to the user's actual PostHog distinct_id (numeric user ID on server). [MEDIUM]
  • No .env.example update: Environment variables (NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN, NEXT_PUBLIC_POSTHOG_HOST) are not documented in any committed file. [MEDIUM]

File changes

Filename Score Description
instrumentation-client.ts 4/5 New file initializing posthog-js with reverse proxy, error tracking, and debug mode
lib/posthog-server.ts 4/5 Server-side PostHog singleton with flushAt:1/flushInterval:0 for short-lived handlers
next.config.ts 5/5 Reverse proxy rewrites correctly routing /ingest to PostHog with assets split
package.json 5/5 posthog-js and posthog-node added as dependencies
pages/_app.tsx 4/5 Imports instrumentation-client to initialize PostHog
components/login.tsx 2/5 Identify uses raw email as distinct_id — should use user ID
components/header.tsx 3/5 Sign-out capture + reset, but duplicates server-side event
pages/api/auth/sign-in.ts 4/5 Server-side capture and identify with user ID
pages/api/auth/sign-up.ts 4/5 Server-side capture and identify with user ID
pages/api/auth/sign-out.ts 3/5 Server-side sign-out capture, duplicates client event
pages/api/stripe/webhook.ts 2/5 Uses Stripe customer ID as distinctId instead of user ID
pages/api/stripe/checkout.ts 4/5 Checkout completed capture with plan details
pages/api/stripe/create-checkout.ts 4/5 Checkout session created capture
pages/api/stripe/customer-portal.ts 4/5 Billing portal opened capture
pages/api/account/update.ts 4/5 Account updated capture with context
pages/api/team/invite.ts 4/5 Team invite server-side capture
pages/api/team/remove-member.ts 4/5 Team member removal server-side capture
pages/dashboard/general.tsx 4/5 Client-side account_updated capture
pages/dashboard/index.tsx 4/5 Client-side team management captures
pages/pricing.tsx 5/5 Pricing checkout started with plan details
posthog-setup-report.md 2/5 Unnecessary generated report file committed

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes No syntax or type errors introduced; all imports resolve
Preserves existing env vars & configs Yes Existing code preserved; next.config.ts comments removed but no functional loss
No syntax or type errors Yes All TypeScript is valid
Correct imports/exports Yes posthog-js imported client-side, posthog-node imported server-side
Minimal, focused changes No Includes unnecessary posthog-setup-report.md and duplicate client/server events
Pre-existing issues None

Issues

  • Unnecessary report file committed: posthog-setup-report.md is a wizard-generated artifact that shouldn't be committed to the codebase. [LOW]
  • Environment variables not documented: No .env.example update for NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN and NEXT_PUBLIC_POSTHOG_HOST. [MEDIUM]

Other completed criteria

  • App builds without errors — valid TypeScript, correct package dependencies
  • Existing app functionality preserved — sign-in/sign-out/sign-up flows still work
  • Build configuration valid — package.json and next.config.ts are well-formed

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js ^1.396.6 and posthog-node ^5.39.4 in package.json
PostHog client initialized Yes instrumentation-client.ts with posthog.init() using env vars, imported in _app.tsx
capture() Yes 16+ meaningful capture calls across client and server
identify() No Client uses raw email as distinct_id (posthog.identify(data.email)), server uses user.id.toString() — mismatch causes fragmented data
Error tracking Yes capture_exceptions: true in init config enables exception autocapture
Reverse proxy Yes Next.js rewrites in next.config.ts correctly routing /ingest/* with static/array asset split

Issues

  • Client identify uses email as distinct_id: In login.tsx, posthog.identify(data.email) uses the raw email address as the distinct_id. The server-side identify in sign-in.ts and sign-up.ts uses foundUser.id.toString(). This mismatch means client-side events and server-side events will be attributed to different distinct IDs, causing fragmented user profiles. The API response should return the user ID and the client should use that. [CRITICAL]
  • Stripe webhook uses Stripe customer ID as distinctId: In webhook.ts, String(subscription.customer) is a Stripe customer ID (e.g., cus_xxx), not the app's user ID. These events won't be associated with the correct PostHog person. [MEDIUM]
  • Duplicate sign-out events: Both header.tsx (client) and sign-out.ts (server) capture user_signed_out, causing double-counting of sign-out events. [MEDIUM]

Other completed criteria

  • API key loaded from process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN (not hardcoded)
  • Host correctly configured via reverse proxy (/ingest) with ui_host pointing to PostHog
  • Server-side client uses singleton pattern with flushAt: 1 and flushInterval: 0 per Next.js docs
  • posthog.reset() called on sign-out in header.tsx
  • Both static and array asset routes correctly proxy to us-assets.i.posthog.com

PostHog insights and events ⚠️

Filename PostHog events Description
components/login.tsx user_signed_in, user_signed_up Client-side auth events with checkout/invite context
components/header.tsx user_signed_out Client-side sign-out with reset()
pages/pricing.tsx pricing_checkout_started Checkout initiation with plan/price details
pages/dashboard/general.tsx account_updated Profile update with change context
pages/dashboard/index.tsx team_member_removed, team_member_invited Team management actions
pages/api/auth/sign-in.ts server_user_signed_in Server-side sign-in with identify
pages/api/auth/sign-up.ts server_user_signed_up Server-side sign-up with identify
pages/api/auth/sign-out.ts user_signed_out Server-side sign-out (duplicates client event)
pages/api/stripe/checkout.ts checkout_completed Stripe checkout completion with plan details
pages/api/stripe/create-checkout.ts server_checkout_session_created Checkout session creation
pages/api/stripe/customer-portal.ts billing_portal_opened Billing portal access
pages/api/stripe/webhook.ts stripe_subscription_changed Subscription updates/cancellations
pages/api/team/invite.ts server_team_member_invited Server-side team invite
pages/api/team/remove-member.ts server_team_member_removed Server-side member removal
pages/api/account/update.ts server_account_updated Server-side account update
instrumentation-client.ts capturedException (autocapture) Exception autocapture enabled

Issues

  • No person properties set on client-side identify: posthog.identify(data.email) doesn't pass person properties (email, name). The server-side identify does set these, but the client should too for consistency. [LOW]
  • Duplicate client/server events with same names: user_signed_out captured in both client and server creates inflated counts. Either rename the server event (e.g., server_user_signed_out) or remove one. [MEDIUM]

Other completed criteria

  • Events represent real user actions across the full SaaS lifecycle (auth, billing, team management)
  • Events enable product insights — can build sign-up → checkout funnel, auth trends, team management metrics
  • Events include relevant contextual properties (plan names, team IDs, subscription status, etc.)
  • No PII in capture event properties — emails only appear in identify person properties
  • Event names are descriptive and use consistent snake_case convention

Reviewed by wizard workbench PR evaluator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants