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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jabworks/oxlint-config

v0.6.0

Published

Opinionated oxlint presets for JS, TS, React, React Native, Next.js, and Vitest, ported from @jabworks/eslint-plugin

Readme

@jabworks/oxlint-config

Opinionated oxlint presets ported from @jabworks/eslint-plugin.

Presets

| Preset | Extends | Use for | | ------------- | ------------- | ------------------------------------------------------ | | base | — | Any JS/TS project | | typescript | base | TypeScript-only additions (some type-aware, see below) | | react | typescript | React libraries and apps | | next | react | Next.js applications | | reactNative | typescript | React Native apps, bare or any framework (oxlint-only) | | expo | reactNative | Expo apps, with expo-router conventions (oxlint-only) | | node | typescript | Node.js backends and APIs | | library | typescript | Framework-agnostic utility libraries | | vitest | — | Vitest test files (composable overlay) |

Installation

npm install -D oxlint oxlint-tsgolint @jabworks/oxlint-config

Usage

// oxlint.config.ts — pick the preset that matches your project
import { next } from '@jabworks/oxlint-config';
// or: import { expo, node, library, react, reactNative, typescript } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({
  extends: [next],
});
// package.json
{
  "scripts": {
    "lint": "oxlint --type-aware --deny-warnings",
  },
}

Note: oxlint.config.ts requires Node.js v22.18+ or v24+.

To compose or override, use the exported mergeConfigs helper:

import { mergeConfigs, typescript } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

const custom = mergeConfigs(typescript, {
  rules: { 'no-console': 'warn' },
});

export default defineConfig({ extends: [custom] });

What survives extends

