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

tailwind-groupify

v0.1.2

Published

Build-time Tailwind CSS class deduplication for JSX and TSX.

Readme

⚡ tailwind-groupify

Automatically extract repeated TailwindCSS utility combinations into shared generated classes, reducing HTML/JSX size and keeping large codebases easier to maintain - with zero runtime cost.

Large Tailwind codebases often repeat the same utility combinations hundreds of times:

  • flex items-center justify-center
  • grid gap-4
  • text-sm font-medium

tailwind-groupify detects these patterns across your project, extracts them into generated classes using @apply, and rewrites your markup automatically.

Benefits

  • Deduplicates repeated utility classes
  • Reduces HTML and JSX output size
  • Extracts shared utility patterns across files
  • Generates reusable classes at build time
  • Adds zero runtime overhead

Turn this:

<div className="flex items-center justify-center p-4 bg-red-500" />
<div className="flex items-center justify-center p-2 bg-blue-500" />

Into this:

<div className="p-4 bg-red-500 twg-0" />
<div className="p-2 bg-blue-500 twg-0" />

With generated CSS:

.twg-0 {
  @apply flex items-center justify-center;
}

🚀 Why use tailwind-groupify?

  • 📦 Reduce HTML + JSX size
  • 🔁 Deduplicate repeated Tailwind patterns
  • ⚡ Zero runtime cost
  • 🧠 Works across your entire codebase
  • 🧼 Keep repeated utility patterns easier to manage

✨ Features

  • 🔍 AST-based analysis (safe transforms)
  • 🧩 Multi-file pattern extraction
  • 🔥 Pair + triple grouping (Apriori-lite)
  • ⚡ Incremental builds (fast)
  • 🧠 Tailwind-aware (@apply)
  • 🛡️ Order-safe mode (important!)
  • ⚙️ Configurable thresholds
  • 🏷️ Configurable generated class prefix
  • ⚡ Vite plugin
  • ▲ Next.js plugin

Status: early release. Use on a branch first and review generated diffs before adopting in production.


📦 Install

npm install tailwind-groupify

⚡ Vite Usage

vite.config.js

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import twGroupify from "tailwind-groupify/vite";

export default defineConfig({
  plugins: [
    react(),
    twGroupify({
      include: ["src/**/*.{jsx,tsx}"],
    }),
  ],
});

Import generated CSS

import "virtual:tw-groupify.css";

▲ Next.js Usage

next.config.js

const withTWGroupify = require("tailwind-groupify/next");

module.exports = withTWGroupify({}, {
  include: ["src/**/*.{jsx,tsx}"],
  cssOutput: "tw-groupify.css",
});

Then import the generated CSS once from your app entry point:

import "../tw-groupify.css";

⚙️ Configuration

Create tw-groupify.config.js:

module.exports = {
  minGroupSize: 2,
  minOccurrences: 2,
  maxCombinationSize: 3,
  classPrefix: "twg-",

  // Important when Tailwind utility order matters.
  preserveOrder: true,

  // Optional glob ignores used by the CLI and Vite plugin.
  ignorePatterns: [],

  // optional
  debug: false,
};

🧪 Examples

Basic Deduplication

Input

<div className="flex items-center justify-center p-4" />
<div className="flex items-center justify-center p-2" />

Output

<div className="p-4 twg-0" />
<div className="p-2 twg-0" />

Works Across Files

// Button.jsx
<button className="flex items-center justify-center px-4 py-2" />

// Card.jsx
<div className="flex items-center justify-center p-6" />

→ Shared group extracted globally.


Dynamic Classes

<div className={`p-4 ${active ? "bg-red-500" : ""}`} />

→ Left unchanged. Dynamic class expressions are skipped so runtime behavior is not changed.


Order Safety

<div className="hover:bg-red-500 bg-blue-500" />

With:

preserveOrder: true

→ Preserves utility order while selecting repeated groups. Review generated diffs when classes intentionally conflict.


📊 Metrics

When enabled, shows:

  • Total class strings analyzed
  • Groups extracted
  • Bytes saved (approx)
  • Compression ratio

🧠 How it works

  1. Parse JSX/TSX using AST
  2. Extract className strings
  3. Find frequent class combinations
  4. Replace with short aliases
  5. Generate CSS using @apply

⚠️ Limitations

  • Dynamic classNames are skipped
  • Tailwind order matters (use preserveOrder)
  • Turbopack support is experimental

🛣️ Roadmap

  • Dev overlay
  • Analyzer UI
  • Next.js Turbopack support
  • Source maps

🤝 Contributing

PRs welcome!


📄 License

MIT