Skip to content

[CI] (0ae2102) tanstack-router/tanstack-router-file-based-saas#1244

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-0ae2102-tanstack-router-tanstack-router-file-based-saas
Closed

[CI] (0ae2102) tanstack-router/tanstack-router-file-based-saas#1244
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-0ae2102-tanstack-router-tanstack-router-file-based-saas

Conversation

@wizard-ci-bot
Copy link
Copy Markdown

@wizard-ci-bot wizard-ci-bot Bot commented Apr 15, 2026

Automated wizard CI run

Source: wizard-pr
Trigger ID: 0ae2102
App: tanstack-router/tanstack-router-file-based-saas
App directory: apps/tanstack-router/tanstack-router-file-based-saas
Workbench branch: wizard-ci-0ae2102-tanstack-router-tanstack-router-file-based-saas
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-04-15T19:44:50.402Z
Duration: 331.8s

@wizard-ci-bot
Copy link
Copy Markdown
Author

wizard-ci-bot Bot commented Apr 15, 2026

Good — the .env file exists locally but is not in the committed changes list (and .env was added to .gitignore). Now let me verify the identify call — username is used as distinct_id and also as a property.

Now I have everything I need to produce the review.


PR Evaluation Report

Summary

This PR integrates PostHog into a TanStack Router file-based SaaS app ("CloudFlow") using the @posthog/react package with PostHogProvider. It adds event captures for sign-in, sign-out, dashboard views, invoice CRUD, and upgrade clicks. A Vite dev-server proxy is set up for /ingest as a reverse proxy, and user identification is implemented on login with posthog.reset() on logout.

Files changed Lines added Lines removed
10 +108 -13

Confidence score: 4/5 👍

  • username used as distinct_id in identify() — The raw username string is used as the distinct ID. In this demo app the username is arbitrary text typed by the user, which means distinct IDs could be non-unique, collide between users, or contain PII. A real app should use a stable, opaque user ID. [MEDIUM]
  • username passed as event property in user_signed_in captureposthog.capture('user_signed_in', { username }) includes what could be PII (the username) in event properties. Usernames/identifiers belong in person properties via identify(), not in capture() properties. [MEDIUM]
  • dashboard_viewed captured in useEffect instead of event handler — React rules say useEffect is for syncing with external systems, not for responding to user navigation. While PostHog capture could be argued as an external system sync, capturing a page-view event on mount is an acceptable pattern for analytics. However, the empty dependency array [] means posthog is an uncaptured dependency — if the hook returns a different reference, this could fail or stale-close. [LOW]
  • Reverse proxy only works in Vite dev server — The /ingest proxy is configured only in vite.config.js's server.proxy, which only applies during development. In production, requests to /ingest will 404 unless a production reverse proxy is separately configured. The api_host is hardcoded to /ingest, so PostHog will not work in production builds without additional infrastructure. [CRITICAL]

File changes

Filename Score Description
src/routes/__root.tsx 4/5 Wraps root component with PostHogProvider, configures api_host, ui_host, defaults, capture_exceptions, and debug mode
vite.config.js 3/5 Adds Vite dev-server proxy for /ingest — only works in dev mode, not production
src/routes/login.tsx 3/5 Adds identify on login with username as distinct_id, capture on sign-in/sign-out, and reset on logout
src/routes/dashboard.index.tsx 3/5 Adds dashboard_viewed capture in useEffect with invoice_count property
src/routes/dashboard.invoices.index.tsx 5/5 Captures invoice_created in mutation onSuccess callback with invoice_id and title
src/routes/dashboard.invoices..tsx 5/5 Captures invoice_updated in mutation onSuccess callback with invoice_id and title
src/routes/_auth.profile.tsx 5/5 Captures upgrade_clicked in button onClick handler with current_plan property
package.json 5/5 Adds @posthog/react dependency
.gitignore 5/5 Adds .env to gitignore
posthog-setup-report.md 4/5 Wizard setup report documenting all changes

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes Valid syntax, correct imports, @posthog/react added to dependencies
Preserves existing env vars & configs Yes Existing vite config plugins preserved, only proxy added; existing route logic intact
No syntax or type errors Yes All files have valid TypeScript/JSX syntax
Correct imports/exports Yes usePostHog and PostHogProvider correctly imported from @posthog/react
Minimal, focused changes Yes All changes relate to PostHog integration, no unrelated refactors
Pre-existing issues None