oxlint's extends keeps a preset's rules, categories, plugins, and overrides, but drops its top-level env, globals, and ignorePatterns (verified on oxlint 1.85, and not mentioned in oxlint's docs). The presets are built around that:

  • Globals (env.browser in react/next, env.node in node, the React Native globals in reactNative) are delivered through a catch-all files: ['**/*'] override, which does survive extends.
  • Tool config files (*.config.{js,mjs,cjs,ts,mts,cts}, including oxlint.config.ts itself) get an override in base that allows their default export.
  • Ignore patterns (dist/, build/, coverage/, .next/, .expo/, …) only apply when a preset is spread into your config or passed through mergeConfigs. With plain extends, rely on .gitignore, which oxlint honors by default and which normally covers these paths already, or add ignorePatterns to your own config.

Type-aware rules

The typescript preset enables type-aware rules (typescript/no-misused-promises, typescript/consistent-type-exports, typescript/restrict-template-expressions, …). These require oxlint-tsgolint installed in the consuming project and running oxlint with --type-aware; without it they are silently skipped.

React Native and Expo presets

Neither preset has an @jabworks/eslint-plugin counterpart.

reactNative

For any React Native app, bare or built on a framework. It carries the same React rules as react (hooks, React Compiler rules, component style) but leaves out everything that assumes a DOM: the jsx-a11y plugin, env.browser, react/button-has-type, and react/jsx-no-target-blank. On top of that:

  • Globals. oxlint has no react-native environment, so the preset enables shared-node-browser (fetch, timers, URL, console) and declares __DEV__ and process (the bundler inlines process.env reads) as read-only globals. window and document stay undefined.
  • Ignores. android/ and ios/.

Platform suffixes such as card.ios.tsx already satisfy unicorn/filename-case in kebab case.

// oxlint.config.ts
import { reactNative } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({ extends: [reactNative] });

expo

reactNative plus expo-router's file conventions. It is a separate preset because the route override below would misfire in a bare React Native app, where an app/ folder holds ordinary named-export modules.

  • expo-router routes. Every file under app/ or src/app/ is a route, layout, or special file (_layout, +not-found, +html) that expo-router loads through its default export. There, import/no-default-export is off and import/prefer-default-export is on. API routes (*+api.ts) export named HTTP handlers and keep the house named-export rule. *.config.{ts,mts,cts} files, such as app.config.ts, must default-export too.
  • Ignores. .expo/ and expo-env.d.ts.

expo-router's file names ([id].tsx, [...rest].tsx, +not-found.tsx, (tabs)/_layout.tsx) already satisfy unicorn/filename-case in kebab case.

// oxlint.config.ts
import { expo } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({ extends: [expo] });

Note: like every preset's ignore patterns, these only apply when the preset is spread or merged (see What survives extends). A default React Native or Expo .gitignore already covers these paths.

Imperative renderers (three.js / React Three Fiber)

Code that drives an imperative renderer from React (three.js through React Three Fiber, Skia, expo-gl) trips two React Compiler rules on purpose:

  • react/refs flags the "latest ref" pattern (ref.current = value during render), which frame loops use to read fresh props without re-subscribing every frame.
  • react/preserve-manual-memoization only matters when the React Compiler runs, and it is usually off for such code.

imperativeRenderOverride turns both off for the globs you pass. Keep them narrow, so the rest of the app is still checked:

// oxlint.config.ts
import { imperativeRenderOverride, reactNative } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({
  extends: [reactNative],
  // Point it at wherever your renderer code lives.
  overrides: [imperativeRenderOverride(['src/3d/**'])],
});

It works with any React preset, not only reactNative. R3F's JSX props (args, castShadow, …) need no override: react/no-unknown-property is in oxlint's restriction category, which no preset enables.

Opt-in plugin layers: expoPlugin and reactNativePlugin

Two layers add rules that oxlint does not have built in, by running an ESLint-style plugin through oxlint's JS plugin support. They are opt-in because each one needs its plugin installed, and because any JS plugin adds a fixed runtime cost to every lint run (about 0.2 s on a mid-sized app).

| Layer | Install | Rules | | ------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | | expoPlugin | eslint-plugin-expo (official, from Expo) | no-dynamic-env-var, no-env-var-destructuring, use-dom-exports (error) | | reactNativePlugin | oxlint-plugin-react-native | no-raw-text (error); no-color-literals, no-inline-styles, no-single-element-style-arrays, no-unused-styles (warn) |

  • Env vars: Expo inlines only literal process.env.EXPO_PUBLIC_* reads, so a dynamic key or a destructured read is undefined at runtime.
  • no-raw-text: a string outside <Text> is a runtime error on native. The other React Native rules are hygiene: colours belong to theme tokens, and inline or single-element style arrays re-render needlessly.
  • Left out: expo/prefer-box-shadow (a styling preference) and react-native/sort-styles (only orders style keys).
npm install -D eslint-plugin-expo oxlint-plugin-react-native
// oxlint.config.ts
import { expo, expoPlugin, reactNativePlugin } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

// A bare React Native app would use `reactNative` with `reactNativePlugin` alone.
export default defineConfig({ extends: [expo, expoPlugin, reactNativePlugin] });

Both plugins are optional peer dependencies of this package, which lets pnpm link them where the preset can resolve them. Opting into a layer without installing its plugin stops the lint run with Failed to load JS plugin: <name>. JS plugins are alpha in oxlint and outside its semver guarantees, so pin oxlint in apps that use them.

Node and library presets

node

Sets env.node: true and enables the built-in node plugin with Node.js best practices:

  • unicorn/no-process-exit — use process.exitCode instead of process.exit() (registered under oxlint's unicorn plugin)
  • node/no-path-concat — use path.join() or path.resolve() over string concatenation
  • node/no-new-require — disallow new require(…)
  • node/no-exports-assign — disallow reassigning exports
  • node/handle-callback-err — enforce error handling in callbacks

Also includes a vitest test-file override (same as react).

// oxlint.config.ts
import { node } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({ extends: [node] });

Note: n/prefer-promises/fs, n/prefer-promises/dns, and n/prefer-global/* from eslint-plugin-n have no oxlint built-in equivalent as of 1.85. Use the ESLint node config alongside for those rules.

library

No environment globals — suitable for framework-agnostic packages (utility libraries, shared hooks, etc.). Activates import/no-cycle which is disabled in base for performance.

// oxlint.config.ts
import { library } from '@jabworks/oxlint-config';
import { defineConfig } from 'oxlint';

export default defineConfig({ extends: [library] });

Rules not ported from @jabworks/eslint-plugin

Unsupported by oxlint 1.85. Verify by loading a config that names the rule and checking for Rule '<name>' not found in plugin '<plugin>' — oxlint --rules prints nothing and cannot be used for this.

  • Core: no-octal-escape, camelcase, no-undef-init
  • Import: no-extraneous-dependencies, no-relative-packages, no-useless-path-segments, no-deprecated
  • TypeScript: naming-convention
  • React: jsx-no-leaked-render, jsx-sort-props, react-hooks/config, react-hooks/gating (the other twelve React Compiler rules from react-hooks recommended-latest are ported, at the same severities)
  • Node: n/prefer-promises/fs, n/prefer-promises/dns, n/no-callback-literal, n/prefer-global/*
  • Plugins with no oxlint equivalent: simple-import-sort, eslint-comments, @stylistic (formatting is Prettier's job)

Restored in oxlint 1.59–1.75 (previously dropped): no-implied-eval, prefer-regex-literals, prefer-arrow-callback, no-unreachable-loop, typescript/method-signature-style, object-shorthand, import/newline-after-import, import/prefer-default-export, react/function-component-definition, react/hook-use-state, react/no-unstable-nested-components.