npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

eslint-plugin-use-agnostic

v1.7.5

Published

Highlights problematic server-client imports in projects made with the Fullstack React Architecture.

Downloads

1,880

Readme

eslint-plugin-use-agnostic

(Now powered by Comment Variables.)

eslint-plugin-use-agnostic highlights problematic server-client imports in projects made with the Fullstack React Architecture (Next.js App Router, etc.) based on each of their modules' derived effective directives through detailed import rule violations, thanks to the introduction of its very own 'use agnostic' directive.

Intro example of linting with the use-agnostic ESLint plugin including the suggestion to use the 'use agnostic' directive.

Installation

npm install eslint@^9 eslint-plugin-use-agnostic@latest --save-dev

Setup

// eslint.config.js

import { defineConfig, globalIgnores } from "eslint/config";

import useAgnostic, {
  useAgnosticPluginName,
  agnostic20ConfigName,
  // enforceEffectiveDirectivesRuleName
} from "eslint-plugin-use-agnostic";

export default defineConfig([
  globalIgnores([".next", ".react-router", "node_modules"]),
  {
    files: [
      "**/*.tsx",
      "**/*.ts",
      "**/*.jsx",
      "**/*.js",
      "**/*.mjs",
      "**/*.cjs",
    ],
    plugins: {
      [useAgnosticPluginName]: useAgnostic,
    },
    extends: [`${useAgnosticPluginName}/${agnostic20ConfigName}`],
  },
]);

And don't forget to install the ESLint VS Code plugin for live reports.

How it works

In the beginning, there were not two kinds of modules in the Fullstack React Architecture (server vs. client). There were three:

  • Server Modules
  • Client Modules
  • and Shared Modules, now Agnostic Modules

Shared Modules, which I've now renamed Agnostic Modules, are still here today. In fact, the React team originally anticipated that most modules used in conjunction with React Server Components would be Agnostic Modules. The problem is that Agnostic Modules are never surfaced between the current trifecta of 'use server', 'use client', and the lack of a directive:

  • 'use server' denotes modules that exclusively export Server Functions
  • 'use client' denotes modules that exclusively export code that is meant to be executed on the client
  • and the lack of a directive implies that a module is server-first... until it isn't

This means that while 'use server' denotes some special Server Modules but not all, and 'use client' denotes all Client Modules regardless of their range of behaviors, the lack of a directive denotes both Server Modules that do possess server-side code, and Agnostic Modules that possess code that is neither server nor client and can safely run in both environments.

With the 'use agnostic' directive, taking advantage of its being innocuous and entirely ignored by React at this time, it now becomes possible to manually distinguish between Server Modules, which are to remain unmarked by any directive in order to fullfill their server-first promise, and Agnostic Modules, which the 'use agnostic' directive now allows to identify clearly; all with eslint-plugin-use-agnostic linting your project accordingly.

But it doesn't end there. With React Components into the mix (especially RSCs), the reality is that not all Server, Client, and Agnostic Modules are born the same. For example, though a Server Module exporting Server Components cannot import client-side logic, it can actually import and compose with Client Components. This is where a new distinction intervenes, one that particularly takes into account the file extensions of the modules at hand to establish a list of 7 known modules in the Fullstack React Architecture:

  • Server Logics Modules, which DO NOT export React Components, and DO NOT use a JSX file extension
  • Server Components Modules, which ONLY export React Components (Server Components), and ONLY use a JSX file extension
  • Server Functions Modules, which ONLY export Server Functions, and DO NOT use a JSX file extension
  • Client Logics Modules, which DO NOT export React Components, and DO NOT use a JSX file extension
  • Client Components Modules, which ONLY export React Components (Client Components), and ONLY use a JSX file extension
  • Agnostic Logics Modules, which DO NOT export React Components, and DO NOT use a JSX file extension
  • Agnostic Components Modules, which ONLY export React Components (Agnostic Components), and ONLY use a JSX file extension

With this list established, it thus becomes possible to recognize static import violations between these 7 known modules that eslint-plugin-use-agnostic can now highlight for you in your code editor and in the CLI.

Caveats

It is up to you to confirm that your Agnostic Modules are indeed agnostic, meaning that they have neither server- nor client-side code. eslint-plugin-use-agnostic, at least at this time, does not do this verification for you.

It is also up to you to ensure, as outlined above, that you avoid exporting React components along with other logics within the same modules (unless you have to per the design of your current framework), which may derail the linting in some cases. Separating exporting React components within their own modules ending with a JSX file extension, from exporting other logics within modules that don't end with a JSX file extension, is crucial for distinguishing between Components Modules and Logics Modules respectively.

The import rules are designed to be as permissive as possible, allowing for more obscure use cases as long as they are non-breaking. However, it is still your responsibility as a developer to, within a file, not mix in incompatible ways code that cannot compose.

Philosophy

I believe the core issue hindering the comprehension of React Server Components is the fact that the Fullstack React Architecture has entirely erased its own roots since the introduction of directives by disregarding the architecture's primordial realities I have detailed above: its Modules. Server Modules. Client Modules. Agnostic Modules.

'use client' may denote to the server that a module's exports are to be imported as client references. But that effectively makes said module a "'use client' module", and it's only natural that a "'use client' module" would behave in a 'use client' way.

'use server' may denote to the client that a module's exports are to be imported as server references. But that effectively makes said module a "'use server' module", and it's only natural that a "'use server' module" would behave in a 'use server' way.

React can easily understand that a 'use client' module is, from a primordial standpoint, a Client Module. And it can also understand that a 'use server' module is a Server Module, albeit a special one.

But not having a directive to distinguish between 1. non-special Server Modules that are never meant to be imported on the client, even as references; and 2. actual Agnostic Modules, the Shared Modules that are still here at the heart of this system and are able to run anywhere; this creates a confusion that is detrimental to every single stackholder in the RSC ecosystem:

  • Developers are confused and have no idea what "Server" or "Client" means, since React doesn't make it crystal clear.
  • LLMs are confused, because even they can't understand what 'use server' and 'use client' mean and therefore cannot explain it to developers facing their own specific concerns.
  • And if LLMs are confused, I can't even imagine what that must mean for AI tools and AI agents.

This is what the 'use agnostic' directive solves. It clearly marks a module to be an Agnostic Module. And if a module that used to lack a directive can now be marked as an Agnostic Module, this allows modules without a directive to finally, truly be Server Modules by default. And eslint-plugin-use-agnostic can work from there.

A lot more needs to be done, and I suspect a lot of it unfortunately can only be optimized more deeply into React's innerworkings. But if the introduction of 'use agnostic' can already create such powerful static analysis, imagine what it could produce if only it were incorporated into React as an official directive of the Fullstack React Architecture.