Re-running the wizard on an already-instrumented project overwrites deliberate user configuration
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 197
- Forks
- 51
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 94
Description
Problem
#616 describes the detection gap and quotes a user who feared the wizard "was about to start changing whatever I had set up previously." I ran the full default flow on an already-instrumented project to see what actually happens on that path. The fear is justified: re-instrumentation undoes deliberate, hand-written configuration — including a setting PostHog's own docs require.
Setup: Next.js 16.2.10 app deployed to Cloudflare Workers via @opennextjs/cloudflare 1.20.1, with a hand-tuned PostHog integration already in place: reverse proxy through Next rewrites (/ingest), an identify component with an intentional dedupe guard, and a server-side posthog-node client. Wizard 2.64.1.
To be fair up front: the event instrumentation the wizard added was genuinely good — sensible snake_case taxonomy with useful properties (scene_added {scene_type}, new_film_started {creation_method}), captures placed in the state-owning hooks rather than the UI layer, and it even gated one capture on a workflow's APPLIED status instead of capturing blindly. The problem is what it did to the code that already existed.
What got overwritten
1. Removed ui_host while keeping the reverse proxy
posthog.init(token, {
api_host: "/ingest",
- ui_host: "https://us.posthog.com",
+ tracing_headers: [window.location.hostname],
defaults: "2026-01-30",
capture_exceptions: true,
The reverse proxy docs explicitly say to set ui_host when api_host points at a proxy, so the toolbar and app links don't resolve against the proxy. The wizard kept my api_host: "/ingest" (good) but dropped the ui_host that goes with it. As far as I can tell the only reference to ui_host in this repo is an e2e fixture, so nothing currently asserts it survives a run.
(The tracing_headers addition itself is fine — I verified it's a real option in posthog-js 1.407.2.)
2. Deleted hand-written comments explaining why
The init file had comments documenting the reverse-proxy rationale ("rewrites via the worker so ad-blockers don't eat events") and the error-tracking choice. The identify component had a comment explaining what it links. All dropped, while the surrounding code was kept. Comments are the strongest intent signal a hand-written integration has, and they didn't survive the rewrite.
3. Removed an intentional identify guard
export function PostHogIdentify({ userId, email }: { userId: string; email?: string | null }) {
useEffect(() => {
- if (posthog.get_distinct_id() !== userId) {
- posthog.identify(userId, email ? { email } : undefined);
- }
+ posthog.identify(userId, email ? { email } : undefined);
}, [userId, email]);
The component is rendered from server pages, so it mounts on every navigation. With the guard gone, identify() (with a properties payload) now fires per navigation, sending redundant $set events. The guard was deliberate.
4. Silently dropped an explicit host fallback in the server client
client = new PostHog(key, {
- host: env?.NEXT_PUBLIC_POSTHOG_HOST ?? process.env.NEXT_PUBLIC_POSTHOG_HOST ?? "https://us.i.posthog.com",
+ host: env?.NEXT_PUBLIC_POSTHOG_HOST ?? process.env.NEXT_PUBLIC_POSTHOG_HOST,
Behavior now depends on the env var being set, with no stated reason for the change. (On Workers, env access is request-scoped, which is why the explicit fallback existed.)
5. Minor, in code it added: logout capture races a full-page POST
<form action="/auth/logout" method="post"
onSubmit={() => { posthog.capture("user_logged_out"); posthog.reset(); }}>
The form immediately navigates, so the capture can be lost in the unload, and reset() competes with the flush. (Adding reset() on logout was the right call — the ordering is the issue.)
Why this happens
The wizard has no way to distinguish "deliberate user decision" from "default it should improve." A hand-tuned ui_host looks identical to leftover boilerplate, and the comments that would disambiguate get deleted rather than read as intent. On greenfield this doesn't matter; on the exact path #616 worries about, it does.
Suggested behavior
- Treat existing, working integration code as load-bearing: don't remove config options, guards, or comments the wizard didn't author unless it can say why.
- Preserve comments verbatim when editing existing files.
- When changing existing config is genuinely warranted, surface it as an explicit per-change "changed X because Y" in the review step, rather than a silent rewrite.
- This pairs with #616: its proposed "Re-run integration anyway" escape hatch is only safe if this path is non-destructive.
Happy to share the full diff of the run if useful.
Environment
@posthog/wizard2.64.1 (vianpx)- Next.js 16.2.10,
@opennextjs/cloudflare1.20.1, wrangler 4.112.0 - posthog-js 1.407.2, posthog-node 5.46.0
- Node v22.23.2, Linux
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the wizard logic that rewrites existing integration files and the e2e fixture that references ui_host, then compare how existing configuration and comments are handled. Done should mean re-running on an instrumented project preserves user-owned options, guards, and comments, while any intentional changes are explained explicitly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nextjs, typescript
- Domain
- developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100