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

@jslibkit/tailwind-theme-engine

v1.0.5

Published

Dynamic runtime theming for Tailwind CSS using semantic CSS variable color scales.

Readme

tailwind-theme-engine

Dynamic theming for Tailwind CSS using semantic color classes and CSS variables.

<div class="bg-primary-500 text-primary-100"></div>

Themes can change at runtime, but Tailwind stays static. No Tailwind rebuild is needed when switching themes.

Prerequisites

  • Node.js 18 or newer
  • Tailwind CSS 3 or newer
  • React 18 or newer when using @jslibkit/tailwind-theme-engine/react
  • An ESM-compatible app or bundler

Recommended setup:

  • Tailwind v4: use theme.css plus generated theme CSS.
  • Tailwind v3: use the Tailwind preset plus generated theme CSS.
  • React apps: use generated themes with useThemeEngine.

Install

npm install @jslibkit/tailwind-theme-engine

During install, the package creates this file in your project if it does not already exist:

tailwind-theme-engine.config.js

Existing config files are never overwritten.

Local package testing:

npm install "D:\Projects\Bun\tailwind-theme-engine"

If npm fails with a Windows EPERM cache error:

npm install "D:\Projects\Bun\tailwind-theme-engine" --cache ./.npm-cache

Quick Start: React + Tailwind v4

Edit tailwind-theme-engine.config.js:

export const themeDefinitions = {
  purple: {
    label: "Purple",
    colors: {
      primary: "#8b5cf6",
      secondary: "#ec4899",
      tertiary: "#111827",
      success: "#22c55e",
      warning: "#f59e0b",
      info: "#0ea5e9",
      danger: "#ef4444"
    }
  },
  green: {
    label: "Green",
    colors: {
      primary: "#10b981",
      secondary: "#84cc16",
      tertiary: "#111827",
      success: "#22c55e",
      warning: "#f59e0b",
      info: "#0ea5e9",
      danger: "#ef4444"
    }
  }
};

Generate theme files:

npx tte build

This creates:

theme/
  purple.css
  purple.js
  green.css
  green.js
  index.js

Import Tailwind, the package color bridge, and one initial theme CSS file:

@import "tailwindcss";
@import "@jslibkit/tailwind-theme-engine/theme.css";
@import "../theme/purple.css";

Initialize the theme engine once before React renders:

import React from "react";
import ReactDOM from "react-dom/client";
import { initializeThemeEngine } from "@jslibkit/tailwind-theme-engine/react";
import { themes } from "../theme";
import "./index.css";
import App from "./App";

initializeThemeEngine({
  initialTheme: "purple",
  themes,
  storageKey: "app-theme"
});

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Use the theme state anywhere:

import { useThemeEngine } from "@jslibkit/tailwind-theme-engine/react";

export default function App() {
  const { themeName, setTheme } = useThemeEngine();

  return (
    <main className="min-h-screen bg-primary-50 p-8 text-primary-950">
      <button
        className="rounded-md bg-primary-500 px-4 py-2 text-white hover:bg-primary-600"
        onClick={() => setTheme(themeName === "purple" ? "green" : "purple")}
      >
        Switch Theme
      </button>
    </main>
  );
}

The imported CSS file gives instant first paint. The shared theme engine handles switching after the app loads.

Tailwind v4 Setup

In your app CSS:

@import "tailwindcss";
@import "@jslibkit/tailwind-theme-engine/theme.css";
@import "../theme/purple.css";

@jslibkit/tailwind-theme-engine/theme.css registers static Tailwind color tokens through @theme inline.

The generated theme CSS file provides initial CSS variable values:

:root {
  --primary-500: 133 88 238;
  --secondary-500: 232 72 153;
}

Tailwind v3 Setup

Create or update tailwind.config.js:

import preset from "@jslibkit/tailwind-theme-engine/preset";

export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  presets: [preset]
};

Then import one generated theme CSS file in your app CSS:

@import "../theme/purple.css";

Theme Config

tailwind-theme-engine.config.js should export themeDefinitions.

Each theme can be a plain color object or an object with label and colors.

export const themeDefinitions = {
  brand: {
    label: "Brand",
    colors: {
      primary: "#3b82f6",
      secondary: "#06b6d4",
      tertiary: "#111827",
      success: "#22c55e",
      warning: "#f59e0b",
      info: "#0ea5e9",
      danger: "#ef4444"
    }
  }
};

The library generates the full Tailwind-style shade scale:

50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950

Supported Color Names

Out of the box, Tailwind classes are registered for:

  • primary
  • secondary
  • tertiary
  • success
  • warning
  • info
  • danger

Examples:

<div class="bg-primary-500 text-primary-50"></div>
<button class="bg-secondary-600 hover:bg-secondary-700"></button>
<p class="text-tertiary-900"></p>
<div class="bg-warning-100 text-warning-800"></div>
<div class="bg-info-100 text-info-800"></div>
<p class="text-danger-600"></p>

Runtime CSS variables can be generated for any color name, but Tailwind classes only work for names registered in the Tailwind bridge.

Build Command

npx tte build

Options:

npx tte build --config tailwind-theme-engine.config.js
npx tte build --out-dir src/generated-themes
npx tte build --force

Behavior:

  • Reads theme definitions from config.
  • Creates one .css file per theme.
  • Creates one .js file per theme.
  • Creates index.js with named exports, themes, themeMetadata, and themeOptions.
  • Refuses to overwrite files unless --force is passed.

Generated JS usage:

import { themes, themeOptions } from "../theme";
import { green } from "../theme/green.js";

Generated CSS usage:

@import "../theme/purple.css";

If you remove a generated JS file, also remove its export from theme/index.js, or import individual generated files directly.

React Hook

