The world of NPM is massive. Over 2 million packages, and yet, most developers end up using the same 20-30 over and over again.
React, Lodash, Express. The usual suspects.
But what about the hidden gems? The ones that could make your workflow easier, cleaner, and smarter?
Here are five underrated NPM packages that deserve more attention.
1. date-fns-tz
Time zones are annoying. This makes them less so.
If you’ve ever scheduled an event across time zones, you know how quickly things get messy. Moment.js? Bloated. Manually handling offsets? A disaster waiting to happen.
Enter date-fns-tz
.
Why it deserves more love:
- Built on
date-fns
, so it’s modular and tree-shakable. - Does one thing well: time zone management.
- No unnecessary overhead.
Where it helps:
When you’re building apps that handle scheduling for users in different time zones.
Example:
import { formatInTimeZone } from 'date-fns-tz';
const timeZone = 'America/New_York';
const date = new Date();
const formattedDate = formatInTimeZone(date, timeZone, 'yyyy-MM-dd HH:mm:ssXXX');
console.log(formattedDate); // 2024-11-25 10:00:00-05:00
2. clsx
Writing messy className logic? Stop. Use this.
If you’ve written dynamic className
logic in React, you’ve probably seen something like this:
const buttonClass = `btn ${isActive ? 'btn-active' : ''} ${isDisabled ? 'btn-disabled' : ''}`;
It works. But it’s ugly.
Enter clsx
. A tiny utility that makes class name logic elegant.
Why you need this:
- Handles conditional logic, arrays, and objects effortlessly.
- Automatically ignores falsy values.
- Makes your UI code cleaner and more readable.
Example:
import clsx from 'clsx';
const isActive = true;
const isDisabled = false;
const buttonClass = clsx('btn', { 'btn-active': isActive, 'btn-disabled': isDisabled });
console.log(buttonClass); // "btn btn-active"
3. ow
Validation that doesn’t make you want to quit coding.
If you’ve written input validation manually, you know it gets repetitive fast.
ow
, by Sindre Sorhus, makes it simple and declarative.
Why it’s underrated:
- TypeScript-friendly with strong error messages.
- Expressive syntax that reads like English.
- Handles complex validations in a single line.
Where it helps:
Validating API responses, CLI inputs, or function arguments.
Example:
import ow from 'ow';
const validateUser = (user) => {
ow(user, ow.object.exactShape({
name: ow.string.minLength(3),
age: ow.number.integer.positive,
email: ow.string.url,
}));
};
validateUser({ name: 'John', age: 25, email: 'example@example.com' }); // Passes
4. npm-check
Your node_modules is a mess. This fixes it.
Have you ever wondered:
- Which dependencies are outdated?
- Which ones are unused?
- Which ones you accidentally forgot to install?
npm-check
gives you an interactive way to clean things up.
Why it’s useful:
- Finds outdated, unused, or missing dependencies.
- Works interactively, so you can update/uninstall with a keystroke.
- Works with both local and global packages.
Example:
npx npm-check
Run that command, and you’ll get a nice interactive list of dependencies with options to update or remove them.
5. log-symbols
Make your CLI logs actually readable.
Ever built a CLI tool and thought, this looks so plain?
log-symbols
adds intuitive icons (✅ ❌ ⚠️) to your logs, making them clearer at a glance.
Why you should use it:
- Gives instant visual feedback in the terminal.
- Works across macOS, Linux, and Windows.
- Small but powerful.
Example:
import logSymbols from 'log-symbols';
console.log(logSymbols.success, 'Build completed successfully!');
console.log(logSymbols.error, 'Failed to connect to the database.');
console.log(logSymbols.warning, 'Using default configuration.');
Don’t just use what’s popular. Use what makes your life easier.
The next time you find yourself repeating code or struggling with a common problem, take a detour into the lesser-known corners of NPM.
What’s your favorite underrated NPM package?
Top comments (2)
I always use classnames to manage dynamic className logic in React. I compared clsx and classnames; their functions are similar, but clsx is smaller in size than classnames. I will use clsx instead of classnames in my next project. Thank you, this is helpful for me!
Recently I abandoned one of my side projects because I couldn't solve timezone variations by using moment.js library. I will try date-fns-tz and see how it goes.