Frameworks · Next.js

AI code review for Next.js —
catches the App Router / Server Actions traps.

Next.js has a specific class of bugs that generic reviewers miss: getServerSideProps leaking server env vars to the client bundle, Server Actions with no revalidation, unescaped user data in Route Handlers, useEffect cleanup gaps. LGTM's Next.js hints fire in the bugs + security + best-practices agents whenever it sees `next` in your package.json.

Auto-detected. Zero configuration.

Auto-detected when `next` appears in your package.json dependencies. Nothing to configure — install the App on your repo, LGTM flips into Next.js-aware mode on the next review.

Next.js bugs that hide in plain sight

Four patterns that get past general-purpose code review because they look like idiomatic Next.js. LGTM knows the shape of each.

Server env vars leaking to the client

getServerSideProps returns everything on `props` — but that `props` object is serialized into __NEXT_DATA__ and shipped to every browser. One line like `stripeKey: process.env.STRIPE_SECRET_KEY` and your secret is publicly viewable in View Source.

Server Actions with no revalidation

A Server Action mutates the DB, returns success, and the UI still shows the pre-mutation data because you forgot `revalidatePath()` or `revalidateTag()`. Silent staleness — no error, no crash, just wrong data on screen.

Route Handler + untrusted input

`app/api/*/route.ts` handlers receive Request objects. Interpolating `request.nextUrl.searchParams.get('id')` straight into a SQL query is a classic — no ORM to catch it, no framework guardrail. Standard code review misses it because it looks like ordinary TypeScript.

useEffect cleanup gaps

Subscriptions, timers, event listeners set up in useEffect need cleanup returns. Missing them means memory leaks + duplicate handlers on every re-mount. React StrictMode surfaces the double-invoke — but only if you're testing that path.

What LGTM actually catches

Three real examples — the Next.js-aware bugs + security agents flag these with inline 🎯 Actionable comments and a clear "why" explanation.

criticalsensitive-data-exposure
import type { GetServerSideProps } from "next";

export const getServerSideProps: GetServerSideProps = async () => {
  return { props: { stripeKey: process.env.STRIPE_SECRET_KEY! } };
};

What: getServerSideProps returns a server-only secret via props

Why: The whole props object is serialized into __NEXT_DATA__ and shipped to every visitor's browser. STRIPE_SECRET_KEY is publicly viewable — full account compromise. Use an API route with an authenticated fetch instead.

mediummissing-revalidation
"use server";
export async function updateUsername(id: string, name: string) {
  await db.user.update({ where: { id }, data: { name } });
  // no revalidatePath — the /users page still shows the old name
  return { ok: true };
}

What: Server Action mutates but doesn't revalidate any path

Why: Users see stale data until the next full navigation. Add `revalidatePath('/users')` or `revalidateTag('users')` before the return.

criticalsql-injection
export async function GET(request: NextRequest) {
  const id = request.nextUrl.searchParams.get("id");
  const row = await db.$queryRaw(
    `SELECT * FROM users WHERE id = '${id}'`,
  );
  return Response.json(row);
}

What: Raw SQL interpolation of a query-param in a Route Handler

Why: `request.nextUrl.searchParams` is fully attacker-controlled. Use `db.$queryRawUnsafe(sql, params)` with `$1` placeholders, or better yet the typed Prisma query.

Next.js starter .lgtm.yml

Skip generated `.next/**`, force the nextjs framework slug (so hints fire even without a package.json), bump sensitive-data-exposure to critical.

version: 1

paths:
  - pattern: ".next/**"
    skip: true
  - pattern: "**/*.generated.ts"
    skip: true

frameworks:
  - "nextjs"

severity_overrides:
  sensitive-data-exposure: "critical"
  sql-injection: "critical"

auto_approve_docs_only: true

Commit as .lgtm.yml at your repo root, flip the Enable .lgtm.yml toggle in Repo Settings. Next PR picks it up. See all recipes →

What ships on every Next.js review

Same pipeline that reviews everything else on LGTM — the Next.jshints just tune each agent's attention.

6 agents in parallel

Bugs, Security, Performance, Readability, Best-practices, Documentation. Each with framework-specific hints when LGTM detects your stack.

16 CI/CD detectors

LGTM Security scans your GitHub Actions, Dockerfiles, and lockfiles alongside the code review. Merge-blocking Check Run on block-level findings.

Adversarial verifier

Every finding is refuted by a skeptic LLM before it posts. Only survivors reach your PR. Kills the confident-hallucination class of false positives.

Try LGTM on your Next.js repo

Free tier: 20 reviews / month, all 6 agents, all 16 security detectors. BYOK OpenAI or Anthropic. No card required.