[CI] (gpt54-trial-fill) next-js/15-app-router-saas#2406
Closed
wizard-ci-bot[bot] wants to merge 1 commit into
Closed
[CI] (gpt54-trial-fill) next-js/15-app-router-saas#2406wizard-ci-bot[bot] wants to merge 1 commit into
wizard-ci-bot[bot] wants to merge 1 commit into
Conversation
Author
|
Now I have enough context. Let me produce the evaluation. PR Evaluation ReportSummaryThis PR integrates PostHog into a Next.js 15 App Router SaaS application, adding client-side initialization via
Confidence score: 4/5 👍
File changes
App sanity check
|
| Criteria | Result | Description |
|---|---|---|
| App builds and runs | Yes | No syntax or type errors that would prevent build |
| Preserves existing env vars & configs | Yes | Existing env vars preserved; original config comments removed but non-functional |
| No syntax or type errors | Yes | All code is syntactically valid TypeScript/TSX |
| Correct imports/exports | Yes | posthog-js used on client, posthog-node on server; all imports resolve |
| Minimal, focused changes | No | posthog-setup-report.md is unnecessary scope creep |
| Pre-existing issues | None | No pre-existing issues observed |
Issues
- Unnecessary report file:
posthog-setup-report.mdis generated documentation that doesn't belong in the codebase as committed code. [LOW] - Removed config comments: Original Next.js config comments about PPR/canary were removed from
next.config.ts. [LOW]
Other completed criteria
- Environment variables documented in both
.env.exampleandREADME.md - Build configuration is valid with proper package.json entries
- Both SDKs correctly added to dependencies
PostHog implementation ❌
| Criteria | Result | Description |
|---|---|---|
| PostHog SDKs installed | Yes | posthog-js@^1.396.6 and posthog-node@^5.39.4 added to package.json |
| PostHog client initialized | Yes | instrumentation-client.ts uses posthog.init() with env vars, correct Next.js 15.3+ pattern |
| capture() | Yes | 12 meaningful events across client and server |
| identify() | No | Uses user.email as distinct_id on client, user.id.toString() on server — mismatched identifiers and PII as distinct_id |
| Error tracking | Yes | capture_exceptions: true in posthog.init() config |
| Reverse proxy | No | Asset host derivation is broken: .replace('i.', 'assets.i.') produces us.assets.i.posthog.com instead of us-assets.i.posthog.com |
Issues
- Broken reverse proxy asset host derivation:
posthogHost?.replace('i.', 'assets.i.')onhttps://us.i.posthog.comproduceshttps://us.assets.i.posthog.com(period-separated) instead of the correcthttps://us-assets.i.posthog.com(hyphen-separated). The/ingest/static/*and/ingest/array/*rewrites will fail to reach PostHog's CDN, breaking SDK asset loading through the proxy. Fix: useposthogHost?.replace('.i.posthog.com', '-assets.i.posthog.com')or hardcode the correct asset host. [CRITICAL] - Mismatched distinct_ids: Client-side uses
user.emailas distinct_id inposthog.identify(), while server-side usesuser.id.toString()incaptureServerEvent(). PostHog will create separate person profiles for the same user, fragmenting analytics data across client and server events. Fix: useuser.id.toString()consistently everywhere, or pass user ID to client components. [CRITICAL] - Email as distinct_id: Using raw email as the PostHog distinct_id leaks PII into a system identifier field and is explicitly discouraged. The app has numeric user IDs available via
user.id— these should be used instead. [CRITICAL] - Premature identify on login: In
login.tsx,posthog.identify(email)is called in the submit button'sonClickhandler before the form submission completes. If authentication fails, PostHog still links the anonymous session to that email. Identify should be called after successful authentication. [MEDIUM] - useEffect anti-patterns:
general/page.tsxandsecurity/page.tsxuseuseEffectto react tostate.successandisDeletePendingstate changes for capture calls. Per React best practices, analytics should be captured in the event handler that triggers the action, not in a useEffect observing derived state. [MEDIUM] - Duplicate event names:
password_updated,account_updated, andaccount_deletion_requestedare captured with identical names on both client (useEffect) and server (actions.ts), double-counting these user actions. Server events for sign-in/sign-up correctly useserver_prefix but these three events don't. [MEDIUM]
Other completed criteria
- API key loaded from
NEXT_PUBLIC_POSTHOG_PROJECT_TOKENenvironment variable (not hardcoded) - API host correctly configured via environment variable
posthog.reset()correctly called on sign-out before navigation- Server-side client uses
flushAt: 1andflushInterval: 0per Next.js docs ui_hostcorrectly set for reverse proxy configuration
PostHog insights and events ⚠️
| Filename | PostHog events | Description |
|---|---|---|
instrumentation-client.ts |
captureException (autocapture) |
Client-side error tracking via capture_exceptions: true |
app/(login)/login.tsx |
user_signed_in, user_signed_up |
Client-side auth events with source property; also premature identify |
app/(dashboard)/layout.tsx |
user_signed_out |
Sign-out event with posthog.reset(); identify on dashboard load |
app/(dashboard)/dashboard/general/page.tsx |
account_updated |
Client-side account update on success state |
app/(dashboard)/dashboard/security/page.tsx |
password_updated, account_deletion_requested |
Client-side security actions on state changes |
app/(dashboard)/pricing/submit-button.tsx |
pricing_cta_clicked |
Plan selection with plan_name and price_id properties |
app/(login)/actions.ts |
server_user_signed_in, server_user_signed_up, password_updated, account_updated, account_deletion_requested |
Server-side auth and account management events |
lib/payments/actions.ts |
checkout_session_started |
Server-side checkout initiation with team and plan context |
app/api/stripe/checkout/route.ts |
checkout_completed |
Checkout completion with Stripe subscription details |
app/api/stripe/webhook/route.ts |
stripe_subscription_updated |
Webhook-driven subscription lifecycle events |
Issues
- Duplicate client/server events will inflate metrics: Three event names (
password_updated,account_updated,account_deletion_requested) fire on both client and server, making funnel and trend analyses unreliable without filtering by source. Fix: either remove client-side duplicates or use distinct names (e.g.,server_password_updated). [MEDIUM] - Webhook uses Stripe customer ID as distinct_id: In
stripe/webhook/route.ts,String(subscription.customer)is a Stripe customer ID (e.g.,cus_xxx), not a PostHog distinct_id. These events won't link to the user's profile. Fix: look up the user by Stripe customer ID and use their app user ID. [MEDIUM]
Other completed criteria
- Events represent real user actions across the full SaaS lifecycle (auth → pricing → checkout → account management)
- Events enable product insights: sign-up to checkout funnel is possible, retention via auth events
- Events include contextual properties (team_id, plan_name, source, subscription_status)
- No PII in capture() event properties — emails only appear in identify() person properties
- Event names are descriptive, consistent snake_case convention
Reviewed by wizard workbench PR evaluator
Draft
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated wizard CI run
Source: manual
Trigger ID:
gpt54-trial-fillApp:
next-js/15-app-router-saasApp directory:
apps/next-js/15-app-router-saasWorkbench branch:
wizard-ci-gpt54-trial-fill-next-js-15-app-router-saasWizard branch:
543fbd70b7d834c9bb2bf5afe28fc0a5761ced5dContext Mill branch:
mainPostHog (MCP) branch:
masterTimestamp: 2026-07-03T16:29:53.301Z
Duration: 334.2s
YARA Scanner