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

@itsarises/theme-control

v0.4.0

Published

Dev-mode floating control panel for Next.js + Tailwind v4: live-tweak colors, fonts and radius, then write changes back to your @theme block.

Readme

@itsarises/theme-control

Dev-mode floating control panel for Next.js + Tailwind CSS v4, by arises.com. Live-tweak your design tokens — colors, fonts, border radius — directly in the browser, then hit Apply to write the changes back into your @theme block at the code level.

  • 3–12 color tokens: lock, remove, add, copy, per-tile regenerate, regenerate-all (OKLCH harmony algorithm)
  • Edit any color as hex, oklch(), or a CSS color name ("tomato"); toggle display format hex ↔ oklch
  • Font swapping from a curated Google Fonts list (live preview, --font-* written on Apply)
  • Border radius sliders for every --radius* token
  • Undo (100 steps) and Revert (back to last applied file state)
  • Real-time preview via CSS variable overrides — zero rebuild, works with everything that uses your Tailwind tokens
  • Production-safe: the component renders null and the API returns 404 outside NODE_ENV=development

How it works

  1. GET /api/theme-control reads your CSS file, parses the @theme { ... } block, returns all --color-*, --font-*, --radius* tokens.
  2. Every panel change sets the variable on document.documentElement → instant live preview.
  3. Apply POSTs the token set; the server rewrites only the values inside @theme (rest of the file untouched, byte-for-byte). Tailwind's dev server hot-reloads the CSS.

Install

npm i -D @itsarises/theme-control

1. API route (App Router)

// app/api/theme-control/route.ts
export { GET, POST } from "@itsarises/theme-control/server"

Custom CSS location:

import { createHandlers } from "@itsarises/theme-control/server"
export const { GET, POST } = createHandlers({ cssPath: "src/styles/theme.css" })

By default these paths are tried: app/globals.css, src/app/globals.css, styles/globals.css, src/styles/globals.css.

2. Mount the panel (zero production bytes)

// app/layout.tsx
import dynamic from "next/dynamic"

const ThemeControl =
  process.env.NODE_ENV === "development"
    ? dynamic(() => import("@itsarises/theme-control").then((m) => m.ThemeControl))
    : () => null

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <ThemeControl />
      </body>
    </html>
  )
}

A plain import { ThemeControl } from "@itsarises/theme-control" also works (it renders null in production), but the dynamic pattern above keeps the code out of production bundles entirely.

3. Have tokens in @theme

/* app/globals.css */
@import "tailwindcss";

@theme {
  --color-background: oklch(0.985 0.005 250);
  --color-foreground: oklch(0.21 0.02 250);
  --color-primary: oklch(0.65 0.15 165);
  --color-muted: oklch(0.9 0.01 250);
  --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-mono: ui-monospace, monospace;
  --radius: 0.625rem;
}

Use them as normal Tailwind classes (bg-background, text-primary, font-sans, shadcn rounded-lg), and the whole site responds to the panel in real time.

Options

| Prop / option | Where | Default | Description | |---|---|---|---| | endpoint | <ThemeControl /> | /api/theme-control | API route the panel calls | | cssPath | createHandlers() | auto-detected | CSS file containing the @theme block, relative to project root |

Notes & limits (v0.x)

  • Only values inside @theme are written. Hardcoded hexes in className strings are out of scope by design.
  • Font Apply writes the --font-* stack. For production you should still load the font properly (next/font or a <link>); the panel's Google-Fonts <link> injection is preview-only.
  • Removing a token deletes its declaration on Apply — make sure nothing still references it.
  • Commit before big Apply sessions; the file write is surgical but git is your real undo.

v0.4 — shadcn fonts, bulletproof preview, version badge

  • Fonts section restored for shadcn projects: --font-sans: var(--font-geist-sans) tokens are now managed. Preview overrides the underlying variable; Apply writes a literal font stack into @theme (replacing the next/font link for that token — a "Project default" option switches back).
  • Live preview fixed for @theme inline: Tailwind can bake the underlying variable into utilities, so the panel now overrides both the theme key and the underlying var. Preview works in every Tailwind emit mode.
  • Version badge: the panel header shows its version (e.g. v0.4.0), so you can instantly confirm an update took. When updating: bump src/version.ts together with package.json.

v0.3 — undo fixes + version history

  • Undo/Revert fixed: history snapshots were being duplicated by React StrictMode's double-invoked updaters (undo appeared to do nothing). Snapshots now happen outside the render cycle.
  • Coalesced undo steps: rapid changes to the same control (slider drags, repeated edits within 800ms) collapse into one undo step instead of one per pixel.
  • Version history (v1, v2, v3…): every successful Apply saves a version to localStorage (per CSS file, capped at 20). The History section lists them — Restore loads any version as a live preview, then Apply writes it back. Git remains your durable history; restore covers token values, not adds/removes.

v0.2 — shadcn/ui support

  • Full shadcn structure support: @theme inline { --color-x: var(--x) } is resolved; edits are written to :root and .dark (where the real values live), not the mapping block. Dark/light theming keeps working after Apply.
  • Light / Dark editing: when a .dark block exists, a mode toggle appears — edit and preview each mode's palette separately. Removing a token cleans it out of @theme, :root, and .dark.
  • Grouped tokens: with 10+ colors, tiles are grouped into Core / Charts / Sidebar (Charts and Sidebar start collapsed) so shadcn's ~27 tokens stay manageable.
  • Overrides clear on Apply: after a successful Apply the live-preview overrides are removed, so the page reflects exactly what's in the file (previously it looked like "nothing happened").
  • Portal rendering: the panel portals into document.body, so <ThemeControl /> can be mounted anywhere — even directly under <html> — without invalid-nesting hydration errors.
  • Values the panel can't manage safely (e.g. calc()-derived radii, var()-based font stacks from next/font) are left untouched.

Development

npm i
npm run typecheck
npm run build   # tsup → dist/ (ESM + d.ts)

Releasing

npm version patch   # or minor / major
npm publish         # publishConfig.access is already "public"
git push --follow-tags

MIT © itsace (arises.com)