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

classpresso

v1.7.2

Published

CSS class consolidation tool - compress multiple utility classes into single optimized classes

Readme

Classpresso

Make utility-first CSS render faster — 50% faster style recalculation, 42% faster First Paint

Classpresso consolidates repeated utility class patterns at build time, dramatically reducing browser rendering work. Works with Tailwind, Bootstrap, Bulma, Tachyons, UnoCSS, and any utility-first CSS framework.

📦 Post-Build Tool — Your Development Workflow is Unchanged

Classpresso runs after your build (npm run build), not during development. Your source code is never modified — only the compiled output in .next, dist, build, etc. You'll always see your normal Tailwind/utility classes while developing and debugging.

Performance Results

| Metric | Improvement | |--------|-------------| | Style Recalculation | 50% faster | | First Paint | 42% faster | | Memory Usage | 21% less | | Runtime Overhead | 0ms |

Benchmarks run on 1000 complex components with Playwright + Chrome DevTools Protocol

The Problem

Utility-first CSS means elements with 10-20+ classes:

<button class="inline-flex items-center justify-center rounded-md text-sm font-medium
               transition-colors focus-visible:outline-none focus-visible:ring-2
               bg-primary text-white hover:bg-primary/90 h-10 px-4 py-2">
  Submit
</button>

Every class on every element is work for the browser:

  • Parse the class string
  • Look up each class in stylesheets
  • Calculate specificity and resolve conflicts
  • Compute final styles

With 15 classes × 500 elements = 7,500 class lookups per page load.

The Solution

Classpresso finds repeated patterns and consolidates them:

Before:

<button class="inline-flex items-center justify-center rounded-md text-sm font-medium...">Submit</button>
<button class="inline-flex items-center justify-center rounded-md text-sm font-medium...">Cancel</button>
<button class="inline-flex items-center justify-center rounded-md text-sm font-medium...">Delete</button>

After:

<button class="cp-btn bg-primary">Submit</button>
<button class="cp-btn bg-secondary">Cancel</button>
<button class="cp-btn bg-destructive">Delete</button>

Generated CSS:

.cp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* ... all consolidated utilities */
}

Result: Fewer classes = less browser work = faster rendering.

Installation

npm install classpresso --save-dev

Quick Start

# Build your project first
npm run build

# Analyze potential savings
npx classpresso analyze

# Apply optimizations
npx classpresso optimize

Framework Compatibility

CSS Frameworks

| Framework | Classes per Element | Performance Gain | |-----------|---------------------|------------------| | Tailwind CSS | 10-20+ typical | Excellent | | Bootstrap | 5-15 typical | Good | | Bulma | 5-10 typical | Good | | Tachyons | 15-25+ typical | Excellent | | UnoCSS | 10-20+ typical | Excellent | | Any utility CSS | Varies | Automatic |

Build Frameworks

Classpresso works with 20+ frameworks out of the box:

| Framework | Build Directory | SSR Flag | Notes | |-----------|-----------------|----------|-------| | React Meta-Frameworks | | Next.js | .next (default) | --ssr for App Router | Pages Router usually doesn't need SSR flag | | Remix | build | --ssr recommended | | | Gatsby | public | Not needed | Static only | | RedwoodJS | web/dist | --ssr if using SSR | | | Vue Meta-Frameworks | | Nuxt 3 | .output | --ssr recommended | | | VitePress | .vitepress/dist | Not needed | Static docs | | Gridsome | dist | Not needed | Static only | | Svelte | | SvelteKit | build | --ssr recommended | Or .svelte-kit | | Other Frameworks | | Astro | dist | --ssr for islands | Static doesn't need SSR | | Solid Start | .output or dist | --ssr recommended | | | Qwik | dist | --ssr recommended | | | Angular | dist/[project-name] | Not needed | Angular 17+ uses browser/ subdir | | Ember | dist | Not needed | | | Preact | build or dist | Depends on setup | | | Generic Bundlers | | Vite | dist | Depends on framework | | | Webpack | dist | Not needed | | | Parcel | dist | Not needed | | | Create React App | build | Not needed | | | Static Site Generators | | Eleventy (11ty) | _site | Not needed | | | Hugo | public | Not needed | | | Docusaurus | build | Not needed | |

