# React Doctor Framework-Specific Rules for Next.js, React Native, and Vite

> Explore React Doctor's framework-specific lint rules for Next.js, React Native, and Vite. Enhance your code quality with specialized checks tailored for each environment. Find rules to improve your React projects.

- Repository: [Million Software, Inc./react-doctor](https://github.com/millionco/react-doctor)
- Tags: deep-dive
- Published: 2026-05-12

---

**React Doctor provides 15+ specialized lint rules for Next.js, 23+ rules for React Native, and currently relies on generic React rules for Vite projects.**

React Doctor is an ESLint-style static analysis tool that automatically detects your project framework and applies targeted rules for safer, more performant code. The linter identifies frameworks in [`packages/react-doctor/src/utils/discover-project.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/discover-project.ts) and activates rules based on the `requires` field defined in [`packages/react-doctor/src/oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts).

## How Framework Detection Works

The framework detection logic maps project signatures to specific rule sets. In [`packages/react-doctor/src/utils/discover-project.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/discover-project.ts), the `FRAMEWORK_MAP` object recognizes Next.js, React Native, and Vite among others.

```ts
export const FRAMEWORK_MAP = {
  nextjs: "Next.js",
  "react-native": "React Native",
  vite: "Vite",
  // …other frameworks
};

```

Only rules whose `requires` array includes the detected framework are enabled. For example, rules in [`packages/react-doctor/src/plugin/rules/nextjs.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/nextjs.ts) specify `requires: ["nextjs"]`, while React Native rules in [`packages/react-doctor/src/plugin/rules/react-native.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/react-native.ts) use `requires: ["react-native"]`.

## Next.js Framework-Specific Rules

All Next.js rules reside in [`packages/react-doctor/src/plugin/rules/nextjs.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/nextjs.ts) and enforce App Router compatibility, image optimization, and proper data fetching patterns.

### Image and Asset Optimization

**`nextjsNoImgElement`** disallows raw `<img>` tags in favor of the optimized `next/image` component.

```tsx
// ❌ Triggers error
<img src="/logo.png" alt="logo" />

// ✅ Recommended fix
import Image from 'next/image';
<Image src="/logo.png" alt="logo" width={200} height={100} />

```

**`nextjsImageMissingSizes`** requires a `sizes` attribute when using `fill` mode to prevent layout shifts.

```tsx
// ❌ Missing sizes
<Image src="/hero.jpg" fill />

// ✅ Correct usage
<Image src="/hero.jpg" fill sizes="(max-width: 600px) 100vw, 600px" />

```

**`nextjsNoNativeScript`** and **`nextjsInlineScriptMissingId`** enforce the use of `next/script` for external scripts and require IDs for inline scripts to ensure proper loading strategies.

```tsx
// ❌ Raw script tags
<script src="/analytics.js" />

// ✅ Use next/script
import Script from 'next/script';
<Script src="/analytics.js" strategy="afterInteractive" />

```

### App Router and Component Patterns

**`nextjsAsyncClientComponent`** flags async function components marked with `"use client"`, as client components cannot be async functions.

```tsx
'use client';
// ❌ Invalid: Client components cannot be async
export async function MyComp() { return <div />; }

```

**`nextjsNoUseSearchParamsWithoutSuspense`** ensures components using `useSearchParams()` are wrapped in `<Suspense>` boundaries to prevent server rendering issues.

```tsx
// ❌ Missing Suspense boundary
const params = useSearchParams();

// ✅ Wrap in Suspense
<Suspense fallback={<div>Loading...</div>}>
  <MyComponent />
</Suspense>

```

### Data Fetching and Navigation

**`nextjsNoClientFetchForServerData`** prohibits `fetch` calls inside `useEffect` on pages or layouts, encouraging server components or `getServerSideProps` instead.

**`nextjsNoClientSideRedirect`** and **`nextjsNoRedirectInTryCatch`** enforce server-side redirects using `redirect()` from `next/navigation` rather than client-side router pushes inside effects or try-catch blocks.

### Metadata and SEO

**`nextjsMissingMetadata`** ensures pages export `metadata` or `generateMetadata` for SEO optimization in the App Router.

```tsx
// ❌ Missing metadata export
export default function Page() { return <div />; }

// ✅ Add metadata
export const metadata = { title: "My Page" };

```

**`nextjsNoHeadImport`** disallows `next/head` usage in the App Router, directing developers to the Metadata API instead.

## React Native Framework-Specific Rules

React Native rules in [`packages/react-doctor/src/plugin/rules/react-native.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/react-native.ts) address native-specific pitfalls including raw text rendering, deprecated modules, and list performance.

### Core Component Safety

**`rnNoRawText`** prevents crashes by disallowing raw text nodes outside `<Text>` components, which is a common error that causes runtime failures on native platforms.

```tsx
// ❌ Crashes on native
<View>Hello World</View>

// ✅ Wrap in Text
<Text>Hello World</Text>

```

**`rnNoDeprecatedModules`** flags imports of removed React Native APIs and suggests replacements from the `DEPRECATED_RN_MODULE_REPLACEMENTS` mapping.

### List Performance Optimization

**`rnNoInlineFlatlistRenderitem`** detects inline function definitions in `renderItem` props that break memoization and cause unnecessary re-renders.

```tsx
// ❌ Inline function breaks memo
<FlatList data={items} renderItem={({item}) => <Item {...item} />} />

// ✅ Extract to stable reference
const renderItem = useCallback(({item}) => <Item {...item} />, []);
<FlatList data={items} renderItem={renderItem} />

```

**`rnNoScrollviewMappedList`** flags `ScrollView` with mapped children, suggesting virtualization via `FlatList` or `FlashList` for large datasets.

**`rnNoInlineObjectInListItem`** catches object literals in list item props that defeat React.memo optimizations.

### Animation and Styling

**`rnPreferReanimated`** suggests `react-native-reanimated` over the legacy `Animated` API for smoother, thread-safe animations.

**`rnAnimateLayoutProperty`** warns against animating layout properties like `height` in `useAnimatedStyle`, which runs on the UI thread and can drop frames.

**`rnStylePreferBoxShadow`** and **`rnNoLegacyShadowStyles`** enforce modern `boxShadow` syntax over platform-specific shadow properties.

### Navigation and Gestures

**`rnNoNonNativeNavigator`** prefers `@react-navigation/native-stack` over JavaScript-based stacks for better performance.

**`rnPressableSharedValueMutation`** flags direct mutations of Reanimated shared values inside `Pressable` handlers, recommending `GestureDetector` instead.

## Vite Framework Support

Currently, **React Doctor does not ship framework-specific rules for Vite**. While the framework detector recognizes Vite projects (`framework: "vite"`), no rules in [`packages/react-doctor/src/oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts) specify `requires: ["vite"]`. Vite projects receive the generic React rule set covering accessibility, performance, and design patterns applicable to any React codebase.

To add Vite-specific rules, developers can extend the configuration by creating a rule file and registering it with `requires: ["vite"]` in [`packages/react-doctor/src/oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts).

## Enabling Framework-Specific Rules

Activate rules by specifying the framework when running React Doctor:

```ts
import { reactDoctor } from "react-doctor";

// Next.js project
reactDoctor.run({
  cwd: "/path/to/next-app",
  framework: "nextjs",
});

// React Native project  
reactDoctor.run({
  cwd: "/path/to/rn-app",
  framework: "react-native",
});

```

Alternatively, import pre-configured rule sets directly:

```ts
import { configs } from "react-doctor";

reactDoctor.lint({ config: configs["next"] });          // Next.js rules
reactDoctor.lint({ config: configs["react-native"] }); // React Native rules  
reactDoctor.lint({ config: configs["recommended"] });  // Generic rules only

```

## Summary

- **Next.js** receives 15+ specialized rules in [`packages/react-doctor/src/plugin/rules/nextjs.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/nextjs.ts) covering image optimization (`nextjsNoImgElement`), App Router patterns (`nextjsAsyncClientComponent`), metadata requirements (`nextjsMissingMetadata`), and script loading (`nextjsNoNativeScript`).

- **React Native** benefits from 23+ rules in [`packages/react-doctor/src/plugin/rules/react-native.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/react-native.ts) addressing native crashes (`rnNoRawText`), list performance (`rnNoInlineFlatlistRenderitem`), animation threading (`rnPreferReanimated`), and deprecated APIs (`rnNoDeprecatedModules`).

- **Vite** projects currently use only generic React rules; no Vite-specific lint rules exist in the current version of `millionco/react-doctor`.

- Framework detection occurs automatically in [`packages/react-doctor/src/utils/discover-project.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/discover-project.ts), with rule activation controlled by the `requires` field in [`packages/react-doctor/src/oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts).

## Frequently Asked Questions

### How does React Doctor detect which framework I'm using?

React Doctor scans your project dependencies and structure in [`packages/react-doctor/src/utils/discover-project.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/discover-project.ts), mapping detected signatures to framework keys like `"nextjs"`, `"react-native"`, or `"vite"` via the `FRAMEWORK_MAP` constant. The detected framework key is then matched against the `requires` array in [`packages/react-doctor/src/oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts) to determine which rules to enable.

### Can I use Next.js rules in a React Native project?

No, framework-specific rules are isolated by their `requires` field. Rules defined in [`packages/react-doctor/src/plugin/rules/nextjs.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/nextjs.ts) specify `requires: ["nextjs"]`, meaning they only activate when the detector identifies a Next.js project. Similarly, React Native rules require `"react-native"` in their `requires` array.

### Why are there no Vite-specific rules available?

As implemented in `millionco/react-doctor`, the Vite framework detection exists in [`packages/react-doctor/src/utils/discover-project.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/discover-project.ts), but no rules in [`packages/react-doctor/src/oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts) currently specify `requires: ["vite"]`. The maintainers have focused on Next.js and React Native-specific optimizations, leaving Vite projects with the generic React rule set that applies to all React codebases.

### How do I enable framework-specific rules in my CI pipeline?

Import the pre-built config for your target framework and pass it to the lint function:

```ts
import { reactDoctor, configs } from "react-doctor";

await reactDoctor.lint({
  config: configs["next"], // or configs["react-native"]
  cwd: process.cwd()
});

```

This ensures only the relevant framework-specific rules from [`packages/react-doctor/src/plugin/rules/nextjs.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/nextjs.ts) or [`packages/react-doctor/src/plugin/rules/react-native.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/plugin/rules/react-native.ts) are executed against your codebase.