Skip to content

[CI] (582c032) react-router/saas-template#751

Closed
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-582c032-react-router-saas-template
Closed

[CI] (582c032) react-router/saas-template#751
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-582c032-react-router-saas-template

Conversation

@wizard-ci-bot
Copy link
Copy Markdown

@wizard-ci-bot wizard-ci-bot bot commented Mar 12, 2026

Automated wizard CI run

Source: wizard-pr
Trigger ID: 582c032
App: react-router/saas-template
App directory: apps/react-router/saas-template
Workbench branch: wizard-ci-582c032-react-router-saas-template
Wizard branch: agent-jail
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-03-12T22:34:06.255Z
Duration: 823.1s

@wizard-ci-bot
Copy link
Copy Markdown
Author

wizard-ci-bot bot commented Mar 12, 2026

Now I have read all the changed files. Let me provide the comprehensive PR evaluation.


PR Evaluation Report

Summary

This PR integrates PostHog analytics into a React Router v7 SaaS template, implementing both client-side and server-side event tracking. The integration includes SDK initialization, middleware for session stitching, error tracking, and 12 business events covering authentication, billing, onboarding, and organization management flows.

Files changed Lines added Lines removed
16 +253 -9

Confidence score: 4/5 👍

  • Redundant .env entry in .gitignore: The .gitignore already has *.env on line 9, making the added .env on line 31 redundant. [LOW]
  • Stripe webhook handler creates separate PostHog client: The stripe-event-handlers.server.ts creates its own PostHog instance instead of using the middleware context, which is unavoidable for webhook handlers but creates inconsistency. [LOW]
  • No reverse proxy configured: Events sent directly to PostHog host may be blocked by ad blockers. Consider adding a reverse proxy configuration. [MEDIUM]

File changes

Filename Score Description
app/entry.client.tsx 5/5 Properly initializes PostHog client-side SDK with environment variables, tracing headers for session stitching, and wraps app with PostHogProvider
app/root.tsx 5/5 Adds posthogMiddleware to middleware chain and implements error tracking via captureException in ErrorBoundary
app/utils/posthog-middleware.server.ts 5/5 Well-structured middleware that creates PostHog client per-request, extracts session/distinct IDs from headers, uses withContext for session stitching, and properly shuts down
app/utils/env.server.ts 5/5 Correctly adds optional PostHog environment variables to the schema
package.json 5/5 Adds posthog-js, posthog-node, and @posthog/react dependencies with appropriate versions
vite.config.ts 5/5 Correctly configures ssr.noExternal for PostHog packages to handle SSR compatibility
app/features/billing/billing-action.server.ts 5/5 Adds 4 billing events with relevant properties (subscription_cancelled, subscription_checkout_started, subscription_resumed, subscription_switched)
app/features/billing/contact-sales/contact-sales-action.server.ts 5/5 Captures contact_sales_submitted event with company_name and email properties
app/features/billing/stripe-event-handlers.server.ts 4/5 Captures stripe_checkout_completed from webhook, but creates separate PostHog instance (necessary for webhooks but less ideal)
app/features/onboarding/user-account/onboarding-user-account-action.server.ts 5/5 Captures onboarding_user_account_completed with name property
app/features/organizations/accept-email-invite/accept-email-invite-action.server.ts 5/5 Captures email_invite_accepted with organization details and role
app/features/organizations/create-organization/create-organization-action.server.ts 5/5 Captures organization_created with organization name and slug
app/features/organizations/layout/nav-user.tsx 5/5 Client-side user_logged_out event with proper posthog.reset() to clear identity
app/routes/_user-authentication+/_anonymous-routes+/auth.callback.ts 5/5 Captures user_logged_in and user_signed_up events at authentication callback
.gitignore 4/5 Adds .env but this is redundant since *.env already exists on line 9
posthog-setup-report.md 5/5 Comprehensive documentation of events and setup

App sanity check: 5/5 ✅