Zero code changes required. Classpresso runs on your build output. Your React, Vue, Svelte, Solid, Qwik, Astro, Angular, or vanilla HTML stays exactly the same.

How It Works

1. You run your normal build (next build, vite build, etc.)

2. Classpresso scans the output:
   → Finds all class attributes
   → Identifies patterns that repeat
   → Calculates which are worth consolidating

3. Classpresso transforms:
   → Replaces repeated patterns with short hash classes
   → Generates CSS that maps hashes to original utilities
   → Updates HTML/JS with new class names

4. Result:
   → Same visual appearance
   → Dramatically fewer class lookups
   → Faster style recalculation on every interaction

CLI Commands

classpresso analyze

Analyze build output and show potential optimizations without modifying files.

classpresso analyze --dir .next
classpresso analyze --min-occurrences 3 --min-classes 3
classpresso analyze --json

Options:

  • -d, --dir <path> - Build directory (default: .next)
  • --min-occurrences <n> - Minimum times a pattern must appear (default: 2)
  • --min-classes <n> - Minimum classes in a pattern (default: 2)
  • --ssr - Enable SSR-safe mode for hydration compatibility
  • --json - Output as JSON
  • -v, --verbose - Verbose output
  • --debug - Generate detailed debug log file for troubleshooting
  • --send-error-reports - Send error reports to configured webhook
  • --error-report-url <url> - Webhook URL for error reports

classpresso optimize

Apply optimizations to the build output.

classpresso optimize --dir .next
classpresso optimize --dry-run
classpresso optimize --backup

Options:

  • -d, --dir <path> - Build directory (default: .next)
  • --min-occurrences <n> - Minimum times a pattern must appear (default: 2)
  • --min-classes <n> - Minimum classes in a pattern (default: 2)
  • --ssr - Enable SSR-safe mode for hydration compatibility
  • --dry-run - Show what would be done without making changes
  • --backup - Create backup files before modifying
  • --no-manifest - Don't generate manifest file
  • -v, --verbose - Verbose output
  • --debug - Generate detailed debug log file for troubleshooting
  • --send-error-reports - Send error reports to configured webhook
  • --error-report-url <url> - Webhook URL for error reports

classpresso report

Generate a report from an existing manifest.

classpresso report --dir .next
classpresso report --format json
classpresso report --format html > report.html

Options:

  • -d, --dir <path> - Build directory (default: .next)
  • --format <type> - Output format: text, json, html (default: text)

Integration Examples

Next.js

{
  "scripts": {
    "build": "next build && classpresso optimize",
    "build:analyze": "next build && classpresso analyze"
  }
}

Vite

{
  "scripts": {
    "build": "vite build && classpresso optimize --dir dist"
  }
}

Create React App

{
  "scripts": {
    "build": "react-scripts build && classpresso optimize --dir build"
  }
}

Astro

Classpresso fully supports Astro static, SSR, and hybrid builds.

Static Build (default):

{
  "scripts": {
    "build": "astro build && classpresso optimize --dir dist"
  }
}

SSR/Hybrid Build (with React/Vue/Svelte islands):

{
  "scripts": {
    "build": "astro build && classpresso optimize --dir dist --ssr"
  }
}

Configuration file:

// classpresso.config.js
module.exports = {
  buildDir: 'dist',
  // Use --ssr flag if you have interactive islands with client:* directives
  ssr: false,
};

Classpresso automatically detects Astro's build structure:

  • dist/**/*.html - Static HTML pages
  • dist/_astro/**/*.js - Client-side JavaScript
  • dist/_astro/**/*.css - Compiled CSS
  • dist/server/**/*.mjs - Server code (SSR mode)
  • dist/client/_astro/**/* - Client assets (SSR mode)

Nuxt 3

{
  "scripts": {
    "build": "nuxt build && classpresso optimize --dir .output --ssr"
  }
}

SvelteKit

{
  "scripts": {
    "build": "vite build && classpresso optimize --dir build --ssr"
  }
}

