Skip to content

Migrate from Vite to Next.js 16 App Router#188

Merged
MaxGhenis merged 1 commit into
mainfrom
vite-to-next
May 9, 2026
Merged

Migrate from Vite to Next.js 16 App Router#188
MaxGhenis merged 1 commit into
mainfrom
vite-to-next

Conversation

@MaxGhenis
Copy link
Copy Markdown
Contributor

Summary

  • Swap Vite for Next.js 16.2.x App Router; React 19.2.x, Tailwind 4.2.x via @tailwindcss/postcss, @policyengine/ui-kit 0.9.x theme tokens. Mirrors the cbo-baseline-tracker layout used across PolicyEngine Next.js apps.
  • Port index.html SEO (metadata, JSON-LD, GA scripts, noscript fallback) into src/app/layout.jsx via the Next metadata API. The interactive tracker loads through next/dynamic with ssr: false so the SSR-rendered layout keeps full SEO while the window-driven SPA boots on the client.
  • Replace import.meta.env.VITE_* with process.env.NEXT_PUBLIC_*, swap the Vite PostHog middleware for a Next rewrite, guard window access in lib/basePath.js, drop .npmrc, commit bun.lock, native flat ESLint via eslint-config-next (no FlatCompat), no output: "standalone" / output: "export".

Notes

  • Two pre-existing useEffect blocks that mirror data into state synchronously get a scoped react-hooks/set-state-in-effect disable; refactoring would change runtime behavior, so the React 19 rule is silenced inline rather than rewriting.
  • modal_app.py still expects dist/ from a Vite build and scripts/prerender.mjs writes there. The Modal deploy and the prerender pipeline will need a follow-up to target Next's output. Not addressed here to keep the PR focused on the framework swap.

Test plan

  • bun run lint clean (0 errors, 10 pre-existing warnings)
  • bun run build succeeds and statically prerenders /
  • bun run test 31/31 pass
  • bun run dev returns 200 with full SEO metadata in initial HTML
  • CI green on Vercel preview

Generated with Claude Code

Mirrors the cbo-baseline-tracker shape so this repo follows the same
PolicyEngine Next.js layout: Tailwind v4 via @tailwindcss/postcss,
@policyengine/ui-kit theme tokens, eslint-config-next flat config, bun
lockfile.

The single-page tracker stays a client app (window-driven routing,
ResizeObserver, PostHog) and is loaded through next/dynamic with
ssr:false so the metadata-rich layout renders on the server while the
interactive surface boots on the client. SEO metadata, JSON-LD,
Google Analytics, and the noscript fallback are ported from index.html
into app/layout.jsx via the Next metadata API.

Vite-specific bits removed: vite.config.js, eslint.config.js, the legacy
.npmrc (Bun handles peer deps), package-lock.json, src/main.jsx, and
import.meta.env references (replaced with NEXT_PUBLIC_*). The PostHog
proxy moves from a Vite middleware to a Next rewrite, and basePath.js
now guards window access for SSR safety.

Two pre-existing useEffects that mirror data into state synchronously
get a scoped react-hooks/set-state-in-effect disable comment; the new
React 19 rule flagged them but refactoring would change behavior. The
modal_app.py deploy still expects dist/ from a Vite build and will need
a follow-up update once this lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@policyengine
Copy link
Copy Markdown

policyengine Bot commented May 9, 2026

Sorry @MaxGhenis, only members of the PolicyEngine/core-developers team can invoke Claude Code.

@MaxGhenis MaxGhenis merged commit fa5f793 into main May 9, 2026
@MaxGhenis MaxGhenis deleted the vite-to-next branch May 9, 2026 22:18
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