{"slug": "fix-a-setting-shows-as-undefined-in-the-browser-of-your-next-js-app-next-public", "title": "Fix: a setting shows as \"undefined\" in the browser of your Next.js app (NEXT_PUBLIC_ environment variable, tested repro, Next 16 + React 19.3)", "summary": "A developer reproduced a Next.js bug where a client-side setting renders as \"undefined\" in the browser despite a passing build, tracing it to two causes: environment variables missing the NEXT_PUBLIC_ prefix, and variables added after `next build` ran. The fix is to rename the variable and its reader with the NEXT_PUBLIC_ prefix, then rebuild; the repro was verified on a synthetic app with Next 16.4.3, React 19.3.1 and headless Chrome, and the developer notes secret keys must never receive the public prefix.", "body_md": "A setting such as a booking link works on the server but shows up as `undefined` in the browser, with no error message and a passing build. In an AI-built (or hand-built) Next.js app, the usual causes are a variable name without the `NEXT_PUBLIC_` prefix, or a variable added after the app was built.\n\nWe reproduced it on a small synthetic app, applied the smallest fix, and checked it by clicking the button in headless Chrome. Below: the symptom, the cause, the fix, how we verified it, and what we did **not** test.\n\n**Short answer:** If a setting such as your booking link or API address works on the server but shows up as `undefined` in the browser, either the variable's name doesn't start with `NEXT_PUBLIC_`, or you added it after the app was built. The smallest fix is to rename it (and the line of code that reads it) with the `NEXT_PUBLIC_` prefix, then **rebuild**. **Verified on a synthetic app only.**\n\n`app/` folder), with a setting stored as an environment variable (a `.env.local` file or your host's \"Environment Variables\" page).`undefined` (for example a link that goes to `undefined/book`). `NEXT_PUBLIC_` value is copied into the code every visitor downloads. Secret keys (service-role keys, payment secrets, passwords) must never get this prefix. See \"Security notes\".\nThere is no red error. This is what we saw in headless Chrome after clicking the button:\n\n```\ntext shown after clicking \"Book a call\": \"undefined/book\"\n```\n\nThe page's code was `process.env.BOOKING_URL + \"/book\"`, and `BOOKING_URL=https://booking.example.test` was set in `.env.local`. The build log even says `Environments: .env.local` and exits 0. If your code sends that value to a service, you will typically see failed requests or `undefined` inside a URL in your browser's Network tab instead (we did not test that part).\n\n| Item | Version | \n|---|---|\n| Node.js | 20.19.2 | \n| next | 16.4.3 (Turbopack) | \n| react / react-dom | 19.3.1 | \n| Browser | Google Chrome 155.0.8059.84, headless, via playwright-core 1.64.1 | \n| OS | Linux, single machine | \n\nNext.js runs your code in two places: on the server, and in your visitor's browser. The browser can't see your server's settings. To let it see a setting, Next.js copies the value into the downloaded JavaScript when you run `next build`, but **only** for variables whose names start with `NEXT_PUBLIC_`, and only if the variable exists at that moment ([official docs](https://nextjs.org/docs/app/guides/environment-variables)).\n\nThat gives two common ways to get `undefined`:\n\n`BOOKING_URL` stays on the server. In the browser, `process.env.BOOKING_URL` is empty. In our built bundle the code was still a lookup at click time: `process.env.BOOKING_URL+\"/book\"`.` NEXT_PUBLIC_BOOKING_URL` is right, but it wasn't set when `next build` ran (for example you added it to your host's settings after the last deploy). The value is \"frozen\" at build time, so the browser still gets `next start` still gave Public reports of the same family: the [Next.js discussion #74624](https://github.com/vercel/next.js/discussions/74624) (Next 15 + React 19 + Turbopack) and a [Stack Overflow answer](https://stackoverflow.com/questions/68205264/environment-variables-in-nextjs-are-undefined) saying env files are read when the server starts and production needs a rebuild. We found these through web search and did not measure how common the problem is, or how often AI tools cause it.\n\n`process.env.NEXT_PUBLIC_BOOKING_URL`.` npx next build`, start again; in dev, stop and restart `npm run dev`). On a host, trigger a new deploy after saving the variable.`app/BookButton.js`\n\n``` js\n\"use client\";\nimport { useState } from \"react\";\n\nexport default function BookButton() {\n  const [link, setLink] = useState(\"\");\n  return (\n    <div>\n      <button onClick={() => setLink(process.env.BOOKING_URL + \"/book\")}>Book a call</button>\n      <p id=\"link\">{link}</p>\n    </div>\n  );\n}\n```\n\n`.env.local`: `BOOKING_URL=https://booking.example.test`\n\n``` js\n-      <button onClick={() => setLink(process.env.BOOKING_URL + \"/book\")}>Book a call</button>\n+      <button onClick={() => setLink(process.env.NEXT_PUBLIC_BOOKING_URL + \"/book\")}>Book a call</button>\n```\n\n`.env.local`: `NEXT_PUBLIC_BOOKING_URL=https://booking.example.test`\n\nWrite it exactly as `process.env.NEXT_PUBLIC_NAME`. Per the Next.js docs and the discussion linked above, forms like `process.env[name]`, saving `process.env` in a variable first, or optional chaining (`process?.env?.NAME`) are not replaced. **We did not test those forms.**\n\nIf the value must be changeable without rebuilding, or must stay secret, don't use `NEXT_PUBLIC_`. Read the value in server code and give the browser only what it needs, for example through your own API route. **We did not test that approach.**\n\n```\nIn my Next.js App Router app, a setting works on the server but is undefined in the browser. Find every place in files marked \"use client\" (or components imported by them) that reads process.env.SOMETHING where SOMETHING does not start with NEXT_PUBLIC_. For each one, tell me whether the value is safe for any visitor to see. For the safe ones only, rename the variable to NEXT_PUBLIC_SOMETHING in the code, in .env.local and in .env.example, and write the access exactly as process.env.NEXT_PUBLIC_SOMETHING (no optional chaining, no process.env[name], no aliasing). For secrets (keys, tokens, passwords), do NOT add the prefix; instead move that code to a server route and tell me. Do not change anything else, show me the diff, and remind me to set the renamed variables on my host and redeploy.\n```\n\nReview the diff yourself and check no secret got the prefix. We did not test this prompt in any AI tool.\n\nRun on 2026-10-24 on a small synthetic app (three copies: before, after, and \"added too late\"), using headless Chrome with default settings.\n\n`next dev`):` https://booking.example.test/book`.\nEvery run also logged one unrelated `404` resource error that we did not identify (probably a missing icon file); we did not confirm which file it was.\n\n`VITE_` names and `import.meta.env`). A `process.env[name]` and aliasing cases, and the \"read it on the server and pass it down\" alternative.`package.json`) and the name has no typos or spaces around `=`.` https://booking.example.test`.\nThe original guide, with the before/after files, is on The Agent Ledger: [A setting shows as \"undefined\" in the browser: Next.js fix](https://theagentledger.ai/fixes/next-public-env-undefined-in-browser/?utm_source=devto&utm_medium=post&utm_campaign=fix04).\n\n*AI disclosure: This article was written with the help of AI. The reproduction and the before/after browser runs described above were actually performed and checked against the logs before publishing.*", "url": "https://wpnews.pro/news/fix-a-setting-shows-as-undefined-in-the-browser-of-your-next-js-app-next-public", "canonical_source": "https://dev.to/theagentledger/fix-a-setting-shows-as-undefined-in-the-browser-of-your-nextjs-app-nextpublic-environment-39f6", "published_at": "2026-10-24 13:32:38+00:00", "updated_at": "2026-10-24 13:42:50.769379+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Next.js", "Vercel", "React", "Chrome", "Playwright"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/fix-a-setting-shows-as-undefined-in-the-browser-of-your-next-js-app-next-public", "markdown": "https://wpnews.pro/news/fix-a-setting-shows-as-undefined-in-the-browser-of-your-next-js-app-next-public.md", "text": "https://wpnews.pro/news/fix-a-setting-shows-as-undefined-in-the-browser-of-your-next-js-app-next-public.txt", "jsonld": "https://wpnews.pro/news/fix-a-setting-shows-as-undefined-in-the-browser-of-your-next-js-app-next-public.jsonld"}}