Skip to content

[CI] (275b928) next-js/15-app-router-saas - #3127

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-275b928-next-js-15-app-router-saas
Closed

[CI] (275b928) next-js/15-app-router-saas#3127
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-275b928-next-js-15-app-router-saas

Conversation

@wizard-ci-bot

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

Copy link
Copy Markdown

Automated wizard CI run

Source: wizard-pr
Trigger ID: 275b928
App: next-js/15-app-router-saas
App directory: apps/next-js/15-app-router-saas
Workbench branch: wizard-ci-275b928-next-js-15-app-router-saas
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-27T19:14:16.130Z
Duration: 400.0s

YARA Scanner

✓ 150 tool calls scanned, 0 violations detected

No violations: ✓ 150 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown
Author

PR Evaluation Report

Summary

This PR integrates PostHog into a Next.js 15 App Router SaaS application with both client-side (posthog-js) and server-side (posthog-node) SDKs. Client initialization uses instrumentation-client.ts, user identification is wired in the dashboard layout, and ten meaningful server-side events are captured across auth, team management, and Stripe checkout flows.

Files changed Lines added Lines removed
9 +245 -23

Confidence score: 5/5 🧙

  • No reverse proxy configured: The client-side posthog-js SDK sends events directly to us.i.posthog.com. Next.js rewrites or Vercel rewrites should be configured to prevent ad-blocker interception. [MEDIUM]
  • Missing defaults config option: The posthog.init() call in instrumentation-client.ts omits the recommended defaults: '2026-05-30' configuration snapshot, which opts the SDK into the latest recommended defaults. [LOW]

File changes

Filename Score Description
instrumentation-client.ts 4/5 New file: client-side PostHog init with env var guard, exception capture, debug mode. Missing defaults option.
lib/posthog-server.ts 5/5 New file: server-side singleton PostHog client with server-only guard, immediate flushing, graceful no-op when unconfigured.
app/(dashboard)/layout.tsx 5/5 Adds posthog.identify() with stable user ID and person properties; posthog.reset() on sign-out.
app/(login)/actions.ts 5/5 Adds server-side captures for 8 user actions (sign in/up/out, account/password update, delete, team invite/remove).
app/api/stripe/checkout/route.ts 5/5 Captures subscription_checkout_completed with subscription status and plan name.
lib/payments/stripe.ts 5/5 Captures checkout_started with existing subscription context.
package.json 5/5 Adds posthog-js and posthog-node dependencies.
.env.example 5/5 Documents both PostHog env vars.
posthog-setup-report.md N/A Wizard-generated setup report documenting the integration.

App sanity check ✅

Criteria Result Description
App builds and runs Yes Build fails only due to pre-existing missing POSTGRES_URL, unrelated to PostHog changes.
Preserves existing env vars & configs Yes All existing code/configs preserved; PostHog calls added alongside existing logActivity calls using Promise.all.
No syntax or type errors Yes All new code is syntactically correct TypeScript.
Correct imports/exports Yes posthog-js on client only, posthog-node on server with 'server-only' guard, correct package names throughout.
Minimal, focused changes Yes All changes relate to PostHog integration; no unrelated refactors.
Pre-existing issues Build fails at page-data collection for /api/stripe/webhook due to missing POSTGRES_URL env var — not introduced by this PR.

Issues

No issues introduced by this PR.

Other completed criteria

  • Environment variables documented in .env.example
  • package.json dependencies correctly added
  • import 'server-only' prevents accidental client-side import of server module
  • Server client gracefully degrades to no-op when env vars are missing in production

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.407.3 and posthog-node@^5.46.1 added to package.json.
PostHog client initialized Yes Client initialized in instrumentation-client.ts (correct Next.js pattern). Server singleton in lib/posthog-server.ts with flushAt: 1, flushInterval: 0.
capture() Yes 10 meaningful server-side events + autocapture on client.
identify() Yes posthog.identify(user.id.toString(), { email, name, role }) on authenticated dashboard load; posthog.reset() on sign-out. Stable numeric user ID used as distinct_id.
Error tracking Yes capture_exceptions: true in client init enables global browser exception autocapture.
Reverse proxy No No reverse proxy configured. Next.js rewrites or managed proxy recommended for client-side event delivery reliability.

Issues

  • No reverse proxy: Client-side events go directly to us.i.posthog.com, making them susceptible to ad-blocker interception. Configure Next.js rewrites or PostHog's managed reverse proxy. [MEDIUM]
  • Missing defaults option: posthog.init() omits the defaults: '2026-05-30' configuration snapshot recommended in the Next.js docs. [LOW]

Other completed criteria

  • API key loaded from NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN environment variable, not hardcoded
  • API host loaded from NEXT_PUBLIC_POSTHOG_HOST environment variable
  • Server client uses singleton pattern with lazy initialization and server-only guard
  • Server client calls flush() after each capture for immediate delivery in short-lived Next.js functions
  • Development-mode error thrown when env vars missing, graceful no-op in production

PostHog insights and events ✅

Filename PostHog events Description
instrumentation-client.ts captureException (auto) Browser exception autocapture via capture_exceptions: true
app/(dashboard)/layout.tsx identify, reset User identification on dashboard load, reset on sign-out
app/(login)/actions.ts user_signed_in, user_signed_up, user_signed_out, password_updated, account_updated, account_deleted, team_member_invited, team_member_removed Full auth and team lifecycle events with relevant properties
lib/payments/stripe.ts checkout_started Checkout initiation with has_existing_subscription property
app/api/stripe/checkout/route.ts subscription_checkout_completed Successful checkout with subscription_status and plan_name

Issues

No issues with event quality.

Other completed criteria

  • Events represent real user actions across the full SaaS lifecycle (auth → team management → billing)
  • Events enable product insights: signup→signin funnel, checkout conversion funnel, team growth tracking
  • Events include contextual properties: signup_method, invited_role, subscription_status, plan_name, has_existing_subscription
  • No PII in event properties — email/name/role set via identify() person properties only
  • Consistent snake_case naming convention across all event names

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