Skip to content

[False Positive] Next.js rules recommend server-only fixes under output: "export" (static export) #976

Description

@Cmoen11

Summary

Several Next.js rules recommend a server-side fix (server redirect(), middleware, Server Actions). In a statically exported app (output: "export" in next.config) there is no server, no middleware, and no Server Actions, so the recommended fix is impossible and the finding is unactionable. react-doctor already adapts rules to project config elsewhere (e.g. static-value-rebuilt was disabled under React Compiler in #669 / #672), so detecting output: "export" and gating these rules would fit the same pattern.

Environment

  • react-doctor: 0.5.8 (npx react-doctor@latest)
  • next: 16.2.6, react / react-dom: 19.2.4
  • next.config.ts: output: "export", trailingSlash: true (no SSR, no middleware, no server-side auth)

Affected rules

1. react-doctor/nextjs-no-client-side-redirect

The message recommends redirect() in a server component or middleware. Under static export, any redirect that depends on client-only runtime state (auth, payment result, wizard state, sessionStorage) must run client-side in an effect — a server redirect() cannot observe that state, and middleware does not run. Example:

"use client";
// redirect after auth resolves on the client — there is no server to do this
useEffect(() => {
  if (!isLoading && isLoggedIn) router.replace("/mine-billetter/");
}, [isLoading, isLoggedIn, router]);

(Unconditional aliases like //no can and should still use server redirect(), and the rule correctly does not flag those — so a fix should keep flagging unconditional client-side redirects while exempting client-state-dependent ones, or gate on output: "export".)

2. react-doctor/no-prevent-default

For framework=nextjs it recommends <form action={serverAction}>. Server Actions are not supported with output: "export", so a client onSubmit + preventDefault() driving a client mutation is the only option:

<form onSubmit={(e) => { e.preventDefault(); renameMutation.mutate(value); }}>

The rule already self-exempts client-only frameworks (isClientOnlyFramework), but a static-export Next.js app is not detected as client-only even though, for this purpose, it is.

Suggested fix

Detect output: "export" from next.config.* (the loader already reads the Next.js version / config for capability detection) and add a capability such as nextjs:static-export. Then:

  • gate nextjs-no-client-side-redirect so it does not recommend a server redirect / middleware for client-state-dependent redirects, and
  • treat static-export Next.js like a client-only framework for no-prevent-default (and any other rule that recommends Server Actions).

This mirrors the React-Compiler handling in #669 / #672.

Note

This is distinct from #83 (which was about the diagnostic message being confusing and was fixed). This report is about the rule's recommended fix being impossible under output: "export", independent of wording.

Workaround (for reference)

In doctor.config.ts, "react-doctor/nextjs-no-client-side-redirect": "off" plus a per-file ignore.overrides entry for no-prevent-default removes the noise, but a config-aware rule would be preferable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions