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

styleenv

v1.1.0

Published

Environment-tinted favicons for Next.js and Vite — see at a glance whether a tab is dev, preview, staging, or production.

Readme

Five browser tabs, all the same favicon: dev, preview, production.. and you keep editing the wrong one. styleenv tints your existing favicon per environment at build time, Vercel-style: same mark, different color. Production is never touched.

Install

pnpm add styleenv
# or: npm install styleenv

Usage

Next.js

// next.config.ts
import { withEnvStyles } from 'styleenv'

export default withEnvStyles(nextConfig)

That's the only change needed. No layout edits, no manual favicon files.

Vite

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { envStyle } from 'styleenv/vite'

export default defineConfig({
  plugins: [react(), envStyle()],
})

Default colors

| environment | color | |---------------|--------------------| | development | #3b82f6 blue | | preview | #f59e0b amber | | anything else | #6b7280 gray | | production | never touched |

Environment names are plain strings: whatever detection yields (e.g. ENV_STYLES_ENV=staging, or a Vercel custom environment via VERCEL_TARGET_ENV) is used as the color key. Any env without a color gets the gray fallback — except production, which is never touched.

Options

  • enabled?: boolean — kill switch for the whole tool. Default true.
  • color?: Partial<Record<string, string>> — override the tint color per environment.
  • environment?: string — force the environment instead of detecting it.
  • excludeColors?: string[] — keep pixels near these colors untinted (e.g. white backgrounds or marks in an icon that shouldn't shift).
  • icon?: string | Partial<Record<string, string>> — path to a ready-made icon, or a per-environment map of paths (e.g. { staging: 'staging-icon.png' }), served as-is for styled environments. Tinting and excludeColors are skipped entirely. An env missing from the map falls back to normal tinting.
  • fallbackShape?: "circle" | "square" | "rounded-square" | "ring" — shape of the fallback icon when no source icon is found. Default "circle".
  • runtime?: boolean | { hostnamePatterns?: Partial<Record<string, string>> } — enable runtime restyle for promoted builds. Pre-generates icons for all environments and injects a client-side script that swaps the favicon based on hostname. Default false.
export default withEnvStyles(nextConfig, {
  color: { staging: '#ff00ff' },
  excludeColors: ['#fff'],
  fallbackShape: 'ring',
})

Runtime restyle

When a build is promoted from preview to production, the favicon stays tinted — a single build can't re-tint. The runtime option solves this by pre-generating icons for all environments at build time and injecting a small client-side script that swaps the favicon based on hostname patterns.

// Next.js
export default withEnvStyles(nextConfig, {
  runtime: {
    hostnamePatterns: {
      preview: '-git-.*\\.vercel\\.app$',
      staging: 'staging\\.myapp\\.com$',
    },
  },
})
// Vite
envStyle({
  runtime: {
    hostnamePatterns: {
      preview: '-git-.*\\.vercel\\.app$',
    },
  },
})

Default hostname patterns match localhost → development and Vercel preview URLs → preview. Custom patterns are merged with the defaults.

For Next.js, the runtime script is exported via process.env.ENV_STYLE_RUNTIME_SCRIPT so you can inject it into your root layout:

// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <script dangerouslySetInnerHTML={{ __html: process.env.ENV_STYLE_RUNTIME_SCRIPT }} />
      </head>
      <body>{children}</body>
    </html>
  )
}

Doctor CLI

Inspect what styleenv would do without running a build:

npx styleenv doctor

Output shows detected environment, tint color, fallback shape, source icon, rewrites, and whether the tool is active or disabled (production = zero footprint).

Options:

  • -e, --environment <env> — force environment
  • --color <env>=<hex> — override color per env
  • --exclude-colors <c1,c2> — colors to exclude from tinting
  • --icon <path> — custom icon path
  • --fallback-shape <shape> — circle, square, rounded-square, or ring

Multi-resolution .ico

The tool generates multi-resolution .ico files (16, 32, 48, 64px) alongside the tinted .png. The /favicon.ico route automatically serves the .ico version.

Next.js Metadata API

If your project uses app/icon.tsx or app/apple-icon.tsx (Next.js Metadata API), styleenv automatically detects these and adds the corresponding rewrites (/icon, /apple-icon).

How it works

  • Detects the environment: environment option → ENV_STYLES_ENVVERCEL_TARGET_ENVVERCEL_ENV. If none is set, Next.js falls back to NODE_ENV; Vite falls back to the command (dev server = development, vite build = production — set ENV_STYLES_ENV to tint a build).
  • Tints your existing favicon with sharp and writes it to public/__styleenv/, which self-gitignores.
  • Next.js: serves the tinted icon at your normal favicon URLs via beforeFiles rewrites, with Cache-Control: no-store so stale icons don't linger after switching envs.
  • Vite: rewrites <link rel="icon"> tags in index.html to point at the tinted icon (injecting one if none exists) and serves it with no-store from dev-server middleware.
  • In runtime mode, icons for all environments are pre-generated and a client-side script swaps the favicon based on hostname patterns.

Known limits

  • Environment is resolved at build time — a single build promoted across environments won't restyle (unless runtime is enabled).
  • CDN-only favicons aren't intercepted; on Next.js, custom metadata icons paths aren't either.
  • Icon source changes need a dev server or build restart to pick up.

Development

  • pnpm test — unit tests (vitest); pnpm typecheck — TypeScript.
  • pnpm lint — linting (biome); pnpm format — auto-fix.
  • pnpm test:visual — fetches real brand favicons and writes a before/after tint gallery to .tmp/visual/index.html (needs network; Node >= 22.18 to run the .ts script directly).
  • Runnable examples: cd examples/nextjs && pnpm install && pnpm dev (same for examples/vite-react) — the tab favicon should render tinted green.

License

MIT