Skip to content

chore(deps): upgrade next.js to 16.2.4#4460

Open
waleedlatif1 wants to merge 8 commits intostagingfrom
waleedlatif1/nextjs-upgrade-check
Open

chore(deps): upgrade next.js to 16.2.4#4460
waleedlatif1 wants to merge 8 commits intostagingfrom
waleedlatif1/nextjs-upgrade-check

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

@waleedlatif1 waleedlatif1 commented May 6, 2026

Summary

  • Bump next and @next/env to 16.2.4 across root, apps/sim, and apps/docs
  • Replace next-runtime-env's env() helper with a direct window.__ENV / process.env getter — its unstable_noStore() call is rejected by Next 16.2 outside request scope
  • Add export const dynamic = 'force-dynamic' to landing /privacy and /terms so NEXT_PUBLIC_* runtime env reads aren't baked at build

Type of Change

  • Chore / dependency upgrade

Testing

Tested manually — next build, tsc --noEmit, check:api-validation, and the full test suite (5695 tests) pass.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

- Bump next and @next/env to 16.2.4 across root, apps/sim, apps/docs
- Replace next-runtime-env's env() helper (calls unstable_noStore(), rejected by Next 16.2 outside request scope) with a direct window.__ENV / process.env getter
- Add export const dynamic = 'force-dynamic' on landing /privacy and /terms pages so NEXT_PUBLIC_* runtime env reads aren't baked at build
@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 6, 2026 1:51am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 6, 2026

PR Summary

Medium Risk
Upgrading Next.js and changing how NEXT_PUBLIC_* variables are resolved can affect build/runtime behavior and caching, especially for prerendered routes and image remote patterns.

Overview
Upgrades next/@next/env to 16.2.4 across the monorepo (including lockfile and overrides).

Reworks public env resolution to avoid next-runtime-env's env() helper (now reading NEXT_PUBLIC_* from window.__ENV on the client and process.env on the server), updates next.config.ts to use process.env for brand image host allowlisting, and forces dynamic rendering on a handful of routes (/privacy, /terms, /reset-password, /invite/[id], /unsubscribe, and manifest) so runtime-injected env values aren’t baked into static output.

Reviewed by Cursor Bugbot for commit 3abdafc. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR upgrades Next.js from 16.1.6 to 16.2.4 across the monorepo and adapts the codebase to Next 16.2's stricter rules around unstable_noStore() and useSearchParams usage outside Suspense boundaries.

  • env.ts rewrite: Removes the next-runtime-env env() helper (which internally called unstable_noStore(), rejected by Next 16.2 outside request scope) and replaces it with a direct window.__ENV / process.env getter; next.config.ts is updated to read process.env directly since it runs at build time in Node.js.
  • useSearchParams fixes: OAuthConsentPage is correctly wrapped in a Suspense boundary; the landing Navbar avoids Suspense by switching to a one-shot useEffect that reads window.location.search on mount.
  • force-dynamic opt-outs: Added to privacy, terms, manifest, reset-password, invite, and unsubscribe so runtime-injected NEXT_PUBLIC_* values are not baked at build time.

Confidence Score: 5/5

Safe to merge — the upgrade is mechanical and well-reasoned, with no changes to auth, data paths, or API contracts.

All changed files address Next 16.2 compatibility in straightforward ways. The env.ts rewrite is correct for both server and client paths. The force-dynamic additions are audited and necessary. The Suspense fix for OAuthConsentPage is the canonical pattern. The two observations are minor behavioral trade-offs with negligible real-world impact for this use case.

No files require special attention; the navbar's isBrowsingHome one-shot read and the env.ts client fallback are worth keeping in mind if landing page navigation behavior changes in future.

Important Files Changed

