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

eslint-immersive

v7.7.0

Published

Complete ESLint configuration bundle — stylistic rules, import ordering, alignment, and assignment formatting in one plugin.

Readme

eslint-immersive

This is an extremely opinionated ESLint configuration. It is not a starting point to tweak — it is a finished, self-consistent code style enforced end to end. Tabs for indentation, single quotes, no semicolons, aligned from keywords, aligned assignment =, aligned object colons. If you disagree with any of those, this bundle is almost certainly not for you, and that is by design. There are no options to soften it. Install it only if you want this style, exactly, with zero configuration.

A complete, batteries-included ESLint setup for TypeScript projects. One dependency, one import, a fully opinionated style enforced and auto-fixable.

Why

Most style configs leave dozens of decisions open and end up re-litigated in every code review. This one makes every decision for you and enforces it mechanically, so reviews are about behavior, not whitespace. The trade-off is deliberate: no knobs, strong opinions, consistency over preference.

Requirements

  • ESLint >= 10
  • TypeScript >= 5
  • jiti >= 2 (required by ESLint to load a TypeScript eslint.config.ts)
  • settings.tailwindcss.cssConfigPath in your own config — mandatory, see below. Without it, eslint does not just report a lint error: it crashes the entire run (uncaught ENOENT from tailwindcss/classnames-order) the first time it lints any file.

Installation

npm install --save-dev eslint-immersive eslint jiti typescript

Then, in the same config array as immersive, point the plugin at your Tailwind v4 CSS entry file:

export default [
	...immersive,
	{ settings: { tailwindcss: { cssConfigPath: './src/app.css' } } },
]

This is the one required setting the bundle cannot supply for you (the path is project-specific). Skipping it is not a style violation you can ignore — eslint will not run at all.

Usage

Flat config only (eslint.config.ts):

import type { Linter } from 'eslint'

import immersive from 'eslint-immersive'

const config: Linter.Config[] = [
	{ ignores: ['.next/**', 'build/**', 'next-env.d.ts', 'node_modules/**', 'out/**'] },
	...immersive,
] satisfies Linter.Config[]

export default config

That is the entire setup. The bundle ships the parser, plugins, and every rule pre-wired.

What it enforces

Formatting (@stylistic)

  • Tabs for indentation
  • Single quotes, no semicolons
  • Trailing commas on multiline
  • Spaces inside array/object brackets
  • At most one consecutive blank line; blank line required before return
  • No multiple spaces (except the alignment cases below)
  • Exactly one trailing newline at the end of every file (eol-last)
  • No space just inside call/grouping parens — fn(a, b), never fn( a, b ) (space-in-parens)
  • One space before the /> of a self-closing JSX tag — <Foo />, never <Foo/> (jsx-tag-spacing)

Alignment (custom rules)

  • import-alignment/space — aligns the from keyword across each import group (groups are separated by blank lines). Side-effect imports (import './x.css') are left untouched.

  • import-assignment/space — aligns = across consecutive variable declarations, and aligns type-annotation colons when two or more typed declarations sit together.

  • immersive/key-align — aligns object-literal, interface, and type-literal colons using spaces (key : value), including nested and optional (?:) members.

  • immersive/call-align — aligns the 2nd argument across consecutive same-object member-call statements, e.g. route/middleware registration:

    hono.use('/service/track/*',    authentication)
    hono.use('/service/waybills/*', authentication)
    
    hono.route('/service/areas',   createAreas({ database, cache, provider }))
    hono.route('/service/captive', createCaptive({ database, cache }))

    Only fires for a run of consecutive-line statements calling the same object (hono.use / hono.route / …) with 2+ arguments; unrelated calls break the group.

    This alignment needs a CallExpression exception on @stylistic/no-multi-spaces (already wired into the bundle) — without it the two rules fight over the inserted spaces and neither converges. One side effect: no-multi-spaces no longer flags accidental double-space typos inside any call's arguments, not just aligned ones.

Import ordering (import-arrangement/order)

type → builtin → external → internal

import type is always hoisted to the top of the file. hono and every hono/* subpath (e.g. hono/router/reg-exp-router) share a single pathGroup, so they land in one consecutive block with no blank line forced between them.

Tailwind class sorting (tailwindcss/classnames-order)

Sorts Tailwind classes in class/className attributes and in classNames/clsx/cn/cva/tv/twMerge/twJoin/ctl/tw calls, using eslint-plugin-tailwindcss. This rule requires a project-specific setting the bundle cannot guess — add it in your own config alongside immersive:

import immersive from 'eslint-immersive'

export default [
	...immersive,
	{ settings: { tailwindcss: { cssConfigPath: './src/app.css' } } },
]

Without cssConfigPath pointing at your Tailwind v4 CSS entry file, the rule cannot resolve your class list and sorting will not run correctly.

Customization

There is intentionally very little. If you must override a single rule, spread the bundle first and set your rule last — but understand that doing so opts out of the guarantee this config exists to provide:

import immersive from 'eslint-immersive'

export default [
	...immersive,
	{ rules: { '@stylistic/quotes': ['error', 'double'] } },
]

License

MIT