JSX
How Nub runs JSX on stock Node — automatic-runtime defaults, tsconfig-driven configuration, and the per-file import-source pragma for mixing runtimes.
Files ending in .jsx and .tsx execute through the same load hook. JSX is recognized in .jsx / .tsx only, never in plain .js. The defaults are the modern ones — automatic runtime, react as the import source — matching oxc-transformer, Vite's React plugins, Rolldown, and Bun, so a React project needs no setup.
nub render.tsxcompilerOptions.jsx
Configure the JSX runtime through tsconfig.json, the way the rest of your toolchain already does. These compilerOptions are honored:
-
jsx— the runtime mode. One of:"preserve" | "react" | "react-jsx" | "react-jsxdev" | "react-native" -
jsxImportSource— the package the automatic runtime imports from (e.g.preact). -
jsxFactory— the factory function for the classic runtime. -
jsxFragmentFactory— the fragment factory for the classic runtime.
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}Preact, Hono, and Vue JSX work via passthrough. Solid is the exception — its JSX needs babel-preset-solid's reactive-graph compilation, which a per-file transpiler can't do, so run Solid through its bundler (e.g. nub run vite).
@jsxImportSource
A per-file /** @jsxImportSource ... */ pragma overrides the tsconfig import source for that one file. This is the standard mechanism for mixing JSX runtimes in a single project — a Hono route alongside React components.
/** @jsxImportSource hono/jsx */
export default function Page() {
return <h1>Hello</h1>;
}The pragma is read from the file source itself; no tsconfig entry is needed for it to take effect.
TypeScript
How Nub runs the full TypeScript surface on stock Node — non-erasable syntax, resource-management downleveling, and source maps — none of which plain Node does.
Decorators
How Nub runs legacy TypeScript decorators and their emitted design-type metadata on stock Node — the form the NestJS, TypeORM, and Angular dependency-injection ecosystem is written against.