import { useThemeEngine } from "@jslibkit/tailwind-theme-engine/react";

Recommended with generated themes:

import { initializeThemeEngine } from "@jslibkit/tailwind-theme-engine/react";
import { themes } from "../theme";

initializeThemeEngine({
  initialTheme: "purple",
  themes,
  storageKey: "app-theme"
});

Then use it anywhere:

import { useThemeEngine } from "@jslibkit/tailwind-theme-engine/react";

const { themeName, setTheme } = useThemeEngine();

The hook also supports runtime generation from base colors:

const { setTheme } = useThemeEngine({
  initialTheme: "brand",
  includeDefaultThemes: false,
  themeDefinitions: {
    brand: {
      primary: "#3b82f6",
      secondary: "#06b6d4",
      tertiary: "#111827",
      success: "#22c55e",
      warning: "#f59e0b",
      info: "#0ea5e9",
      danger: "#ef4444"
    }
  }
});

Use themes for production when possible. Use themeDefinitions when you want browser-side scale generation.

You do not need a React context provider. The React module keeps a small shared external store, so root initialization and later consumption are separate.

Hook options:

| Option | Type | Default | Description | | --- | --- | --- | --- | | initialTheme | string | first available theme | Theme applied on first render. | | themes | object | undefined | Prebuilt theme scales, usually from tte build. | | themeDefinitions | object | built-ins | Base HEX colors for runtime generation. | | includeDefaultThemes | boolean | true | Merge custom definitions with built-ins. Ignored when themes is passed. | | root | HTMLElement | document.documentElement | Element that receives CSS variables. | | storageKey | string | undefined | Persist selected theme in localStorage. |

Hook result:

| Property | Description | | --- | --- | | themeName | Current theme name. | | theme | Current generated theme scale. | | themes | All available theme scales. | | setTheme(name) | Switch theme by name. | | setThemeName(name) | Alias for setTheme. |

Non-hook helpers:

| Helper | Description | | --- | --- | | initializeThemeEngine(options) | Initialize shared themes once, usually before React renders. | | getThemeEngine() | Read the current theme engine snapshot outside React. | | setTheme(name) | Switch theme outside React. |

Core API

import { createTheme, applyTheme } from "@jslibkit/tailwind-theme-engine";

const theme = createTheme({
  colors: {
    primary: "#3b82f6",
    secondary: "#06b6d4",
    tertiary: "#111827"
  }
});

applyTheme(theme);

Output shape:

{
  primary: {
    50: "237 239 255",
    100: "215 220 254",
    500: "58 125 236",
    950: "53 100 186"
  }
}

Applied CSS variables:

:root {
  --primary-500: 58 125 236;
  --secondary-500: 6 182 212;
}

Prebuilt Palettes

import {
  getDefaultPalettes,
  getThemePalettesAsScales
} from "@jslibkit/tailwind-theme-engine/palettes";

const palettes = getDefaultPalettes();
const themes = getThemePalettesAsScales();

Available palettes:

  • blue
  • red
  • green
  • purple
  • dark
  • light

Legacy Single Theme Generation

For simple cases:

npx tte generate --primary "#3b82f6" --secondary "#06b6d4"

Output:

theme/theme.generated.js
theme/index.js

Use tte build for multi-theme projects.

Public Modules

import {
  applyTheme,
  createTheme,
  createThemeCollection,
  defaultThemeDefinitions,
  defaultThemes,
  extendThemeDefinitions,
  generateScale,
  getDefaultPalettes,
  getThemePalettesAsScales
} from "@jslibkit/tailwind-theme-engine";

import preset from "@jslibkit/tailwind-theme-engine/preset";
import { initializeThemeEngine, useThemeEngine } from "@jslibkit/tailwind-theme-engine/react";
import { applyTheme } from "@jslibkit/tailwind-theme-engine/runtime";
import { createTheme } from "@jslibkit/tailwind-theme-engine/createTheme";
import { generateScale } from "@jslibkit/tailwind-theme-engine/generator";

CSS:

@import "@jslibkit/tailwind-theme-engine/theme.css";

TypeScript

Type definitions are included.

import type { Theme, ThemeDefinitions } from "@jslibkit/tailwind-theme-engine";
import { createTheme } from "@jslibkit/tailwind-theme-engine";

const theme: Theme = createTheme({
  colors: {
    primary: "#3b82f6",
    tertiary: "#111827"
  }
});

Important Notes

  • Tailwind classes must remain static.
  • Do not build class names like bg-${color}-500.
  • Runtime switching only updates CSS variables.
  • Tailwind config is not mutated at runtime.
  • Tailwind does not rebuild when themes change.

Troubleshooting

bg-primary-500 flashes after refresh

Import one generated theme CSS file before React loads:

@import "tailwindcss";
@import "@jslibkit/tailwind-theme-engine/theme.css";
@import "../theme/purple.css";

TypeError: Expected color to be a HEX string

You probably passed generated themes as themeDefinitions.

Use this:

useThemeEngine({ themes });

Not this:

useThemeEngine({ themeDefinitions: themes });

Classes are missing

Make sure the class names are static:

<div className="bg-primary-500 text-primary-50" />

Tailwind v4 colors are missing

Make sure this CSS is present:

@import "tailwindcss";
@import "@jslibkit/tailwind-theme-engine/theme.css";

npm install fails with EPERM on Windows

Use a local npm cache:

npm install "D:\Projects\Bun\tailwind-theme-engine" --cache ./.npm-cache

Development

npm install
npm run build
npm test

Project layout:

src/core       color validation, scale generation, theme creation
src/runtime    DOM CSS variable application
src/react      React hook
src/tailwind   Tailwind preset
src/themes     built-in themes and palettes
src/cli        CLI parsing and file generation