Skip to content

[CI] (cef44b4) tanstack-router/tanstack-router-file-based-saas#1413

Closed
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-cef44b4-tanstack-router-tanstack-router-file-based-saas
Closed

[CI] (cef44b4) tanstack-router/tanstack-router-file-based-saas#1413
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-cef44b4-tanstack-router-tanstack-router-file-based-saas

Conversation

@wizard-ci-bot
Copy link
Copy Markdown

@wizard-ci-bot wizard-ci-bot Bot commented May 1, 2026

Automated wizard CI run

Source: context-mill-pr
Trigger ID: cef44b4
App: tanstack-router/tanstack-router-file-based-saas
App directory: apps/tanstack-router/tanstack-router-file-based-saas
Workbench branch: wizard-ci-cef44b4-tanstack-router-tanstack-router-file-based-saas
Wizard branch: main
Context Mill branch: basic-skills-v2
PostHog (MCP) branch: master
Timestamp: 2026-05-01T21:19:38.889Z
Duration: 309.1s

@wizard-ci-bot
Copy link
Copy Markdown
Author

wizard-ci-bot Bot commented May 1, 2026

Now I have enough context to produce the evaluation.


PR Evaluation Report

Summary

This PR integrates PostHog into a TanStack Router file-based SaaS demo app. It adds posthog-js and @posthog/react as dependencies, wraps the app in PostHogProvider, sets up user identification on login/logout, captures meaningful business events (invoice CRUD, upgrade clicks), configures a Vite dev-server reverse proxy, and enables exception autocapture.

Files changed Lines added Lines removed
9 +107 -12

Confidence score: 4/5 👍

  • identify() uses raw username as distinct_id: The app calls posthog.identify(username, { username }) with a plain username string. In a demo app this is acceptable, but in production this risks collisions and fragmented data if usernames aren't globally unique IDs. Using a database user ID would be more robust. [MEDIUM]
  • username leaked into capture() event properties: user_signed_in includes { username } as an event property. Per PostHog best practices, PII-adjacent data like usernames should be set via person properties in identify(), not in capture() event properties. [MEDIUM]
  • No .env.example file: The .env file is gitignored (good), but no .env.example or equivalent documents the required VITE_PUBLIC_POSTHOG_PROJECT_TOKEN and VITE_PUBLIC_POSTHOG_HOST variables for other developers. [MEDIUM]
  • Reverse proxy is dev-server only: The Vite server.proxy config only applies during vite dev. In production builds, /ingest requests would not be proxied. This needs a production proxy (e.g., Vercel rewrites, nginx, Cloudflare) for ad-blocker resilience in deployed environments. [LOW]

File changes

Filename Score Description
package.json 5/5 Adds posthog-js and @posthog/react with appropriate versions
vite.config.js 4/5 Adds reverse proxy for /ingest, /ingest/static, /ingest/array — correct routing but dev-server only
src/routes/__root.tsx 5/5 Wraps app in PostHogProvider with env-based API key, reverse proxy host, exception capture, and debug mode
src/routes/login.tsx 3/5 Implements identify/reset flow but uses username as distinct_id and leaks username into capture properties
src/routes/dashboard.invoices..tsx 5/5 Captures invoice_updated with relevant properties in onSuccess callback
src/routes/dashboard.invoices.index.tsx 5/5 Captures invoice_created with relevant properties in onSuccess callback
src/routes/_auth.profile.tsx 5/5 Captures upgrade_plan_clicked with plan context in click handler
.gitignore 5/5 Adds .env to gitignore
posthog-setup-report.md 4/5 Helpful setup report, though arguably unnecessary file for the integration itself

App sanity check ✅

Criteria Result Description
App builds and runs Yes All imports resolve, syntax is valid, no type errors introduced
Preserves existing env vars & configs Yes Existing plugins and config preserved; vite config refactored to factory form but functionally equivalent
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; posthog-js used indirectly via provider
Minimal, focused changes Yes All changes relate to PostHog integration, no scope creep
Pre-existing issues None

Issues

  • No .env.example for environment variables: The PR adds .env to .gitignore (good) and creates a .env file with the token, but there's no .env.example committed to document the required variables (VITE_PUBLIC_POSTHOG_PROJECT_TOKEN, VITE_PUBLIC_POSTHOG_HOST). [MEDIUM]

Other completed criteria

  • All changes are relevant to PostHog integration
  • Correct files modified for a React/TanStack Router app (root layout, route files, vite config, package.json)
  • Code follows existing codebase patterns (hooks at top of component, event handlers in callbacks)
  • Build configuration remains valid with the factory-form defineConfig

PostHog implementation ✅

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.372.6 and @posthog/react@^1.9.0 added to dependencies
PostHog client initialized Yes PostHogProvider with apiKey from env var, api_host: '/ingest', defaults: '2026-01-30', capture_exceptions: true
capture() Yes 5 meaningful capture calls across 4 files
identify() Yes posthog.identify(username) on login, posthog.reset() on logout — correct flow but uses username as distinct_id
Error tracking Yes capture_exceptions: true in init options enables exception autocapture
Reverse proxy Yes Vite dev proxy routes /ingestus.i.posthog.com, /ingest/static and /ingest/arrayus-assets.i.posthog.com

Issues

  • Username as distinct_id: posthog.identify(username, { username }) uses a plain username string rather than a unique database ID. This could cause data merging issues if usernames collide or change. In a demo app this is understandable, but it's not a production-ready pattern. [MEDIUM]
  • PII in capture event properties: posthog.capture('user_signed_in', { username }) sends username as an event property. Per PostHog best practices, PII should only be in person properties (via identify()), not in capture() event properties. [MEDIUM]
  • Reverse proxy is dev-only: The Vite server.proxy configuration only works during development. Production deployments would need a separate proxy configuration. [LOW]

Other completed criteria

  • API key loaded from import.meta.env.VITE_PUBLIC_POSTHOG_PROJECT_TOKEN environment variable, not hardcoded
  • Host correctly configured via env var with reverse proxy pointing to correct PostHog origins
  • ui_host set separately from api_host — correct pattern when using a reverse proxy
  • posthog.reset() called on logout before auth.logout() — correct ordering

PostHog insights and events ✅

Filename PostHog events Description
src/routes/login.tsx user_signed_in, user_signed_out Tracks sign-in (with identify) and sign-out (with reset) — enables session and retention analysis
src/routes/dashboard.invoices.index.tsx invoice_created Tracks successful invoice creation with invoice_id and title — enables activation/usage funnels
src/routes/dashboard.invoices..tsx invoice_updated Tracks invoice updates with invoice_id and title — enables engagement tracking
src/routes/_auth.profile.tsx upgrade_plan_clicked Tracks upgrade intent with current_plan — enables conversion funnel analysis
src/routes/__root.tsx captureException (via capture_exceptions: true) Automatic exception capture for error tracking

Issues

  • username as event property in user_signed_in: The username property in capture('user_signed_in', { username }) is PII that belongs in person properties, not event properties. Remove it from the capture call since it's already set via identify(). [MEDIUM]

Other completed criteria

  • Events represent real user actions (sign-in, sign-out, create invoice, update invoice, upgrade click)
  • Events enable product insights: sign-in → invoice_created funnel, upgrade conversion tracking, retention via sign-out
  • Events include relevant contextual properties (invoice_id, title, current_plan)
  • Event names are descriptive and use 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