feat(nextjs): add 7 new Next.js best-practice rules from vercel-labs skill#680
feat(nextjs): add 7 new Next.js best-practice rules from vercel-labs skill#680devin-ai-integration[bot] wants to merge 9 commits into
Conversation
- nextjs-error-boundary-missing-use-client: error.tsx/global-error.tsx must have 'use client' - nextjs-global-error-missing-html-body: global-error.tsx must render <html> and <body> - nextjs-no-default-export-in-route-handler: route.ts must use named HTTP method exports - nextjs-no-google-analytics-script: use @next/third-parties instead of manual GA scripts Also extract ROUTE_HANDLER_HTTP_METHODS to constants/nextjs.ts to deduplicate with server-hoist-static-io.ts Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
commit: |
|
No React Doctor issues found. 🎉 Reviewed by React Doctor for commit |
|
/rde parity |
|
✅ Parity OK — no diagnostic differences. Baseline:
trace |
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
| export const GOOGLE_ANALYTICS_SCRIPT_PATTERN = | ||
| /google-analytics\.com|googletagmanager\.com\/gtag|www\.googletagmanager\.com/; |
There was a problem hiding this comment.
🟡 GOOGLE_ANALYTICS_SCRIPT_PATTERN regex matches Google Tag Manager scripts, producing misleading diagnostics
The third alternative in the regex (www\.googletagmanager\.com) matches all scripts from www.googletagmanager.com, including Google Tag Manager scripts (e.g. https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX). These are not Google Analytics scripts, yet the rule fires with the message "Manual Google Analytics script blocks rendering" and recommends importing GoogleAnalytics from @next/third-parties/google. For a GTM script, the correct component would be GoogleTagManager. Additionally, this matching is inconsistent — GTM scripts from googletagmanager.com (without www.) are not caught, as confirmed by testing the regex.
Regex test results
www.googletagmanager.com/gtm.js?id=GTM-XXX→ matches (false positive, it's GTM not GA)googletagmanager.com/gtm.js?id=GTM-XXX→ does NOT match (inconsistent)www.googletagmanager.com/gtag/js?id=G-XXX→ matches (correct, GA4)www.google-analytics.com/analytics.js→ matches (correct, old GA)
| export const GOOGLE_ANALYTICS_SCRIPT_PATTERN = | |
| /google-analytics\.com|googletagmanager\.com\/gtag|www\.googletagmanager\.com/; | |
| export const GOOGLE_ANALYTICS_SCRIPT_PATTERN = | |
| /google-analytics\.com|googletagmanager\.com\/gtag/; |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Good catch — the third alternative matched all GTM scripts, not just GA. Fixed by narrowing to google-analytics\.com|googletagmanager\.com\/gtag which only matches GA4 (/gtag/js) and legacy GA (google-analytics.com).
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
…rt, no-edge-og-runtime - nextjs-no-script-in-head: <Script> inside <Head> is silently ignored - nextjs-no-vercel-og-import: use next/og instead of @vercel/og - nextjs-no-edge-og-runtime: avoid Edge runtime in OG image files Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
- fix: nextjs-no-script-in-head skip self-closing <Head /> to avoid false positives - refactor: extract fileContainsJsxElements to utils/ (one-utility-per-file) - refactor: global-error rule walks AST once instead of twice - refactor: no-edge-og-runtime hoists filename check to Program handler Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
- target/found → targetTagNames/foundTagNames in fileContainsJsxElements - tag → tagName in filter/map callbacks - REQUIRED_TAGS → REQUIRED_HTML_TAGS Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit aeec7ff. Configure here.
Co-Authored-By: Aiden Bai <aiden.bai05@gmail.com>

Summary
Four new Next.js rules derived from the vercel-labs/next-skills/next-best-practices skill, covering gaps in error handling, route handlers, and script optimization:
nextjs-error-boundary-missing-use-client(error) —error.tsx/global-error.tsxin/app/without'use client'silently fails to catch errors. Detection: filename pattern +hasDirective.nextjs-global-error-missing-html-body(error) —global-error.tsxmust render<html>+<body>since the root layout unmounts on error. Detection:walkAstfor JSX tag names.nextjs-no-default-export-in-route-handler(error) —export defaultinroute.tsis silently ignored; Next.js only recognizes named HTTP method exports (GET,POST, etc.). Detection:ExportDefaultDeclaration+ scan for named HTTP method exports viaprogramHasNamedHttpMethodExport.nextjs-no-google-analytics-script(warn) — Manual<script>/<Script>loading Google Analytics hurts performance;@next/third-parties/googleloads optimally. Detection:srcattribute matchingGOOGLE_ANALYTICS_SCRIPT_PATTERN.Also extracts
ROUTE_HANDLER_HTTP_METHODSfrom local constant inserver-hoist-static-io.tsintoconstants/nextjs.tsto deduplicate.Link to Devin session: https://app.devin.ai/sessions/653e55fe57524520a26e1f8fa57eafa2
Requested by: @aidenybai
Note
Low Risk
Additive static-analysis rules and shared constants only; no runtime or security-sensitive behavior changes in consumer apps.
Overview
Adds seven Next.js-focused oxlint rules to
react-doctor, wired through generatedrule-registryentries and shared patterns inconstants/nextjs.ts.Error handling & App Router conventions: flags
error.tsx/global-error.tsxunderapp/without'use client', andglobal-error.tsxmissing<html>/<body>(via newfileContainsJsxElementshelper). Route handlers: warns whenroute.tsusesexport default(or re-exportsdefault) without namedGET/POST/… exports. Scripts & OG: errors on<Script>nested in<Head>, warns on manual GA script tags,@vercel/ogimports, andruntime = 'edge'on opengraph/twitter image routes.ROUTE_HANDLER_HTTP_METHODSis centralized innextjs.tsand reused byserver-hoist-static-io(replacing a local duplicate).Reviewed by Cursor Bugbot for commit 161a6c5. Bugbot is set up for automated code reviews on this repo. Configure here.