Nub – JavaScript toolkit that augments Node.js (instead of trying to replace it)

bentaber1 pts0 comments

Nub — an all-in-one toolkit for Node.js — Nub

NewIntroducing Nub→The all-in-one JavaScript toolkit that augments Node.js instead of trying to replace it<br>A TypeScript-first toolchain for Node.js. Run TypeScript files, package.json scripts, and local CLIs on the node and package manager you already have. No new runtime, no lock-in.<br>macOS / LinuxWindowsnpm<br>$curl -fsSL https://nubjs.com/install.sh | bash

Copy agent prompt

$ nub index.ts # TypeScript-first Node.js runtime<br>$ nub run dev # 24× faster pnpm run<br>$ nubx prisma generate # 19× faster npx<br>$ nub install # 2.7× faster pnpm install<br>$ nub watch src/server.ts # native watch mode<br>$ nub pm shim # built-in Corepack-style shims<br>$ nub node install 26 # Node version manager

The toolchain<br>An all-in-one toolkit for Node.js<br>One Rust binary to run your files and scripts, install dependencies, and manage Node itself.

File runnerScript runnerPackage runnerPackage managerNode version manager

$nub A TypeScript-first Node.js<br>Run .ts, .tsx, and .jsx on stock Node with full support for tsconfig.json, .env loading, and modern syntax and Web APIs.<br>Replacestsxts-nodetsconfig-pathsdotenv

# run a TypeScript file<br>$ nub index.ts<br># restart on changes<br>$ nub watch src/server.ts

$nub<br>A TypeScript-first Node.js<br>Nub adds support for TypeScript, JSX, decorators, .env files, YAML/TOML imports, and modern syntax and APIs on top of stock Node. Flag-for-flag compatible with node. Powered by Rust and oxc.

Architecture<br>Transpiles in Rust, runs on real Node<br>Nub transpiles your code in memory with oxc (compiled into a native Node addon) and runs the output on the stock node binary. There’s no Nub runtime, just real Node. Runs on Node.js 18 LTS and newer.

$ nub app.ts<br># oxc transpiles in memory, then stock node runs it<br>running on node v26.3.0

TypeScript-first<br>Full TypeScript support, not just type stripping<br>Recent versions of Node support type stripping, which erases annotations but rejects non-erasable syntax. Nub’s load hook transpiles each file through its native addon instead, so enums, parameter properties, and extensionless imports that Node doesn’t allow all just work.

import { Model } from "./base" // extensionless → ./base.ts

enum Status { Draft, Sent, Paid }

class Invoice extends Model {<br>constructor(public status = Status.Draft) {} // parameter property

tsconfig<br>Respects your tsconfig.json<br>Nub resolves your tsconfig.json (including "extends") and feeds its paths into Node’s own resolver through a module.registerHooks() resolve hook. No more tsconfig-paths or disagreement between Node.js and your editor.

// tsconfig.json<br>"compilerOptions": {<br>"baseUrl": ".",<br>"paths": {<br>"@/*": ["src/*"],<br>"@db": ["src/db/index.ts"]

Environment<br>Loads .env files automatically<br>Nub reads .env, .env.local, and .env.[NODE_ENV] and injects them before Node starts. No dotenv required. Automatic var expansion via ${VAR} just like Vite and Next.js.

# .env<br>APP=acme<br>DATABASE_URL=postgres://localhost/${APP}_dev

# No dotenv. No cross-env. No import "dotenv/config".<br>$ nub server.ts

Modern syntax<br>Decorators, JSX, and using<br>Nub supports decorators and JSX, transpiling it according to your tsconfig.json settings. Full support for emitDecoratorMetadata and explicit resource management, no build step required.

await using db = await connect() // disposed at scope end

@sealed // legacy decorator<br>class User {}

const view = Hello name="world" /> // JSX in .tsx

Loaders<br>Import JSON, YAML, and TOML<br>Import .yml, .yaml, .toml, .json5, and .jsonc files directly. A module.registerHooks() load hook routes them through fast Rust parsers in Nub’s native addon, resolving each import to a plain JavaScript object. (Oh, .txt works too)

import config from "./config.yaml" // parsed object<br>import flags from "./feature.jsonc" // comments stripped<br>import pkg from "./Cargo.toml" // parsed object<br>import prompt from "./prompt.txt" // string

import { host, port } from "./config.yaml" // named exports

Auto-restart<br>A dependency-aware watch mode<br>Powered by node --watch, Nub’s watch command watches for changes to your entrypoint or any file transitively imported. It also adds TypeScript/JSX sourcemap support and watches your package.json, tsconfigs, and .env files.

$ nub watch src/server.ts<br>Listening on http://localhost:3000

↺ src/db.ts changed — restarting<br>Listening on http://localhost:3000

Node version management<br>Auto-installs Node, on demand<br>Nub reads your .node-version, .nvmrc, or engines/devEngines pin and runs your code on exactly that version. If it isn’t on your machine, Nub downloads it from nodejs.org, verifies the checksum, and installs it on the fly — replacing nvm and fnm. You can also manage versions manually.

$ echo 26 > .node-version<br>$ nub hello.ts<br>Using Node.js 26.3.0 (resolved from .node-version)<br>Installed in 9.8s<br>Hello world!

Performance<br>Negligible overhead over plain Node<br>Nub transpiles each file in memory through its native Rust addon, then runs it on the real node binary. Its own startup is a few...

node typescript import json from watch

Related Articles