[CI] (b3fa00a) next-js/15-pages-router-saas#984
Closed
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
Closed
[CI] (b3fa00a) next-js/15-pages-router-saas#984wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
Conversation
Author
|
Now I have all the context I need. Let me compile my evaluation. Key findings:
PR Evaluation ReportSummaryThis PR integrates PostHog into a Next.js 15 Pages Router SaaS application with both client-side (
Confidence score: 4/5 👍
File changes
App sanity check
|
| Criteria | Result | Description |
|---|---|---|
| App builds and runs | Yes | No syntax errors, valid TypeScript, all imports resolve |
| Preserves existing env vars & configs | Yes | Only adds to next.config.ts; existing configs untouched |
| No syntax or type errors | Yes | All changes are syntactically valid TypeScript |
| Correct imports/exports | Yes | posthog-js imported on client, posthog-node on server, all from correct packages |
| Minimal, focused changes | Yes | All changes relate to PostHog integration |
| Pre-existing issues | None | Base app appears functional |
Issues
- PostHog env vars not in .env.example:
NEXT_PUBLIC_POSTHOG_PROJECT_TOKENandNEXT_PUBLIC_POSTHOG_HOSTare not documented in.env.example. A.env.localfile was created but gitignored. New developers won't know which env vars to set. [MEDIUM]
Other completed criteria
- Build configuration is valid — package.json dependencies added correctly
- No unnecessary changes — all modifications relate to PostHog
- Code follows existing codebase patterns and conventions
PostHog implementation ⚠️
| Criteria | Result | Description |
|---|---|---|
| PostHog SDKs installed | Yes | posthog-js@^1.363.4 and posthog-node@^5.28.5 added to package.json |
| PostHog client initialized | Yes | Client via instrumentation-client.ts (correct for Next.js 15.3+); server via singleton getPostHogClient() with flushAt: 1, flushInterval: 0 |
| capture() | Yes | 10 meaningful events captured across client and server |
| identify() | No | Client uses data.email as distinct_id while server uses String(user.id) — creates split identities. Should consistently use user DB ID. |
| Error tracking | Yes | capture_exceptions: true in init config; posthog.captureException(err) in catch blocks |
| Reverse proxy | Yes | Next.js rewrites configured in next.config.ts routing /ingest/* to PostHog; api_host: '/ingest' in client init |
Issues
- Distinct ID mismatch (client vs server):
posthog.identify(data.email, ...)on the client uses email as the distinct ID, but server-side handlers useString(foundUser.id)/String(createdUser.id). This creates two separate person profiles per user. The client should use the user's DB ID (returned in the API response) as the distinct ID. [CRITICAL] - Stripe webhook distinct_id:
subscription_updatedevent inwebhook.tsusessubscription.customer(Stripe'scus_xxxID) as the distinct ID. This doesn't match the user's DB ID used elsewhere, creating a third orphaned identity. The handler should resolve the Stripe customer to the internal user ID. [CRITICAL] - Server-side host configuration:
posthog-server.tsusesprocess.env.NEXT_PUBLIC_POSTHOG_HOSTfor the server host, butinstrumentation-client.tsusesprocess.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN. These are consistent env var names but the serverhostenv var may be undefined if not set (the reverse proxy/ingestis only for client-side). The server should point directly tohttps://us.i.posthog.com. This works if the env var is set correctly, but there's a risk of misconfiguration. [LOW]
Other completed criteria
- API key loaded from environment variable (
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN) - Host correctly configured via reverse proxy (
/ingest) on client; env var on server posthog.reset()called on sign-out- Client-to-server identity linking attempted via
X-POSTHOG-DISTINCT-IDheader and `` capture_exceptions: trueenabled in init for automatic exception capture
PostHog insights and events ⚠️
| Filename | PostHog events | Description |
|---|---|---|
components/login.tsx |
user_signed_in, user_signed_up, captureException |
Client-side auth events and error tracking on login/signup |
components/header.tsx |
user_signed_out |
Captures sign-out with posthog.reset() to unlink identity |
pages/api/auth/sign-in.ts |
user_signed_in |
Server-side sign-in with identify and anon ID linking |
pages/api/auth/sign-up.ts |
user_signed_up, invitation_accepted |
Server-side signup with conditional invitation tracking |
pages/api/stripe/create-checkout.ts |
checkout_session_created |
Server-side Stripe checkout initiation |
pages/api/stripe/webhook.ts |
subscription_updated |
Subscription lifecycle tracking from Stripe webhooks |
pages/api/team/invite.ts |
team_member_invited |
Team invitation tracking |
pages/api/team/remove-member.ts |
team_member_removed |
Team member removal tracking |
pages/dashboard/general.tsx |
account_updated, captureException |
Account settings update with error tracking |
pages/pricing.tsx |
checkout_started |
Client-side checkout funnel entry point |
Issues
- PII in event properties:
emailis included as an event property inuser_signed_in,user_signed_up,invitation_accepted, andaccount_updatedcapture calls. Email should only be in person properties viaidentify()or ``. Theinvited_emailin `team_member_invited` is also PII. [MEDIUM] - Duplicate events on client and server:
user_signed_inanduser_signed_upare captured on both client-side (login.tsx) and server-side (sign-in.ts,sign-up.ts). This creates double-counted events. Pick one side (server is more reliable). [MEDIUM]
Other completed criteria
- Events represent real user actions (signup, signin, checkout, team management)
- Events enable product insights — full signup-to-checkout funnel is trackable
- Events include relevant properties (team_id, price_id, role, status, etc.)
- Event names are descriptive and consistently use snake_case
Reviewed by wizard workbench PR evaluator
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:
b3fa00aApp:
next-js/15-pages-router-saasApp directory:
apps/next-js/15-pages-router-saasWorkbench branch:
wizard-ci-b3fa00a-next-js-15-pages-router-saasWizard branch:
mainContext Mill branch:
mainPostHog (MCP) branch:
masterTimestamp: 2026-03-24T16:53:35.021Z
Duration: 402.4s