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

vanrs

v1.1.2

Published

Frontend frame for rescript inspired by vanjs

Readme

vanrs

ReScript bindings for VanJS — zero-overhead reactive UI via direct FFI into vanjs-core v1.6.1.

ReScript vanjs-core npm MIT


ReScript  |  VanJS


Overview

vanrs provides typed ReScript APIs for building reactive DOM UIs. State management (VanRs.state, VanRs.derive), element construction (tag functions and VanRs.element), event handling, hydration, and JSX support are all thin wrappers over vanjs-core primitives.

Requires: ReScript ^12.3.0, vanjs-core ^1.6.1 (peer dependency)

Features

  • Direct FFI bindings to vanjs-core — no custom reactivity engine
  • Full state API: state, get, set, raw, old, derive, watch
  • Tag DSL: HTML elements, SVG elements, namespaced tag creation
  • JSX support via VanRsJsx module (ReScript JSX v4)
  • Hydration support for SSR scenarios
  • Type-safe event handlers and reactive attributes
  • Opt-in VanRs.safeUrl helper for untrusted URL-bearing attributes

📦 Installation

1. Create a ReScript Application

npm create rescript-app@latest

See the official ReScript documentation for project setup.

2. Install Dependencies

npm i vanjs-core vanrs

Note: vanjs-core is a peer dependency — you must install it explicitly. vanrs binds to vanjs-core v1.6.1 and expects it to be available at runtime.

3. Configure rescript.json

Add vanrs to your dependencies in rescript.json:

{
  "dependencies": ["vanrs"]
}

For JSX support, the project already includes the correct configuration:

{
  "jsx": {
    "version": 4,
    "module": "VanRsJsx"
  }
}

⚡ Quick Start

Basic Reactive UI

// Mount a reactive counter into the DOM
let count = VanRs.state(0)

let app = VanRs.div([
  VanRs.text("Clicks: "),
  VanRs.stateInt(count),
  VanRs.button(
    ~props=[VanRs.on("click", _ => VanRs.set(count, VanRs.get(count) + 1))],
    [VanRs.text("Click me")]
  )
])

// Add to document body
VanRs.add(VanRs.body(), [app])

Using VanRs.nodeById

// Get an existing DOM element by id
switch VanRs.nodeById("root") {
| Some(root) => VanRs.add(root, [app])->ignore
| None => ()
}

Derive Reactive Values

let name = VanRs.state("World")
let greeting = VanRs.derive(() => "Hello, " ++ VanRs.get(name) ++ "!")

// greeting updates automatically when name changes
VanRs.set(name, "ReScript")

🧪 Testing

Test suite: 163 tests (223 assertions, all passing)

pnpm res:test

Build:

pnpm res:build

See docs/api-reference.md for the complete public API surface.

⚛️ JSX Support

VanRs supports JSX syntax with type-safe prop mapping via the VanRsJsx module. JSX elements are created with correct XML namespaces: SVG elements (like <rect>, <g>, <clipPath>, <linearGradient>) use the SVG namespace (http://www.w3.org/2000/svg), and MathML elements (like <math>, <mrow>, <mi>) use the MathML namespace (http://www.w3.org/1998/Math/MathML). Unknown/custom tags fall back to HTML-namespace creation.

let clicks = VanRs.state(0)

let view = <button
  className="btn"
  onClick={_ => VanRs.set(clicks, VanRs.get(clicks) + 1)}
>
  {clicks->VanRs.stateInt}
</button>

See docs/jsx-mapping.md for the full JSX-to-API mapping with namespace coverage, and docs/api-reference.md for complete API details.

📚 Documentation

| Document | Description | |----------|-------------| | API Reference | Complete public API documentation | | JSX Mapping | JSX syntax to VanRs API mapping | | Known Divergences | 5 known test failures from vanjs-core binding integration |


Explore the docs: API Reference · JSX Mapping · Known Divergences


🏗️ Architecture

The public entry point is VanRs. Low-level vanjs-core FFI bindings are available via VanRsVan for advanced use cases requiring direct access to vanjs primitives.

🔒 Security

VanRs is safe-by-design for normal DOM construction: string children become text nodes (no HTML parsing), attributes route through setAttribute only (not DOM property setters), and event handlers are typed as functions (no string handlers). The one remaining gap is URL-bearing attributes (href, src, action, formaction, xlink:href). When you bind an untrusted string to any of these, wrap it with VanRs.safeUrl:

let link = VanRs.a(
  ~props=[VanRs.attr("href", VanRs.safeUrl(userInput))],
  [VanRs.text("open")],
)

safeUrl neutralizes javascript:, vbscript:, file:, data:text/*, and unknown schemes (returning ""), and defeats control-character tricks like "java\tscript:". It is opt-in; VanRs never sanitizes implicitly. See the API Reference for the full contract.

License

MIT — @MetalbolicX