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

@aerys/ui

v0.1.1

Published

Native Aerys UI — write React components in pure Aerys with no JSX. Provides h(), view(), and lowercase HTML-tag wrappers (button, div, h1, …).

Downloads

226

Readme

@aerys/ui

Native UI primitives for Aerys. Write React components in pure Aerys with zero JSX.

// Counter.aerx — pure Aerys, no '<' anywhere
let { button, div, h1 } = require("@aerys/ui/tags")

component Counter() {
    let count = signal(0)
    return div({ className = "counter" },
        h1({}, `Count: @{count:get()}`),
        button({ onClick = fn() { count:set(count:get() + 1) } }, "+1"),
    )
}

The .aerx file above compiles to standard React. Tailwind, Radix, shadcn-ui, framer-motion, every other React-ecosystem library still works — they're just functions you call in Aerys style.

Install

npm install @aerys/ui

You also need @aerys/aerysx v0.2.0+ wired into your Vite config so .aerx files are compiled, and react 17/18/19 as a peer dependency.

What you get

Three subpath entry points so bundlers tree-shake naturally:

@aerys/ui/runtime

The minimum surface for spelling React without JSX.

let { h, view, Fragment } = require("@aerys/ui/runtime")

| Export | Behaviour | | --- | --- | | h(tag, props, ...children) | Universal element constructor. tag is a string ("div") or a component reference. props may be null/undefined. | | view(...children) | Fragment shortcut. Returns a single child unwrapped, multiple children inside a Fragment, zero children as null. | | Fragment | Re-export of React.Fragment for users who prefer to spell it. |

In practice you rarely call h directly — the AerysX compiler auto-imports it whenever it sees h(...) or view(...) in your file. Calling them in code "just works."

@aerys/ui/tags

Lowercase wrappers for 130+ HTML and SVG elements. Each one is a thin (props, ...children) => React.createElement(name, props, ...children) function so it composes naturally with everything else.

Three patterns, pick whichever feels right:

1) Destructure — most explicit, best tree-shaking:

let { div, h1, p, button, ul, li, form, input, table, svg, path } =
    require("@aerys/ui/tags")

2) tags proxy — one import, every tag, no upfront list:

let { tags } = require("@aerys/ui/tags")

tags.div({}, tags.h1({}, "Title"), tags.button({}, "Click"))

// Hyphenated / web-component names work via bracket access:
tags["my-counter"]({ count = 1 })

The proxy caches each wrapper after first access, so repeated reads return the same function reference — tags.section === tags.section is true — keeping React's referential-equality optimizations (memo, useCallback deps) intact.

3) Universal h() — for fully dynamic tag names:

let { h } = require("@aerys/ui/runtime")
let level = 2
let heading = h(`h@{level}`, {}, "Dynamic")

The full named-export list lives in src/tags.ts.

@aerys/ui (barrel)

Imports everything from both modules. Convenient for quick scripts:

let { h, view, button, div } = require("@aerys/ui")

For app code prefer the subpath imports — they're explicit about what you're using and produce smaller bundles.

How the compiler hooks in

@aerys/aerysx v0.2.0 added three transforms specifically for this package:

  1. component NAME(...) is treated like a top-level fn — it compiles to function NAME(...) with auto-export default for the first one in a file.
  2. Top-level let { a, b } = require("path") is rewritten to import { a, b } from "path". let X = require("path") becomes a default import.
  3. h(...) and view(...) auto-import from @aerys/ui/runtime when used and not already imported.

You don't have to opt in — write Aerys, the compiler handles the rest.

Why no JSX?

Aerys is a complete language with its own syntax for tables, templates, signals, and lambdas. Writing <button onClick={...}> in a .aerx file means switching dialects mid-line. With @aerys/ui the file is Aerys all the way down, but the output is still React — so every component you've already written and every library you depend on keeps working.

License

Proprietary. See LICENSE.