Remix

{
  "scripts": {
    "build": "remix build && classpresso optimize --dir build --ssr"
  }
}

Solid Start

{
  "scripts": {
    "build": "vinxi build && classpresso optimize --dir .output --ssr"
  }
}

Qwik

{
  "scripts": {
    "build": "qwik build && classpresso optimize --dir dist --ssr"
  }
}

Angular

{
  "scripts": {
    "build": "ng build && classpresso optimize --dir dist/my-app"
  }
}

For Angular 17+, the output is in dist/[project-name]/browser.

Gatsby

{
  "scripts": {
    "build": "gatsby build && classpresso optimize --dir public"
  }
}

Eleventy (11ty)

{
  "scripts": {
    "build": "eleventy && classpresso optimize --dir _site"
  }
}

Hugo

hugo && classpresso optimize --dir public

Docusaurus

{
  "scripts": {
    "build": "docusaurus build && classpresso optimize --dir build"
  }
}

VitePress

{
  "scripts": {
    "build": "vitepress build && classpresso optimize --dir .vitepress/dist"
  }
}

SSR-Safe Mode

For Next.js App Router, Remix, or any SSR framework with hydration, use the --ssr flag to prevent hydration mismatches:

classpresso optimize --ssr

What it does

SSR-safe mode only consolidates patterns that appear in both server-rendered HTML and client-side JavaScript. This ensures the browser sees identical class names during hydration.

Without --ssr: A pattern in HTML might get consolidated, but the JavaScript bundle still references the original classes → hydration mismatch error.

With --ssr: Only patterns found in both places are consolidated → perfect hydration.

When to use

Use --ssr for these frameworks:

  • Next.js App Router - Always recommended
  • Nuxt 3 - Recommended
  • SvelteKit - Recommended
  • Remix - Recommended
  • Solid Start - Recommended
  • Qwik - Recommended
  • Astro SSR/Hybrid - If using client:* directives with React/Vue/Svelte islands
  • RedwoodJS - If using SSR features

SSR flag NOT needed:

  • Next.js Pages Router - Different hydration model
  • Astro Static - No hydration
  • Gatsby - Static generation
  • Eleventy (11ty) - Static only
  • Hugo - Static only
  • VitePress - Static docs
  • Docusaurus - Static docs
  • Angular - Client-side rendering
  • Ember - Client-side rendering
  • Static sites (plain HTML) - No hydration

Configuration

// classpresso.config.js
module.exports = {
  ssr: true, // Enable SSR-safe mode
};

Debug Mode

When troubleshooting issues, enable debug mode to generate a detailed log file:

classpresso optimize --debug

This creates classpresso-debug.log in your build directory containing:

  • System info: Node version, OS, platform
  • Config resolution: Final merged config values
  • Operation trace: Every step with timestamps and timing
  • Error details: Full stack traces if errors occur

The log file location is displayed when the command completes. Share this file when reporting issues.

Error Reporting

Opt-in to automatically send error reports to help improve classpresso:

classpresso optimize --send-error-reports --error-report-url https://your-webhook.com/errors

Or configure in classpresso.config.js:

module.exports = {
  sendErrorReports: true,
  errorReportUrl: 'https://your-webhook.com/errors',
};

Privacy: Error reports only include:

  • Classpresso version, Node version, OS
  • Error message and stack trace
  • Non-sensitive config values (thresholds, flags)

Excluded: Full file paths, project structure, class names

Configuration

Create a classpresso.config.js file in your project root:

