Node.js
Install NextRush on Node.js, run a hello-world server, and see how the Node adapter sets the baseline every other runtime is measured against.
Runtime · Baseline
The baseline runtime. Everything in NextRush is designed here first — every capability, every middleware package, and every adapter contract is built and tested against Node.js before any other runtime. Maximum compatibility, the largest ecosystem, and every doc example assumes it unless stated otherwise.
Where Node fits
| Runtime | Best for | Tradeoff |
|---|---|---|
| Node.js · this page | Production APIs, long-running servers, full ecosystem | Heavier footprint than Bun or edge |
| Bun | Local dev speed, fast cold start | Younger ecosystem, some node:* gaps |
| Deno | Secure by default, permission model | Smaller package ecosystem |
| Edge | Global low latency, Cloudflare/Vercel | No long-running server, node:* limited |
| Serverless | Pay-per-request, auto-scaling | Cold starts, no persistent state |
Not sure which runtime fits? See the runtime decision guide.
"Partial" means the adapter is Stable but not yet verified against the real platform in CI (see the compatibility matrix) — not that it's missing features.
Before you begin
- ✓ Node.js 22+ installed (nvm or nodejs.org)
- ✓ A package manager (pnpm, npm, yarn, or bun)
- ✓ ~10 minutes
Confirm your Node.js version
- Why this matters: NextRush targets Node.js 22+ — the ESM-only policy and
node:*APIs assume it.
node --version
# needs to read v22.x.x or higherIf you're on an older line, install 22+ with nvm or from nodejs.org before continuing.
Install NextRush
- Why this matters: the
nextrushmeta-package already includes the Node adapter — one install is everything.
$ pnpm add nextrush$ pnpm add -D tsx typescript @types/node
Or scaffold instead:
pnpm create nextrush my-api --runtime nodeBehind the scenes:
@nextrush/core,@nextrush/router, and@nextrush/adapter-nodeare all re-exported throughnextrush- On every other runtime (Bun, Deno, edge, serverless) the same import stays identical — only the adapter changes
Run a hello-world server
Create src/index.ts:
import { createApp, createRouter, listen } from 'nextrush';
const app = createApp();
const router = createRouter();
router.get('/', (ctx) => {
ctx.json({ runtime: 'node', status: 'ok' });
});
app.route('/', router);
await listen(app, 8080);Run it:
npx tsx src/index.tsExpected result — curl http://localhost:8080/ returns {"runtime": "node", "status": "ok"}
Behind the scenes:
listen(app, 8080)calls@nextrush/adapter-node, which starts a plainnode:httpserver- Each incoming request goes to NextRush's router through the Context API
- The same four calls (
createApp,createRouter, route,listen) are what every runtime starts from
Why Node is the baseline
Your server is now running. Before moving to Bun or Deno, it's worth understanding why Node is the reference runtime — and what that means for portability.
What Node gives you:
- Full
node:*module access — no restrictions - No cold-start behavior to design around
- Every middleware package (
@nextrush/body-parser,@nextrush/static,@nextrush/form-data) targets it directly
This does not mean Node is required — Bun, Deno, edge, and serverless adapters all implement the same Context and Application contract (see each adapter's reference). Node is where that contract has the fewest constraints, so it's the reference point the runtime compatibility concept measures every other adapter against.
Node runtime working — you're ready to verify and move on.
Node baseline complete
Confirm the server answers before moving on:
curl -i http://localhost:8080/
# → HTTP/1.1 200 OK
# → {"runtime":"node","status":"ok"}Your project now looks like:
my-api/
package.json
src/
index.tsBaseline complete — a real NextRush server on Node.js. Every capability the framework ships targets this runtime first.
What you learned
Three things describe how a request reaches your code on Node.js:
- Node is the baseline runtime — the framework's
node:*-using packages, the Node adapter, and the docs' default code examples all target it first - One
nextrushimport covers the adapter —createApp,createRouter, andlistenall come from the meta-package; you never import@nextrush/adapter-nodedirectly unless you need its lower-level surface - The same code moves between runtimes — nothing in
src/index.tsabove is Node-specific; swapping to Bun changes the runtime underneath, not your route handlers
The same app, every runtime
This is the core promise — the code you just wrote runs on every runtime NextRush supports. Only the adapter import changes:
- createApp()
- Router
- Handler
- Node adapter
- Running
Swap the adapter, same everything else:
// Node: import { listen } from '@nextrush/adapter-node';
// Bun: import { listen } from '@nextrush/adapter-bun';
// Deno: import { listen } from '@nextrush/adapter-deno';
// Edge: import { serve } from '@nextrush/adapter-edge';
// Serverless import { handler } from '@nextrush/adapter-serverless';The route handler, middleware, and Context API never change. That's the point — you're learning one runtime today, but you're building toward a portable mental model.
Next steps
🚀 Build a Task API
Go past hello-world: routing, a JSON body, and a real 404 — starting from exactly where this page leaves off.
Deploy to production
Docker, PM2, and systemd deployment paths for a Node.js NextRush server.
Node adapter reference
The full @nextrush/adapter-node surface — serve(), createHandler(), and Node-specific utilities.
Continue learning
Which Runtime Should I Use?
A decision guide for choosing between Node.js, Bun, Deno, edge, and serverless — the fast answer and the criteria behind each choice.
Bun
Install NextRush on Bun, run a hello-world server on Bun.serve(), and see exactly where the Bun adapter's import path diverges from Node's.