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

expo-config-oxlint

v0.2.0

Published

Oxlint preset for Expo apps: Expo's oxlint-config-universe/native plus the React Compiler rules (eslint-plugin-react-hooks) and Expo's lint rules via Oxlint JS plugins

Readme

expo-config-oxlint

Oxlint preset for Expo apps. Extends Expo's own oxlint-config-universe/native and layers in the full eslint-plugin-react-hooks v7 rule set (including the React Compiler rules: immutability, purity, refs, set-state-in-effect, preserve-manual-memoization, ...) and the eslint-plugin-expo rules — loaded through Oxlint JS plugins.

The goal: the enforcement of eslint-config-expo at oxlint speed. On a mid-size Expo app (~65 components), the full pass — compiler rules included — runs about 2× faster than ESLint, and the native-rule portion is near-instant.

Status: bridge package

Expo is migrating its own monorepo to oxlint/oxfmt, but eslint-config-expo (the app-facing config) and the official docs are still ESLint. oxlint-config-universe now exposes native Oxlint ports of most React hooks/compiler rules; this package deliberately uses the React team's JS-plugin implementations instead, disables the native overlaps, and adds the remaining React and Expo rules. It bridges the gap until Expo ships official app-facing oxlint support — at which point you should switch to theirs (and this README will say so in bold).

Also note: Oxlint JS plugins are alpha. The wiring here is conformance-tested (see test/), but expect the occasional breakage on oxlint upgrades. Pin your oxlint version.

Install

npm install --save-dev expo-config-oxlint oxlint

Use

Create oxlint.config.mjs at your project root:

import { defineConfig } from "oxlint";
import expo from "expo-config-oxlint";

export default defineConfig({
  ...expo,
  // your overrides here
});

Run it:

npx oxlint

Composing with your own base

If you only want the JS-plugin wiring (react-hooks + expo rules) on top of a different base config, use the jsPluginConfig fragment:

import { defineConfig } from "oxlint";
import native from "oxlint-config-universe/native";
import { jsPluginConfig } from "expo-config-oxlint";

export default defineConfig({
  ...native,
  ...jsPluginConfig,
  rules: { ...native.rules, ...jsPluginConfig.rules },
});

Softening the compiler rules

The react-hooks rules ship at the severities of the plugin's own recommended-latest config (most compiler rules are error). Animation-heavy React Native code (Reanimated shared values, gesture worklets) triggers them legitimately — downgrade or disable per rule:

export default defineConfig({
  ...expo,
  rules: {
    ...expo.rules,
    "react-hooks-js/immutability": "warn",
  },
});

What's included

| Layer | Source | Rules | |---|---|---| | Oxlint native rules for RN/Expo | oxlint-config-universe/native (Expo-maintained) | eslint core, typescript, react, jsx-a11y, ... | | React hooks + React Compiler | eslint-plugin-react-hooks@7 via JS plugin, namespace react-hooks-js | all 17 recommended-latest rules; overlapping native Oxlint ports are disabled | | Expo rules | eslint-plugin-expo via JS plugin, namespace expo-js | use-dom-exports, no-env-var-destructuring, no-dynamic-env-var (the set eslint-config-expo enables) | | React Native style rules (opt-in) | oxlint-plugin-react-native, namespace react-native | no-inline-styles, no-unused-styles, no-single-element-style-arrays via the reactNativeConfig fragment |

All plugins are dependencies of this package, so they resolve even if your app has no ESLint installed at all.

Opt-in: React Native style rules

eslint-config-expo doesn't enable eslint-plugin-react-native's style rules, so neither does this preset by default. If your ESLint setup added them (common in Ignite-derived apps), compose the fragment — it uses a native Oxlint port with the same react-native/... rule names, so existing disable comments keep working:

import { defineConfig } from "oxlint";
import expo, { reactNativeConfig } from "expo-config-oxlint";

export default defineConfig({
  ...expo,
  jsPlugins: [...expo.jsPlugins, ...reactNativeConfig.jsPlugins],
  rules: { ...expo.rules, ...reactNativeConfig.rules },
});

What's NOT included (gaps vs eslint-config-expo)

Be aware of these before deleting ESLint:

  • import/order — no oxlint implementation. Expo's answer is oxfmt's sortImports; use that (or keep Prettier + an import-sorting plugin).
  • Prettier integration (prettier/prettier as a lint rule) — run prettier --check as a separate step, or switch to oxfmt.
  • A handful of eslint core rules oxlint-config-universe documents as uncovered.

If any of these are load-bearing for you, run a slimmed ESLint config alongside oxlint for just those rules (use eslint-plugin-oxlint to turn off everything oxlint already covers).

Pairs well with: anti-slop

anti-slop is a set of opinionated, generic TypeScript Oxlint rules (no unknown params/returns, no Record<string, unknown>, a // SAFETY: comment on every as, no jest.mock, ...). It is deliberately not part of this preset — it isn't Expo- or RN-specific, and its author intends it to be vendored and edited per repo rather than depended on. Install it into your app alongside this preset with:

npx skills add dmmulroy/anti-slop --skill install-anti-slop

Expect these rules to fire on ordinary Expo/RN code — soften or disable them per project:

  • anti-slop/no-module-mocking — jest.mock("expo-*") / jest.mock("react-native-reanimated") is standard in jest-expo tests.
  • anti-slop/no-conditional-empty-object-spread — ...(Platform.OS === "ios" ? { ... } : {}) in styles/props.
  • anti-slop/no-runtime-typeof — typeof window !== "undefined" web-platform guards.
  • anti-slop/require-safety-comment-for-type-assertion — route.params as X and friends.

Migrating existing eslint-disable comments

Because Oxlint reserves the react-hooks namespace, this preset loads the plugin as react-hooks-js. Your existing inline suppressions name the old rule, so they will NOT suppress — every previously-triaged violation resurfaces on first run (which doubles as a nice audit). Rewrite them:

# macOS sed; drop the '' on Linux
grep -rl "eslint-disable-next-line react-hooks/" src app | \
  xargs sed -i '' 's|eslint-disable-next-line react-hooks/|oxlint-disable-next-line react-hooks-js/|g'

(Using oxlint-disable rather than eslint-disable keeps the two linters' suppressions independent if you run both during a transition.)

Conformance

npm test lints fixture files with known violations through the real published packages and asserts each layer fires: rules-of-hooks, exhaustive-deps, the compiler rules (set-state-in-render, set-state-in-effect), and the expo rules (no-dynamic-env-var, no-env-var-destructuring) — while asserting native ports do not duplicate them, plus a clean file that must produce zero diagnostics.

License

MIT