module.exports = {
  // Build directory
  buildDir: '.next',

  // Consolidation thresholds
  minOccurrences: 2,    // Pattern must appear at least 2 times
  minClasses: 2,        // Pattern must have at least 2 classes
  minBytesSaved: 10,    // Must save at least 10 bytes

  // Hash configuration
  hashPrefix: 'cp-',    // Prefix for consolidated classes
  hashLength: 5,        // Hash length (5 = 1M+ unique combinations)

  // Classes to exclude from consolidation (safelist)
  exclude: {
    prefixes: ['js-', 'data-', 'hook-', 'track-'],
    suffixes: ['-handler', '-trigger'],
    classes: ['no-consolidate'],
    patterns: [/^qa-/, /^test-/, /^e2e-/],
  },

  // CSS output options
  cssLayer: false,      // Wrap in @layer (e.g., 'utilities') or false for none

  // SSR & Hydration
  ssr: false,           // Enable SSR-safe mode for hydration compatibility

  // Debug options
  dataAttributes: false, // Add data-cp-original attribute with original classes
  debug: false,          // Generate detailed debug log file

  // Error reporting (opt-in)
  sendErrorReports: false,           // Send error reports to webhook
  errorReportUrl: undefined,         // Webhook URL (HTTPS required)

  // Output options
  manifest: true,       // Generate manifest.json
  backup: false,        // Create .bak files
};

Benchmark Methodology

Tests run using Playwright with Chrome DevTools Protocol:

Test Environment
────────────────────────────────────────────────────
Browser: Chromium (headless)
CPU: Throttled 4x (simulates mobile)
Metrics: Performance.getMetrics() API

Test Pages
────────────────────────────────────────────────────
500 components: ~26,500 class instances
1000 components: ~53,000 class instances

Each component contains:
- Card container (8 classes)
- Header (12 classes)
- Button (15 classes)
- Badge (6 classes)
- Input (12 classes)

Run benchmarks yourself:

npm run benchmark

Example Output

╔═══════════════════════════════════════════════════════════╗
║                   CLASSPRESSO RESULTS                     ║
╠═══════════════════════════════════════════════════════════╣
║ Files Scanned:                                         45 ║
║ Files Modified:                                        12 ║
╠═══════════════════════════════════════════════════════════╣
║ CLASS CONSOLIDATION                                       ║
║ Patterns found:                                       234 ║
║ Patterns consolidated:                                 67 ║
║ Total occurrences replaced:                           834 ║
╠═══════════════════════════════════════════════════════════╣
║ BROWSER PERFORMANCE IMPACT                                ║
║ Class lookups eliminated:                          12,510 ║
║ Estimated style recalc improvement:                  ~50% ║
║ Estimated First Paint improvement:                   ~42% ║
╠═══════════════════════════════════════════════════════════╣
║ BONUS: SIZE REDUCTION                                     ║
║ HTML bytes saved:                                12,450 B ║
║ CSS overhead:                                     3,200 B ║
║ Net reduction:                                    9,250 B ║
╚═══════════════════════════════════════════════════════════╝

API Usage

Use Classpresso programmatically:

import {
  loadConfig,
  scanBuildOutput,
  detectConsolidatablePatterns,
  createClassMappings,
  generateConsolidatedCSS,
  transformBuildOutput,
} from 'classpresso';

async function optimize() {
  const config = await loadConfig('.next');

  // Scan for patterns
  const scanResult = await scanBuildOutput(config);

  // Detect consolidation candidates
  const candidates = detectConsolidatablePatterns(
    scanResult.occurrences,
    config
  );

  // Create mappings
  const mappings = createClassMappings(candidates);

  // Generate CSS
  const css = await generateConsolidatedCSS(mappings, config.buildDir, config.cssLayer);

  // Transform build
  await transformBuildOutput(mappings, config);
}

FAQ

Does this affect my development workflow?

No. Classpresso is a post-build tool that only runs after npm run build. During development (npm run dev), you see your normal Tailwind/utility classes exactly as you wrote them — perfect for debugging and toggling classes in DevTools. Classpresso only transforms the compiled production output.

Why does this make sites faster?

Every CSS class is work for the browser. With utility-first CSS, a button might have 15+ classes. Classpresso consolidates repeated patterns so there's less to parse, match, and calculate.

What about bundle size?

That's a bonus! HTML typically drops 50-60%. But the real win is browser performance — style recalculation happens on every page load, every DOM change, every interaction. 50% faster there is huge.

Do I need to change my code?

No. Classpresso runs on your build output, not source code. Your components stay exactly the same.

Is there runtime overhead?

Zero. Classpresso is build-time only. No JavaScript added, no runtime processing.

License

MIT

Links