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

@ramonda/build

v0.4.0

Published

The bundler settings a Ramonda app needs, as a Vite plugin and an esbuild plugin — so the app names none of them.

Readme

@ramonda/build

Three bundler settings decide whether a Ramonda app runs. This package owns them, so your app names none of them.

npm license

Status: 0.x. The API changes freely between releases while the design is being explored; from 1.0 the interfaces hold. A breaking change ships as a minor until then — see Upgrading for what that means for a version range, and the root README.

npm install -D @ramonda/build

Documentation: ramonda.dev/reference/build

// vite.config.ts
import { defineConfig } from "vite";
import { ramonda } from "@ramonda/build/vite";

export default defineConfig({ plugins: [ramonda()] });

A project scaffolded with npm create ramonda already has this.

The package is ESM only, so your project needs "type": "module" in its package.json — without it Vite loads the config as CommonJS and stops with "This package is ESM only but it was tried to load by require". Scaffolded projects already declare it.

The fault it exists for

@state, @compute and the rest are TC39 decorators. No engine can parse them — so a bundler has to compile them away, and whether it does comes down to target. esbuild does it for every target except esnext.

esnext is also esbuild's default. So a build that says nothing about a target has already picked the one value that breaks, and nothing tells you: the build succeeds, prints no warning, and emits a file that dies with SyntaxError: Invalid or unexpected token the first time a browser reads it.

That shipped here. It had been working by accident — an unrelated esbuild option was forcing every module through the transform — and removing that option broke the output in silence.

A setting like that should not be something an app writes out by hand, in one place per bundler it runs, and keeps in step with two others forever. So it is not.

Vite 8 made it worse: it transforms with Oxc, which cannot lower a TC39 decorator for any target, so no setting saves them there. On Vite 8 the plugin lowers them itself, with esbuild, after Oxc has compiled each module. The config is the same plugins: [ramonda()] on both.

What it sets

| | | |---|---| | jsx | "automatic" — JSX compiles through the runtime import, so there is no factory to name | | jsxImportSource | "@ramonda/core" — where that import comes from | | target | "es2022" — the one above |

The first two have to agree with your tsconfig.json's jsx and jsxImportSource, which is the other reason they are worth taking from one place.

Vite

import { defineConfig } from "vite";
import { ramonda } from "@ramonda/build/vite";

export default defineConfig({ plugins: [ramonda()] });

esbuild

For a build you call yourself, spread the options:

import { build } from "esbuild";
import { ramondaOptions } from "@ramonda/build/esbuild";

await build({
  ...ramondaOptions,
  entryPoints: ["src/entry-client.tsx"],
  bundle: true,
  format: "esm",
  outfile: "dist/client.js",
});

For a build assembled somewhere you cannot reach, there is a plugin:

import { ramonda } from "@ramonda/build/esbuild";

It fills in whatever the build did not set.

It refuses rather than corrects

If your config names any of the three as something Ramonda cannot work with — a target that would leave the decorators in, or a jsx / jsxImportSource that disagrees — the build stops and tells you which line:

[ramonda] `esbuild.target` in your Vite config has `"esnext"`, and that leaves Ramonda's
decorators in the output.
…
This is refused rather than corrected because you asked for something specific, and the line
you asked it on is the one that has to change.

It could win that argument silently — Vite merges a plugin's config over the user's — and that is exactly why it does not. A setting that gets quietly reversed is a setting you cannot reason about.

A setting that already agrees is left alone, for the same reason: it was a real choice, and handing it back would only replace your line with an identical one. Both adapters answer this from the same place, so Vite and esbuild cannot disagree about your config.

And then check the output

Configuration is not proof. ramonda-check-bundle, from @ramonda/check, parses every file your build emitted and fails the build instead of the browser:

"scripts": {
  "build": "ramonda-check && vite build && ramonda-check-bundle dist"
}

That one is worth reaching for whichever bundler you use. It reads the artifact rather than the configuration, so it does not need to know how the artifact was made.

Another bundler

There is no adapter for webpack, rspack or rollup, because none of them is a bundler Ramonda is built and tested against, and an adapter nobody exercises is a promise nobody is keeping.

The settings themselves are exported, so wiring one up yourself is short:

import { RAMONDA_TRANSFORM, lowersDecorators } from "@ramonda/build";

lowersDecorators(target) answers whether a given target compiles the decorators away — including for a list like ["es2022", "chrome100"], which esbuild reads as the intersection of its entries.

The rule is the same for tsc as for esbuild, which matters here because a webpack or rollup toolchain usually lowers TypeScript with tsc: esnext leaves the decorators in, and every target below it compiles them away. Both compilers are run against that table in this package's tests, so it is a measurement rather than a recollection — but it is only those two. If you lower with something else, run ramonda-check-bundle over the output and let the artifact answer.

Docs

https://ramonda.dev/reference/build

License

MIT © Nikola Blagojević