Filename Overview
apps/sim/lib/core/config/env.ts Replaces next-runtime-env's env() (which called unstable_noStore) with a direct window.__ENV / process.env getter; export is preserved. Client-side process.env fallback is a no-op for dynamic keys.
apps/sim/app/(landing)/components/navbar/navbar.tsx Removes useSearchParams (requires Suspense in Next 16.2) and replaces with a one-shot useEffect; isBrowsingHome won't update on subsequent client-side navigations within the landing layout.
apps/sim/app/(auth)/oauth/consent/page.tsx Wraps useSearchParams in a Suspense boundary — the correct pattern for Next 16.2 compatibility.
apps/sim/next.config.ts Removes getEnv import and uses process.env directly for brand logo/favicon URL parsing — correct since next.config.ts runs in Node.js at build time.
apps/sim/app/manifest.ts Adds force-dynamic to prevent NEXT_PUBLIC_BRAND_* values from being baked at build time.
apps/sim/app/(landing)/privacy/page.tsx Adds force-dynamic so NEXT_PUBLIC_PRIVACY_URL is read from the runtime environment rather than baked at build.
apps/sim/app/(landing)/terms/page.tsx Adds force-dynamic so NEXT_PUBLIC_TERMS_URL is read from the runtime environment rather than baked at build.
apps/sim/package.json Bumps next and @next/env from 16.1.6 to 16.2.4 in both dependencies and overrides.
apps/sim/app/(auth)/reset-password/page.tsx Adds force-dynamic to prevent static prerendering, required for Next 16.2 compatibility.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["getEnv called"] --> B{"typeof window === 'undefined'?"}
    B -- "Yes / Server" --> C["return process.env value"]
    B -- "No / Client" --> D{"window.__ENV has variable?"}
    D -- Yes --> E["return window.__ENV value"]
    D -- No --> F["return process.env fallback (no-op in browser)"]
    G["next.config.ts"] --> H["Uses process.env.NEXT_PUBLIC_BRAND_* directly"]
    I["OAuthConsentPage"] --> J["Suspense wraps useSearchParams"]
    K["Navbar"] --> L["useEffect on mount reads window.location.search once"]
    M["privacy / terms / manifest / reset-password / invite / unsubscribe"] --> N["force-dynamic added"]
Loading

Reviews (5): Last reviewed commit: "fix(navbar): preserve SSR HTML, drop Sus..." | Re-trigger Greptile

Comment thread apps/sim/lib/core/config/env.ts
Without this, NEXT_PUBLIC_BRAND_* values are baked into the manifest at build time. Pairs with the next-runtime-env removal in the prior commit, restoring Docker runtime injection for whitelabel deployments.
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/core/config/env.ts
Next 16.2's stricter prerender check fails the build when useSearchParams() is used without a Suspense boundary. Splits the client component into an outer wrapper and inner body.
Client components in (landing) (e.g. Navbar) read NEXT_PUBLIC_BRAND_* via getEnv. Without this, SSR prerender would bake the build-time process.env values into HTML, mismatching window.__ENV after hydration in Docker runtime-env deployments. Cascades to all landing routes via the layout.
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Cascading force-dynamic neutered dynamicParams = false + generateStaticParams on /blog/[slug], /integrations/[slug], /models/[provider], /models/[provider]/[model] — killing static prerender for SEO-critical pages. The hydration concern only materializes for whitelabel Docker deployments where build-time and runtime NEXT_PUBLIC_BRAND_* differ; those deployments can set the vars at build instead. Keeping force-dynamic on /privacy, /terms, and /manifest where it actually matters.
Next 16.2 fails the build when a client component using useSearchParams() is statically prerendered without a Suspense boundary.

- Wrap landing Navbar in Suspense (imported by /oauth/consent and other pages)
- Add force-dynamic to reset-password, invite/[id], and unsubscribe pages whose client bodies call useSearchParams
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e037cb8. Configure here.

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/(landing)/components/navbar/navbar.tsx Outdated
Reading useSearchParams() forced a Suspense fallback that emitted no navbar HTML during SSR — leaving crawlers and no-JS users without nav. The 'home' query param only affects client-side link targets, so read it from window.location in an effect after hydration. Restores full SSR navbar markup.
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3abdafc. Configure here.

The force-dynamic export name is self-documenting; the remaining env.ts comment is tightened to the essential WHY (why we don't use next-runtime-env's helper).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant