Skip to content

Conversation

@wizard-ci-bot
Copy link

@wizard-ci-bot wizard-ci-bot bot commented Jan 21, 2026

Automated wizard CI run

Source: manual
Trigger ID: 3864784
App: next-js/15-app-router-todo
App directory: apps/next-js/15-app-router-todo
Workbench branch: wizard-ci-3864784-next-js-15-app-router-todo
Wizard branch: main
Examples branch: main
PostHog (MCP) branch: master
Timestamp: 2026-01-21T22:24:45.649Z
Duration: 321.6s

@wizard-ci-bot
Copy link
Author

wizard-ci-bot bot commented Jan 21, 2026

Now I have all the information needed to provide the evaluation. Let me compile the review:


PR Evaluation Report

Summary

This PR integrates PostHog analytics into a Next.js 15 App Router todo application. It adds both client-side (posthog-js) and server-side (posthog-node) tracking, configures a reverse proxy for ad-blocker circumvention, and captures events for todo CRUD operations and navigation clicks.

Files changed Lines added Lines removed
12 +507 -8

Confidence score: 3/5 🤔

  • Metadata removal from About page: The page was converted to a client component ('use client') and the metadata export was removed. The comment says "Metadata moved to layout.tsx or use generateMetadata()" but no layout.tsx exists for /about and the metadata was NOT moved anywhere. This loses SEO metadata for the About page. [MEDIUM]
  • Missing x-posthog-distinct-id header on client requests: Server-side events use request.headers.get('x-posthog-distinct-id') but the client never sends this header, so all server events will have distinctId: 'anonymous'. This breaks user identity linkage between client and server events. [CRITICAL]
  • No identify() call: PostHog is initialized but users are never identified. All users remain anonymous, limiting analytics value. [MEDIUM]
  • Hardcoded API key in .env: While the .env file exists, it contains an actual API key (phc_sBGF...). The PR notes say .env is not committed but the presence of a real key in a file suggests potential security risk if .gitignore is misconfigured. [LOW]

File changes

Filename Score Description
app/about/page.tsx 3/5 Added 'use client' and PostHog click tracking, but removed metadata without moving it elsewhere
app/api/todos/[id]/route.ts 4/5 Added server-side event tracking for todo completion toggle and deletion
app/api/todos/route.ts 4/5 Added server-side event tracking for todo creation
components/todos/todo-form.tsx 5/5 Clean client-side event tracking for add button clicks with property enrichment
components/todos/todo-item.tsx 5/5 Well-structured handlers for toggle and delete events with relevant properties
components/todos/todo-list.tsx 5/5 Added navigation tracking for About link click
instrumentation-client.ts 4/5 Correct Next.js 15.3+ initialization pattern with exception capture enabled
lib/posthog-server.ts 4/5 Singleton pattern for server-side client, includes shutdown function
next.config.ts 5/5 Proper reverse proxy configuration with trailing slash support
package.json 5/5 Both posthog-js and posthog-node dependencies added correctly
pnpm-lock.yaml 5/5 Lock file properly updated
posthog-setup-report.md 4/5 Good documentation of events and next steps

App sanity check: 3/5 ⚠️

Criteria Result Description
App builds and runs Yes Build completes successfully with no errors
Preserves existing env vars & configs No Removed page-specific metadata from About page
No syntax or type errors Yes TypeScript compilation succeeds
Correct imports/exports Yes All PostHog imports are correct
Minimal, focused changes Mostly Changes are focused but include unnecessary metadata removal

Issues

  • Metadata regression: Converting About page to client component removed metadata export (title: 'About - Todo App', description: 'Learn more about this Next.js 15 todo application'). The comment claims it was "moved to layout.tsx" but no such file exists. Should either create app/about/layout.tsx with the metadata or use generateMetadata(). [MEDIUM]
  • No page view tracking: The integration captures custom events but doesn't explicitly set up page view tracking. While PostHog may auto-capture page views, it's not explicitly configured. [LOW]

Other completed criteria

  • Build compiles successfully
  • All imports resolve correctly
  • No runtime errors in build output
  • API routes function correctly
  • Environment variables properly referenced via process.env

PostHog implementation: 3/5 ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.333.0 and posthog-node@^5.24.1 in package.json
PostHog client initialized Yes Client via instrumentation-client.ts, server via singleton in lib/posthog-server.ts
capture() Yes Events captured on both client and server for CRUD operations
Identify() No No posthog.identify() calls anywhere - users remain anonymous
Error tracking Yes capture_exceptions: true enabled in instrumentation-client.ts
Reverse proxy Yes Properly configured in next.config.ts with /ingest rewrites

Issues

  • Client-server identity linkage broken: Server-side events look for x-posthog-distinct-id header but client fetch requests never include this header. All server events will have distinctId: 'anonymous', making it impossible to correlate client and server events for the same user. [CRITICAL]
  • No user identification: No posthog.identify() call anywhere. While this app may not have authentication, the integration should demonstrate identification patterns or at least document this gap. [MEDIUM]
  • Server client uses NEXT_PUBLIC_POSTHOG_HOST: The server client uses process.env.NEXT_PUBLIC_POSTHOG_HOST which is set to https://us.i.posthog.com. This bypasses the reverse proxy (which uses /ingest). Should use https://us.i.posthog.com directly for server-side (which it does) but the variable naming is confusing. [LOW]

Other completed criteria

  • API key accessed via environment variable (not hardcoded in code)
  • Client uses reverse proxy (api_host: "/ingest")
  • UI host correctly set to https://us.posthog.com
  • Exception capture enabled
  • Debug mode conditional on development environment
  • Singleton pattern for server client prevents multiple instances
  • Shutdown function provided for graceful cleanup

PostHog insights and events: 4/5 ✅

Filename PostHog events Description
todo-form.tsx todo_add_button_clicked Client-side click event with has_description property
todo-item.tsx todo_toggle_clicked, todo_delete_button_clicked Client-side interaction events with todo_id, new_completed_state, was_completed properties
todo-list.tsx about_page_link_clicked Navigation tracking
app/about/page.tsx back_to_todos_clicked Navigation tracking
api/todos/route.ts todo_created Server-side creation event with todo_id, has_description
api/todos/[id]/route.ts todo_completed, todo_uncompleted, todo_deleted Server-side state change events with todo_id

Issues

  • Duplicate event tracking for same actions: Client captures todo_toggle_clicked and server captures todo_completed/todo_uncompleted for the same user action. While this provides client vs server confirmation, it may inflate event counts and complicate analysis. Consider documenting the intent or consolidating. [LOW]
  • Missing error context in events: Failed API calls don't capture error events. Consider adding todo_operation_failed events for error tracking beyond exceptions. [LOW]

Other completed criteria

  • Events represent real user actions (create, complete, delete, navigate)
  • Events can support funnel analysis (add button → created, toggle → completed)
  • Events enriched with relevant properties (todo_id, completion states, has_description)
  • No PII captured in event properties
  • Event names are descriptive and follow consistent naming convention
  • Server events capture the "truth" while client events capture intent/timing

Reviewed by wizard workbench PR evaluator

@wizard-ci-bot wizard-ci-bot bot added the CI/CD label Jan 21, 2026
@wizard-ci-bot wizard-ci-bot bot closed this Jan 21, 2026
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.

1 participant