Upgrade to Next.js 16 and next-intl 4.9.1#19
Conversation
- Rename middleware.ts to proxy.ts with named export (Next.js 16 convention) - Add second argument to revalidateTag calls (new required signature) - Create ESLint flat config (eslint.config.mjs) and update lint script - Fix all lint errors: replace refs-during-render with state, derive values instead of setState-in-effect, remove `as any` casts, use next/image for logo SVG Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 44 minutes and 0 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughUpgrades Next.js and React dependencies, adds an ESLint flat config, renames middleware to a named Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 8 |
| Duplication | 2 |
TIP This summary will be updated as you push new changes. Give us feedback
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/sections/ReferLocalGroupModal.tsx (1)
21-27:⚠️ Potential issue | 🟡 Minor
openDialogdoesn't resetformData— inconsistent with the sibling modals.
ReferCommunityProjectModal.openDialogandSubmitProjectModal.openDialogboth callsetFormData({...})to clear the snapshot, but this one doesn't. Once a user submits (or opensawaiting_codethen closes), reopening the modal will render the form with the previous submission prefilled viadefaultValue={formData.*}on lines 293/307/322/337/354/369, which diverges from the other two modals' behavior. If the intent is to always start fresh (matching the sibling modals), add a reset here.🔧 Proposed reset in
openDialogconst openDialog = useCallback(() => { setStatus('idle') setVerificationCode('') setCodeError('') + setFormData({}) openedAtRef.current = Date.now() dialogRef.current?.showModal() }, [])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/sections/ReferLocalGroupModal.tsx` around lines 21 - 27, openDialog in ReferLocalGroupModal currently resets status, verificationCode, codeError and openedAtRef but does not reset formData, causing stale values to reappear via defaultValue bindings (formData.*). Update ReferLocalGroupModal.openDialog to call setFormData(...) to the same initial/empty shape used when the component mounts (match the snapshot clearing behavior of ReferCommunityProjectModal.openDialog and SubmitProjectModal.openDialog) so the modal always opens with a fresh form; reference the formData state and setFormData setter when adding this reset.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@components/projects/RepoLanguages.tsx`:
- Around line 56-69: The effect doesn't reset the loading state when repos
changes; update the useEffect for repoIds/repos so it calls setLoading(true) at
the start (and optionally setLanguages(undefined|null) to clear prior results)
before initiating the fetch, and use an AbortController to cancel the in-flight
fetch instead of a cancelled flag; make changes around the useEffect block that
references repoIds, repos, setLoading and setLanguages so refetches show the
skeleton properly.
In `@components/sections/FishBackground.tsx`:
- Line 3: The FishBackground component currently seeds its SVG layout using
Math.random() inside useState during initialization (the initializer that
creates the fish layout and count), which causes SSR/client hydration mismatches
and also freezes layout when the count prop changes; replace the
nondeterministic initializer by either (a) deriving a deterministic seeded RNG
from the count prop and using that to generate the layout in the component
render (or in a useMemo keyed by count) so server and client produce identical
output, or (b) move the component to client-only rendering via dynamic
import/Suspense and keep the random generation on mount; update the
layout-generation function reference (the function that currently calls
Math.random()) to accept a seed or to be invoked inside a client-only effect so
it no longer runs during SSR.
In `@package.json`:
- Line 30: Update the eslint dependency version range in package.json to require
at least v9.22.0 so that the named exports used in eslint.config.mjs
(defineConfig, globalIgnores) are present; specifically, change the "eslint"
entry currently set to "^9.0.0" to "^9.22.0" to prevent installs that resolve to
9.0.x–9.21.x where those exports are missing.
---
Outside diff comments:
In `@components/sections/ReferLocalGroupModal.tsx`:
- Around line 21-27: openDialog in ReferLocalGroupModal currently resets status,
verificationCode, codeError and openedAtRef but does not reset formData, causing
stale values to reappear via defaultValue bindings (formData.*). Update
ReferLocalGroupModal.openDialog to call setFormData(...) to the same
initial/empty shape used when the component mounts (match the snapshot clearing
behavior of ReferCommunityProjectModal.openDialog and
SubmitProjectModal.openDialog) so the modal always opens with a fresh form;
reference the formData state and setFormData setter when adding this reset.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e871471f-4b8e-46a7-8fe7-666acc33376b
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (15)
app/[lang]/layout.tsxapp/api/revalidate/route.tsapp/api/stats/route.tscomponents/blog/ShareButtons.tsxcomponents/projects/RepoLanguages.tsxcomponents/sections/FishBackground.tsxcomponents/sections/HeroBanner.tsxcomponents/sections/ReferCommunityProjectModal.tsxcomponents/sections/ReferLocalGroupModal.tsxcomponents/sections/SubmitProjectModal.tsxeslint.config.mjspackage.jsonproxy.tssrc/i18n/request.tstsconfig.json
Replace imperative loading/languages reset with derived loading state based on fetchedKey comparison. Use AbortController instead of a cancelled flag for proper fetch cancellation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace Math.random() with a mulberry32 seeded PRNG derived from the count prop. This ensures server and client produce identical fish layouts (no hydration mismatch) and the layout updates when count changes via useMemo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The eslint.config.mjs uses defineConfig and globalIgnores which were added in ESLint 9.22.0. Bump the minimum version to prevent installs that resolve to older 9.x versions where these exports are missing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add setFormData({}) to openDialog to clear stale form values,
matching the reset behavior of the other two modal components.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uncontrolled inputs with defaultValue only read the value on mount. Add a formKey counter that increments on openDialog and handleBackToForm, used as key on the <form> element to force React to remount inputs with current formData values. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…attribute Codacy flags passing an async function directly to onSubmit since the attribute expects void, not Promise<void>. Wrap in a non-async arrow function that discards the return value. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/sections/ReferCommunityProjectModal.tsx (1)
148-153:⚠️ Potential issue | 🟡 MinorMinor:
handleBackToFormleavestagsstate untouched — confirm this is intentional.Unlike
openDialog,handleBackToFormdoes not resettags/tagInput. This is likely desired (preserve user-entered tags on back-navigation, mirroring howdefaultValuere-populates text fields fromformData.fields), but note thattagsis not remounted byformKeysince it lives outside the form subtree, so whatever the user last had in the chip input remains. If the intent was to restore the tags that were submitted (i.e.formData.tags) rather than the current livetags, you'd wantsetTags(formData.tags)here. As-is it's consistent — just flagging for awareness.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/sections/ReferCommunityProjectModal.tsx` around lines 148 - 153, handleBackToForm currently resets status, verificationCode, codeError, and formKey but intentionally leaves tags/tagInput unchanged; decide whether to preserve user-entered chips or restore the submitted tags and implement accordingly: if you want to restore submitted tags use setTags(formData.tags) (and optionally setTagInput('') to clear the input) inside handleBackToForm, otherwise add a short comment in handleBackToForm noting tags/tagInput are intentionally preserved to avoid confusion when future maintainers see the discrepancy with openDialog.
🧹 Nitpick comments (2)
components/sections/FishBackground.tsx (2)
1-3:'use client'may no longer be required.Now that fish generation is fully deterministic and uses only
useMemo(which works in Server Components as a no-op-friendly hook only when state is involved — and here there's no state, effects, refs, or browser APIs), this component could likely be a Server Component. Dropping'use client'would shrink the client bundle and let the SVG markup ship as static RSC payload.That said, if
FishBackgroundis imported into other Client Components, the directive is harmless — feel free to skip if the cost/benefit isn't worth it.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/sections/FishBackground.tsx` around lines 1 - 3, Remove the top-level 'use client' directive from the FishBackground component so it can be a Server Component and avoid shipping unnecessary client JS; locate the FishBackground component in components/sections/FishBackground.tsx (which currently imports useMemo) and confirm the deterministic fish generation only uses useMemo with no state, effects, refs, or browser APIs, then delete the "'use client'" line and ensure imports/exports remain unchanged so the SVG markup is emitted as static RSC payload (keep 'use client' only if this component is directly imported by other Client Components).
55-102: Deterministic seeding resolves the prior hydration concern.The mulberry32 PRNG keyed off
countproduces identical output on server and client, anduseMemo([count])keeps the layout stable while still recomputing ifcountchanges. Nicely addresses the previous Math.random feedback.One small caveat worth being aware of: every
<FishBackground count={N} />rendered with the samecountwill now produce the exact same layout (same positions/rotations/path picks). If you ever render multiple instances on a page and want them to look distinct, consider accepting an optionalseedprop (defaulting tocount * 7919) so callers can vary it.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/sections/FishBackground.tsx` around lines 55 - 102, The current deterministic PRNG uses count*7919 so identical FishBackground instances share layout; add an optional seed prop to FishBackground (e.g., function signature FishBackground({ count = 5, seed?: number }) and prop type) defaulting to count * 7919, use that seed when creating the RNG (replace createSeededRng(count * 7919) with createSeededRng(seed ?? count * 7919)), and include seed in the useMemo dependency array ([count, seed]) so different seeds produce distinct placements; update any callers/tests as needed to pass a custom seed when uniqueness is required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@components/sections/ReferCommunityProjectModal.tsx`:
- Around line 148-153: handleBackToForm currently resets status,
verificationCode, codeError, and formKey but intentionally leaves tags/tagInput
unchanged; decide whether to preserve user-entered chips or restore the
submitted tags and implement accordingly: if you want to restore submitted tags
use setTags(formData.tags) (and optionally setTagInput('') to clear the input)
inside handleBackToForm, otherwise add a short comment in handleBackToForm
noting tags/tagInput are intentionally preserved to avoid confusion when future
maintainers see the discrepancy with openDialog.
---
Nitpick comments:
In `@components/sections/FishBackground.tsx`:
- Around line 1-3: Remove the top-level 'use client' directive from the
FishBackground component so it can be a Server Component and avoid shipping
unnecessary client JS; locate the FishBackground component in
components/sections/FishBackground.tsx (which currently imports useMemo) and
confirm the deterministic fish generation only uses useMemo with no state,
effects, refs, or browser APIs, then delete the "'use client'" line and ensure
imports/exports remain unchanged so the SVG markup is emitted as static RSC
payload (keep 'use client' only if this component is directly imported by other
Client Components).
- Around line 55-102: The current deterministic PRNG uses count*7919 so
identical FishBackground instances share layout; add an optional seed prop to
FishBackground (e.g., function signature FishBackground({ count = 5, seed?:
number }) and prop type) defaulting to count * 7919, use that seed when creating
the RNG (replace createSeededRng(count * 7919) with createSeededRng(seed ??
count * 7919)), and include seed in the useMemo dependency array ([count, seed])
so different seeds produce distinct placements; update any callers/tests as
needed to pass a custom seed when uniqueness is required.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2357e213-9acf-4940-8087-21a8885cd85d
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
components/projects/RepoLanguages.tsxcomponents/sections/FishBackground.tsxcomponents/sections/ReferCommunityProjectModal.tsxcomponents/sections/ReferLocalGroupModal.tsxcomponents/sections/SubmitProjectModal.tsxpackage.json
🚧 Files skipped from review as they are similar to previous changes (4)
- package.json
- components/sections/ReferLocalGroupModal.tsx
- components/sections/SubmitProjectModal.tsx
- components/projects/RepoLanguages.tsx
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove 'use client' and useMemo — the deterministic seeded RNG needs no hooks, so the component can render as a server component. Add an optional seed prop for distinct layouts when multiple instances are needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Closes #18
middleware.ts→proxy.tswith named export (Next.js 16 convention)revalidateTag()calls (new required signature)eslint.config.mjs) replacing removednext lintChanges
package.jsoneslint .middleware.ts→proxy.tsexport default→export const proxyeslint.config.mjsapp/api/*/route.tsrevalidateTag(tag)→revalidateTag(tag, { expire: 0 })app/[lang]/layout.tsx,src/i18n/request.tsas anycastscomponents/blog/ShareButtons.tsxuseSyncExternalStorefor canSharecomponents/sections/FishBackground.tsxuseStateinitializer (avoids impure render)components/projects/RepoLanguages.tsxcomponents/sections/HeroBanner.tsx<img>→<Image>for logoformDataRef(ref) →formData(state)Test plan
npm run buildpassesnpm run lintpasses clean (0 errors, 0 warnings)npm run devstarts on Next.js 16.2.4 (Turbopack)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Improvements
Chores