Skip to content

[CI] (cef44b4) react-router/shopper#1407

Closed
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-cef44b4-react-router-shopper
Closed

[CI] (cef44b4) react-router/shopper#1407
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-cef44b4-react-router-shopper

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: react-router/shopper
App directory: apps/react-router/shopper
Workbench branch: wizard-ci-cef44b4-react-router-shopper
Wizard branch: main
Context Mill branch: basic-skills-v2
PostHog (MCP) branch: master
Timestamp: 2026-05-01T21:11:33.659Z
Duration: 396.9s

@wizard-ci-bot
Copy link
Copy Markdown
Author

wizard-ci-bot Bot commented May 1, 2026


PR Evaluation Report

Summary

This PR integrates PostHog into a React Router v7 framework mode e-commerce app ("Shopper"). It adds client-side initialization via entry.client.tsx with PostHogProvider, server-side middleware with posthog-node, error tracking in the ErrorBoundary, and comprehensive event capture across the shopping funnel (product browsing, cart management, checkout). A Vite dev proxy for /ingest is configured but not actually used by PostHog.

Files changed Lines added Lines removed
11 +222 -3

Confidence score: 4/5 👍

  • No identify() call anywhere: The checkout form collects user name and email, but posthog.identify() is never called. All events remain anonymous, preventing user-level analysis across sessions. [CRITICAL]
  • Reverse proxy configured but not connected: The Vite dev proxy routes /ingest correctly, but posthog.init() sets api_host to the direct PostHog host (VITE_PUBLIC_POSTHOG_HOST), so the proxy is never used. [MEDIUM]
  • product_searched fires on every keystroke: handleSearch is called from onChange, meaning typing "shoes" fires 5 separate events. Should be debounced or fire on blur/submit. [MEDIUM]
  • No .env.example created: Environment variables VITE_PUBLIC_POSTHOG_TOKEN and VITE_PUBLIC_POSTHOG_HOST are used but not documented in any committed file. [MEDIUM]

File changes

Filename Score Description
app/entry.client.tsx 4/5 Correct client-side init with PostHogProvider, tracing headers, and defaults. api_host doesn't use the /ingest proxy.
app/lib/posthog-middleware.ts 5/5 Textbook server-side middleware with withContext(), session/distinct ID extraction, and proper shutdown.
app/root.tsx 4/5 Middleware registered correctly. captureException in ErrorBoundary is good, though calling it during render is a minor React anti-pattern.
app/routes/cart.tsx 5/5 Well-structured remove_from_cart and cart_quantity_updated events in event handlers.
app/routes/checkout.tsx 4/5 Good checkout_started and order_placed funnel events. Missing identify() call despite having user email.
app/routes/products..tsx 5/5 Clean add_to_cart event with source differentiation.
app/routes/products.tsx 3/5 product_searched fires on every keystroke — noisy and expensive.
package.json 5/5 Correct dependencies: posthog-js, @posthog/react, posthog-node.
vite.config.ts 3/5 Dev proxy routes are correctly configured, but disconnected from PostHog init. ssr.noExternal is correct.
react-router.config.ts 5/5 Correctly enables future.v8_middleware.
posthog-setup-report.md 4/5 Comprehensive report with event table and dashboard suggestions.

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes All syntax is valid, dependencies added, vite/react-router configs correct
Preserves existing env vars & configs Yes Only PostHog additions; existing code untouched
No syntax or type errors Yes TypeScript types are correct, optional chaining used appropriately
Correct imports/exports Yes All imports resolve: posthog-js, @posthog/react, posthog-node, react-router
Minimal, focused changes Yes All changes are PostHog-related
Pre-existing issues None

Issues

  • No .env.example file: The PR uses VITE_PUBLIC_POSTHOG_TOKEN and VITE_PUBLIC_POSTHOG_HOST but no .env.example is committed to document these required variables for other developers. [MEDIUM]

Other completed criteria

  • Build configuration is valid — ssr.noExternal and future.v8_middleware correctly configured
  • Package.json dependencies added with appropriate version ranges

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.372.6, @posthog/react@^1.9.0, posthog-node@^5.32.1 in package.json
PostHog client initialized Yes posthog.init() in entry.client.tsx with env vars, defaults, and tracing headers. Server middleware creates per-request PostHog client with flushAt: 1.
capture() Yes 8 distinct capture calls across 4 route files covering the full shopping funnel
identify() No No posthog.identify() call anywhere. The checkout form collects fullName and email but never identifies the user.
Error tracking Yes posthog.captureException(error) in ErrorBoundary in root.tsx
Reverse proxy No Vite dev proxy at /ingest is correctly structured but api_host points directly to https://us.i.posthog.com, so the proxy is never used

Issues

  • Missing identify() call: The checkout form collects user name and email, which should trigger posthog.identify(userId, { email, name }). Without this, all events are anonymous and cannot be linked across sessions. Even without a formal auth system, the checkout email could serve as a distinct ID. Also missing posthog.reset() for any logout-equivalent flow. [CRITICAL]
  • Reverse proxy not connected: posthog.init() should set api_host to "/ingest" (or equivalent) to route through the Vite proxy. Currently, the proxy configuration is dead code. Production reverse proxy is also not addressed. [MEDIUM]

Other completed criteria

  • API key loaded from import.meta.env.VITE_PUBLIC_POSTHOG_TOKEN (not hardcoded)
  • Host correctly configured to https://us.i.posthog.com
  • Server-side PostHog uses withContext() for session correlation
  • __add_tracing_headers correctly configured for client-server linking

PostHog insights and events ⚠️

Filename PostHog events Description
app/routes/products.tsx add_to_cart, product_searched, products_filtered_by_category Product browsing funnel: cart adds from listing, search tracking, category filtering
app/routes/products..tsx add_to_cart Cart add from product detail page, differentiated by source: "product_detail"
app/routes/cart.tsx remove_from_cart, cart_quantity_updated Cart management events with product details and quantity changes
app/routes/checkout.tsx checkout_started, order_placed Checkout conversion funnel with cart totals, item counts, and item details
app/root.tsx captureException Unhandled route errors captured via ErrorBoundary

Issues

  • product_searched fires on every keystroke: The handleSearch function is called from onChange on the search input, meaning each character typed triggers a separate event. This will create excessive noise and cost. Should be debounced (e.g., 300ms) or fire on form submit / blur. [MEDIUM]
  • order_placed includes city: The order_placed event includes city: formData.city as an event property. While a city name alone is borderline, location data is better suited as a person property via ``. [LOW]

Other completed criteria

  • Events represent real user actions mapping to an e-commerce funnel (browse → add to cart → checkout → purchase)
  • Events enable product insights: full conversion funnel, cart abandonment signals, search behavior
  • Events include rich properties: product IDs, names, categories, prices, quantities, cart totals
  • No clear PII in event properties (no emails, names, or phone numbers in capture calls)
  • Event names are descriptive and use consistent snake_case convention
  • add_to_cart events differentiate via source property (listing vs detail page)

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