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

unique-filenames-fnc

v1.0.0

Published

Assert globally unique filenames across your project. Configurable per folder, extension and exclusion rules.

Readme

unique-filenames-fnc

A File Naming Convention (FNC) enforcement tool that asserts globally unique filenames across your project. Duplicate filenames — even in different folders — are caught before they cause confusion in stack traces, IDE search, and auto-imports. Configurable per folder with glob and gitignore-style pattern support. Exits with code 1 when duplicates are found, or run in --warn mode for gradual adoption on existing projects.

Why?

As projects scale, naming files by role alone — Modal.js, utils.js, api.js — leads to collisions. Multiple files sharing the same name across different folders create subtle but persistent maintenance problems:

  • Stack traces reference Modal.js:42 with no indication of which one
  • IDE file search returns multiple matches — wrong file gets opened
  • Refactor rename operates on one file, silently leaving duplicates untouched
  • Import paths become the only disambiguation — easy to import from the wrong location

A globally unique File Naming Convention eliminates this class of problem entirely. It also naturally improves naming quality — Modal.js, ConfirmModal.js and MediaModal.js are not just unique, they are genuinely more descriptive than three files all called Modal.js.

Install

npm install --save-dev unique-filenames-fnc

Usage

npx unique-filenames-fnc

Add to your scripts and run as part of CI:

{
    "scripts": {
        "unique-filenames-fnc": "unique-filenames-fnc"
    }
}

Configuration

Config is read from .unique-filenames-fnc.json in the project root, or from "unique-filenames-fnc" key in package.json. Supports a single config object or an array of objects — each is an independent scan with its own rules.

All params accept a single string or an array of strings.


Example 1 — scan entire project from root

The simplest setup. Omitting folders scans from the project root. Use exclude to skip generated folders and barrel files.

.unique-filenames-fnc.json:

{
    "extensions": [".js", ".ts", ".html", ".scss"],
    "exclude": ["node_modules", "dist", "out", ".git", "**/index.js", "**/index.ts", "**/*.d.ts"]
}

Example 2 — separate rules per folder

Different folders often have different conventions. A scripts/ folder only needs .js checked. An electron/ folder only has .ts. Splitting into multiple configs gives you precision.

.unique-filenames-fnc.json:

[
    {
        "folders": "src",
        "extensions": [".js", ".html", ".scss"],
        "exclude": ["node_modules", "dist", "**/index.js", "**/*.d.ts"]
    },
    {
        "folders": "electron",
        "extensions": ".ts",
        "exclude": ["node_modules", "**/index.ts", "**/*.d.ts"]
    },
    {
        "folders": "scripts",
        "extensions": ".js",
        "exclude": "**/index.js"
    }
]

Example 3 — monorepo with package globs

In a monorepo you want to check each package independently — duplicates within a package are fine, duplicates across packages are not.

.unique-filenames-fnc.json:

[
    {
        "folders": ["packages/ui/**", "packages/core/**"],
        "extensions": [".ts", ".tsx"],
        "exclude": ["node_modules", "**/index.ts", "**/*.d.ts", "**/*.test.ts"]
    },
    {
        "folders": "apps/**",
        "extensions": [".ts", ".tsx"],
        "exclude": ["node_modules", ".next", "dist", "**/*.d.ts"]
    }
]

Config reference

| Option | Type | Default | Description | |---|---|---|---| | folders | string \| string[] | (root) | Micromatch glob(s) for folders to scan. Omit to scan from project root. | | extensions | string \| string[] | [".js", ".ts"] | File extensions to check. | | exclude | string \| string[] | [] | Gitignore-style patterns — matched against full relative path. |


Exclude pattern semantics

Patterns follow the gitignore spec, implemented via the ignore package — the same library used by ESLint.

| Pattern | Meaning | |---|---| | node_modules | No slash — matches any file or folder with this name at any depth | | /dist | Leading slash — anchored to project root only, not nested src/dist | | dist/ | Trailing slash — matches directories only, not a file named dist | | *.d.ts | Wildcard — any .d.ts file at the current directory level | | **/*.d.ts | Double star — any .d.ts file at any depth | | **/index.js | Any index.js file at any depth | | src/generated/** | Everything inside src/generated/ |


CI integration

GitHub Actions

name: CI

on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - name: Assert unique filenames
        run: npm run unique-filenames-fnc

Bitbucket Pipelines

pipelines:
  default:
    - step:
        name: Assert unique filenames
        image: node:20
        caches:
          - node
        script:
          - npm ci
          - npm run unique-filenames-fnc

CLI options

--config <path>   Path to config file (default: .unique-filenames-fnc.json or package.json)
--warn, -w        Report duplicates as warnings — exits with code 0 instead of 1
--help, -h        Show help message

Warn mode

By default unique-filenames-fnc exits with code 1 when duplicates are found, failing the pipeline step. Use --warn to report duplicates without failing — useful when adopting the tool on an existing project that already has duplicates, or when you want visibility without blocking deploys.

unique-filenames-fnc --warn

In warn mode duplicates are printed with instead of and a summary line is added:

⚠ [src] — 1 duplicate(s):

  Button.js
    src/lib/Button/Button.js
    src/components/Toolbar/Button.js

⚠ 1 duplicate filename(s) found — running in warn mode, not failing.

GitHub Actions — warn mode

- name: Check unique filenames (warn only)
  run: npx unique-filenames-fnc --warn

Or configure a dedicated script:

{
    "scripts": {
        "unique-filenames-fnc:warn": "unique-filenames-fnc --warn"
    }
}

Bitbucket Pipelines — warn mode

- step:
    name: Check unique filenames (warn only)
    image: node:20
    caches:
      - node
    script:
      - npm ci
      - npx unique-filenames-fnc --warn

Example output

✗ [src] — 2 duplicate(s):

  Button.js
    src/lib/Button/Button.js
    src/components/Toolbar/Button.js

  utils.js
    src/lib/utils.js
    src/pages/Settings/utils.js

License

MIT