Criteria Result Description
App builds and runs Yes All imports are valid, types are correct, and code integrates properly with existing React Router patterns
Preserves existing env vars & configs Yes Adds new PostHog env vars without modifying existing ones; all existing configurations remain intact
No syntax or type errors Yes TypeScript types are properly used; PostHog SDK patterns are correct
Correct imports/exports Yes All imports from posthog-js, posthog-node, and @posthog/react are correct
Minimal, focused changes Yes Changes are limited to PostHog integration; no unnecessary modifications to existing logic

Issues

  • Redundant .gitignore entry: .env is added on line 31 but *.env already exists on line 9, making it redundant. [LOW]

Other completed criteria

  • Existing app code logic preserved (authentication, billing, organizations flows)
  • Consistent with existing patterns (middleware pattern, context usage)
  • Appropriate error handling (optional chaining posthog?.capture(), catch blocks on shutdown)
  • Environment variables properly documented in env.server.ts schema
  • Build configuration valid with SSR noExternal settings

PostHog implementation: 4/5 ✅

Criteria Result Description
PostHog SDKs installed Yes posthog-js ^1.360.1, posthog-node ^5.28.1, and @posthog/react ^1.8.2 added to dependencies
PostHog client initialized Yes Client-side: posthog.init() in entry.client.tsx with PostHogProvider. Server-side: middleware creates PostHog instance per-request with proper shutdown
capture() Yes 12 business events captured across authentication, billing, onboarding, and organizations
identify() No No explicit posthog.identify() calls; relies on distinctId in capture calls using user email
Error tracking Yes posthog.captureException(error) in ErrorBoundary component
Reverse proxy No No reverse proxy configuration; events sent directly to PostHog host

Issues

  • No reverse proxy: Events are sent directly to PostHog host which may be blocked by ad blockers. Consider configuring a reverse proxy through /api/posthog or similar to circumvent ad blocking. [MEDIUM]
  • No explicit identify() call: While distinctId is used in server-side captures, there's no posthog.identify() call on the client after user login to link client-side events with the user. Consider adding identify in auth callback or user context loading. [MEDIUM]

Other completed criteria

  • API key from environment variable (not hardcoded)
  • Correct API host configuration via environment variable
  • Session stitching via __add_tracing_headers and request header extraction
  • Server-side context with withContext() for proper session/distinctId handling
  • Proper cleanup with posthog.shutdown() on server
  • Client-side cleanup with posthog.reset() on logout
  • No PII concerns - only email used as distinctId which is standard practice
  • SSR compatibility handled via vite.config.ts noExternal setting

PostHog insights and events: 5/5 ✅

Filename PostHog events Description
auth.callback.ts user_logged_in, user_signed_up Core acquisition metrics for tracking signups vs returning users
nav-user.tsx user_logged_out Client-side logout tracking with session reset
onboarding-user-account-action.server.ts onboarding_user_account_completed Onboarding funnel completion tracking
create-organization-action.server.ts organization_created Tracks organization creation with name and slug
accept-email-invite-action.server.ts email_invite_accepted Team collaboration metric with role tracking
billing-action.server.ts subscription_cancelled, subscription_checkout_started, subscription_resumed, subscription_switched Full billing lifecycle coverage for revenue and churn analysis
contact-sales-action.server.ts contact_sales_submitted Enterprise lead tracking
stripe-event-handlers.server.ts stripe_checkout_completed Authoritative payment confirmation from webhook
root.tsx captureException Error tracking for monitoring app stability

Issues

None - the event coverage is comprehensive for a SaaS application.

Other completed criteria

  • Events cover full user lifecycle: signup → onboarding → organization → subscription → churn
  • Events have meaningful properties (organization_slug, role, price_id, amount_total)
  • Supports building key SaaS insights: conversion funnels, churn signals, team collaboration activity
  • Error tracking provides stability monitoring
  • No redundant or noisy events

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