Issues

  • No production .env.example: The .env file was created locally but is gitignored and not committed. There is no .env.example or similar file in the PR to document required environment variables for other developers. The report file mentions the env vars but a committed .env.example would be better practice. [LOW]

Other completed criteria

  • All imports resolve correctly (@posthog/react is a valid package)
  • Build configuration remains valid — existing vite plugins preserved
  • Existing app functionality (auth, routing, invoices) is fully preserved
  • .env correctly added to .gitignore

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes @posthog/react ^1.9.0 added to package.json dependencies (includes posthog-js as peer dep)
PostHog client initialized Yes PostHogProvider wraps root component with apiKey from env var, api_host set to /ingest, defaults and capture_exceptions configured
capture() Yes 6 meaningful capture calls across login, dashboard, invoices, and profile routes
identify() Yes posthog.identify(username, { username }) called on login, posthog.reset() on logout
Error tracking Yes capture_exceptions: true set in PostHogProvider options
Reverse proxy No Vite dev-server proxy for /ingest configured, but this only works in development. Production builds will fail to reach PostHog since api_host is /ingest with no production proxy

Issues

  • Reverse proxy is dev-only: The /ingest proxy in vite.config.js only applies during vite dev. In production, the app's api_host: '/ingest' will return 404s. The app needs a production-level reverse proxy (e.g., Vercel rewrites, nginx config, or Cloudflare) or should fall back to the PostHog host directly. [CRITICAL]
  • username as distinct_id: posthog.identify(username, { username }) uses the raw typed username as the distinct ID. This could cause identity collisions if two users type the same username, and the username itself could be PII. A stable, opaque user ID is recommended. [MEDIUM]
  • ui_host fallback uses wrong domain: The fallback 'https://us.posthog.com' should be 'https://us.i.posthog.com' to match the PostHog ingestion host pattern, though ui_host is only used for toolbar/survey rendering, not ingestion. [LOW]

Other completed criteria

  • API key correctly loaded from VITE_PUBLIC_POSTHOG_PROJECT_TOKEN environment variable
  • PostHog host correctly configured via VITE_PUBLIC_POSTHOG_HOST environment variable
  • posthog.reset() correctly called on sign-out before auth.logout()
  • capture_exceptions: true enables automatic error tracking
  • defaults: '2026-01-30' set per documentation

PostHog insights and events ⚠️

Filename PostHog events Description
src/routes/login.tsx user_signed_in, user_signed_out Tracks authentication flow; identify on login, reset on logout
src/routes/dashboard.index.tsx dashboard_viewed Captures dashboard page view with invoice_count property
src/routes/dashboard.invoices.index.tsx invoice_created Tracks invoice creation in mutation onSuccess with invoice_id and title
src/routes/dashboard.invoices..tsx invoice_updated Tracks invoice updates in mutation onSuccess with invoice_id and title
src/routes/_auth.profile.tsx upgrade_clicked Tracks upgrade button clicks with current_plan property
src/routes/__root.tsx captureException (via config) Automatic exception capture enabled via capture_exceptions: true

Issues

  • PII in user_signed_in event properties: posthog.capture('user_signed_in', { username }) sends the username as an event property. The username should only be in person properties (already set via identify()), not in capture() event properties. [MEDIUM]

Other completed criteria

  • Events represent real user actions (sign-in, sign-out, view dashboard, create/update invoices, upgrade click)
  • Events enable meaningful product insights — can build login→dashboard→upgrade funnel, invoice creation trends
  • Most events include relevant contextual properties (invoice_id, title, invoice_count, current_plan)
  • Event names are descriptive, 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