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

@expo-forge/forge-ui

v0.0.50

Published

ForgeUI — utility-first CSS/React Native style engine

Readme

ForgeUI

ForgeUI is a utility-first styling engine for:

  • Web apps (Forge scans classes and generates CSS)
  • React Native / Expo apps (Forge uses a Babel plugin, no CSS file)

v0.0.10 — Babel plugin now automatically injects useTheme() from @expo-forge/forge-ui into all components with dark: classes, ensuring they automatically re-render across all pages when theme changes (no manual hook call needed).

v0.0.9 — Theme preference is now persisted across app restarts using AsyncStorage (React Native) and localStorage (web). The theme will remember your toggle choice.

v0.0.6 — Native theme detection now uses useColorScheme as the primary source, which fixes Expo system theme detection.

Quick Start

  1. Install:
npm install @expo-forge/forge-ui
  1. Choose setup path:

Web Setup

Step 1: Create forge.config.toml

Create this file in your project root:

[general]
input = [
  "src/**/*.html",
  "src/**/*.jsx",
  "src/**/*.tsx",
  "src/**/*.vue",
  "src/**/*.svelte",
]
# CSS only (JS goes next to it):
output = "dist/forge.css"
# — or — separate dirs for CSS and JS:
# output = "public/css, public/js"

[options]
important = false
minify = false

[components]
enabled = true
js = true

When components.enabled = true, Forge only emits CSS for components whose class names appear in your scanned source files. Unused component blocks (button, card, modal, etc.) produce no output.

Step 2: Build or watch

One-time build:

npx forge build

Dev watch mode:

npx forge dev

Step 3: Load generated files

Required CSS:

<link rel="stylesheet" href="/forge.css" />

Optional runtime (needed for interactive Forge components and dev auto-refresh):

<script src="/forge-runtime.js" defer></script>

Web Setup By Platform

Plain HTML

  1. Include src/**/*.html in general.input.
  2. Run npx forge build or npx forge dev.
  3. Load generated files:
<link rel="stylesheet" href="/dist/forge.css" />
<script src="/dist/forge-runtime.js" defer></script>

React / Vite

  1. Include src/**/*.jsx and/or src/**/*.tsx in general.input.
  2. Run npx forge dev.
  3. Import generated CSS in app entry file:
import "../dist/forge.css";

If using interactive Forge components, include forge-runtime.js in index.html.

Next.js

Use this config:

[general]
input = ["app/**/*.tsx", "app/**/*.ts", "components/**/*.tsx"]
output = "public/forge.css"

[options]
important = false
minify = false

[components]
enabled = true
js = true

Load in root layout:

<head>
  <link rel="stylesheet" href="/forge.css" />
</head>
<body>
  {children}
  <script src="/forge-runtime.js" defer></script>
</body>

Vue

  1. Include src/**/*.vue in general.input.
  2. Run npx forge dev.
  3. Import generated CSS in app entry file:
import "../dist/forge.css";

Svelte

  1. Include src/**/*.svelte in general.input.
  2. Run npx forge dev.
  3. Import generated CSS in root entry/layout file:
import "../dist/forge.css";

React Native / Expo Setup

Important

React Native does not use:

  • forge.config.toml
  • forge.css
  • forge-runtime.js

Step 1: Initialize

npx forge init --native

Step 2: Enable Babel plugin

Use:

@expo-forge/forge-ui/babel-plugin

Step 3: Wrap app with ThemeProvider

import { ThemeProvider } from "@expo-forge/forge-ui";

export default function RootLayout() {
  return <ThemeProvider>{/* app */}</ThemeProvider>;
}

Step 4: Start Expo

npx expo start

Required app.json settings

{
  "expo": {
    "userInterfaceStyle": "automatic",
    "experiments": {
      "reactCompiler": false
    }
  }
}

Step 5: Use Forge color palettes in native

You can now use all Forge color palettes in your native components:

import { useColors } from "@expo-forge/forge-ui";

export default function MyComponent() {
  const colors = useColors();
  return <View style={{ backgroundColor: colors.blue[5] }} />;
}

Dynamic Classes (Web)

Literal class strings are supported:

const card = {
  color: "bg-gradient-to-r from-blue-1 to-green-1",
};

For fully runtime-generated class names (example: bg-${tone}-5), use:

  1. general.safelist
  2. general.inject_colors = true (larger CSS output)

Output Optimizations

Forge automatically tree-shakes generated CSS — no extra config needed.

Selective :root color variables

The :root block only contains variables for color palettes you actually use. A project that only uses bg-blue-5 text-red-3 gets --blue-* and --red-* variables only — not all 22 palettes.

Lazy component CSS

When components.enabled = true, Forge only emits CSS for components whose class names appear in scanned files:

| Component block | Emitted when you use… | | --------------- | --------------------------------------------------------------------------------------------------------- | | Button | button, button-primary, button-secondary, button-ghost, button-danger, button-sm, button-lg | | Card | card, card-header, card-body, card-footer | | Modal | modal-content, data-fg-modal, data-fg-toggle | | Utility | avatar, dot, spark, bar, table-wrap | | Visibility | hidden |

Advanced Utilities

Fluid text sizing

Use text-clamp-* for responsive font sizes with CSS clamp(...):

<h1 class="text-clamp-4xl">Fluid heading</h1>
<p class="text-clamp-sm">Fluid body text</p>

Supported presets: sx/xs, sm, base, lg, xl, 2xl ... 9xl.

Class-driven at-rules

Forge can emit custom at-rules directly from class tokens:

<div class="media-[(min-width:900px)]:text-clamp-xl">Custom media query</div>

<div class="layer-[components]:rounded-lg">Wrapped in @layer components</div>

<div
  class="keyframes-[wiggle:0%{transform:rotate(-3deg)}100%{transform:rotate(3deg)}] animate-[wiggle_1.2s_ease-in-out_infinite]"
>
  Custom keyframes + animation
</div>

Notes:

  • Replace spaces with underscores inside bracket syntax when needed.
  • These tokens work with existing variants like md:, hover:, and dark:.

Config Reference

| Key | Type | Default | Purpose | | ------------------------------- | ---------- | --------------------- | ------------------------------------------------ | | general.input | string[] | common src/** globs | Files to scan for classes | | general.output | string | forge.css | CSS output (and optional JS output) — see below | | general.safelist | string[] | [] | Always include these classes | | general.inject_colors | bool | false | Pre-generate full color and gradient utility set | | general.inject_color_variants | string[] | [] | Variant prefixes for injected classes | | options.important | bool | false | Append !important to declarations | | options.minify | bool | false | Minify output CSS | | components.enabled | bool | true | Include built-in component CSS | | components.js | bool | true | Emit forge-runtime.js |

output format

# CSS only — JS written next to it
output = "dist/forge.css"

# CSS in one dir, JS in another
output = "public/css, public/js"

# Bare directories — filenames appended automatically
# public/css/forge.css + public/js/forge-runtime.js
output = "public/css, public/js"

# Explicit filenames also work
output = "public/css/styles.css, public/js/runtime.js"

Common Mistakes

No styles applied

  • Run npx forge build
  • Confirm file exists at general.output
  • Confirm app loads the same file path

Some classes missing

  • Your file globs likely miss some folders
  • Add those folders to general.input

Browser does not update during dev

  • Use npx forge dev
  • Ensure /forge-runtime.js is loaded

React Native styles do not apply

  • Run npx forge init --native
  • Ensure Babel plugin is configured
  • Restart Metro

Command Summary

Same commands on Windows, macOS, and Linux:

npx forge build
npx forge dev
npx forge init --native

Repository

https://github.com/semsakadanupol/forge-ui

Web-like first: and last: pseudo-classes in React Native

With Forge-UI's experimental Babel plugin support, you can use first: and last: pseudo-classes directly in className inside a .map loop—just like on the web!

Example:

{
  items.map((item) => (
    <View key={item.id} className="p-4 first:bg-red-1 last:rounded-b-xl">
      {item.text}
    </View>
  ));
}
  • first:bg-red-1 will only apply to the first child.
  • last:rounded-b-xl will only apply to the last child.
  • No manual index checks or helpers needed—just write your classes as you would for web.

This works for any dynamic array mapping in JSX in React Native.