
r/node

What are the best practices of integartion tsting in Node.js?
We test the routes, mock the database and use supertest?
Ran real PHP applications as TypeScript on Bun 1.3.14; migration from Node was mostly a non-event
I’ve been transpiling PHP applications to TypeScript and running the output on Bun, and I’ve now got real apps executing end to end. Sharing some notes in case they’re useful to anyone moving a Node-targeted codebase over.
Coming from Node 22, the runtime side was almost boring, most of the transpiled output just ran on Bun directly, no changes needed.
The one real snag was native code. A few C bindings (PCRE, LibXML) that worked fine on Node 22 didn’t load on Bun 1.3.14. That’s understandable: native addons are compiled against a specific runtime’s ABI/internals, so a binding built for one runtime won’t necessarily load on another. Instead of maintaining runtime-specific builds, I compiled the C bindings to WebAssembly. They’re now version-independent; no ABI coupling, so the same WASM artifact behaves the same regardless of the runtime underneath.
The thing I’m still figuring out: I’d been using Node’s cluster mode to mirror PHP-FPM’s process model (a master plus a pool of workers), and I’m still investigating how that holds up under Bun. If anyone here has run node:cluster workloads on Bun, especially anything resembling a prefork worker pool, I’d like to hear how it went and where the edges are.
Reached ~178 Stars! Built a Terminal Torrent client that searches every trusted source at once and downloads straight to disk
Finding a torrent in 2026 sucks. One site is a minefield of fake download buttons. Another hides the real link under a popup that spawns two more tabs. And after all that, half the results are dead with zero seeders.
So I built the opposite. torlink lives in your terminal: you type a query, it hits a curated set of trackers all at once, and the results stream back tagged with source, size, and seeders as fast as each site answers. Arrow to the one you want, press d, and it lands on your drive. No browser and no setup.
The whole thing is one command:
npx torlnk
That's it, all you need is Node. (The npm name is torlnk; torlink was too close to an existing package, so the spare "i" had to go.)
What you get
- One search across FitGirl, YTS, EZTV, Nyaa, SubsPlease, and SolidTorrents at once, with results streaming in and staying sorted as each source answers. If one is down it keeps going and tells you which.
- Press
dto grab. Queue up as many as you want; they download in the background and pick up where they left off if you quit mid-transfer. - It seeds by default once a download finishes, and you can turn that off per item. Torrenting only works when people give back.
- A clean keyboard-driven TUI: one footer line, a
?cheatsheet, and that is the whole surface. Nothing leaves your machine except the request to the torrent network.
My favorite way to use it right now is loading up on games to try out this summer. One search, a couple of keystrokes, and a whole stack of them is downloading in the background.
On games: games are the only category that can actually run code, so those come from FitGirl alone, a repacker with a long, well-known track record. Everything else is plain video and subtitles from sources like YTS, EZTV, and Nyaa.
MIT and open source. Open to feedback and source suggestions, and a star is appreciated if you find it useful.
My Next.js SaaS architecture tech stack as a solo developer
The goal of this diagram is to show how I structure my SaaS app as a solo developer.
This is not “the perfect stack”, and I don’t think every project needs all of this. The goal isn’t to say everyone should use the exact same tools, I'm just sharing an architecture that currently works well for me.
At a high level:
Frontend: Next.js, React, Tailwind CSS, shadcn/ui, React Hook Form, TypeScript
Backend: Node.js, oRPC, Zod for the frontend/backend contract
Database: PostgreSQL with Drizzle ORM
Auth: Clerk
Payments: Stripe
Emails: React Email
Observability: Sentry + LogTape
CI/CD and quality: ESLint, Vitest, Playwright, Knip, Storybook, GitHub Actions
I turned this architecture into an open-source GitHub project here: SaaS Boilerplate
ELI5: What is a mass-assignment vulnerability?
And why can't it be solved through parameterized queries?
Yet Another TypeScript Template: Opinionated and minimal.
Built this for myself, sharing in hopes some may find it useful.
Features:
- Reduce supply chain risk with a
.npmrcpreconfigured withignore-scriptsandmin-release-ageenabled - Test without extra tooling using the built-in Node.js test runner
- Run TypeScript directly in Node.js using native type stripping (
erasableSyntaxOnlyenabled to enforce compatibility) - ESLint & Prettier preconfigured
- Husky pre-commit configured to lint, format & test
- Strict type checking on run and test
- Pinned dependencies to reduce supply chain risk
SecretSpec 0.13: SDKs for Python, Node.js, Go, Ruby, and Haskell
secretspec.devWhy does accessing stdin this way seem to make it impossible to clean up?
In the upcoming application, when hitting q, quit gets set to true causing the interval to be cleared and the readable handler to be removed, but the process continues to hang. Why does there not seem to be a way to clean up properly such that the process ends automatically instead of requiring a process.exit() to end the process?
import process from 'node:process';
const p = 'p'.charCodeAt(0);
const q = 'q'.charCodeAt(0);
let paused = false;
let quit = false;
const signalsToStringMap: (0 | NodeJS.Signals)[] = [0, 0, 0, 'SIGINT'];
const readableHandler = () => {
const inp = process.stdin.read();
process.stdin.resume();
const sig = signalsToStringMap[inp[0]];
if (sig) {
return process.emit(sig);
}
if (p === inp[0]) paused = !paused;
if (q === inp[0]) quit = true;
};
process.stdin.setRawMode(true);
process.stdin.on('readable', readableHandler);
export const cleanup = () => {
process.stdin.setRawMode(false);
process.stdin.off('readable', readableHandler);
};
const interval = setInterval(() => {
if (quit) {
clearInterval(interval);
cleanup();
return console.info(
'interval cleared and cleaned up - should automatically exit here',
);
}
if (!paused) {
console.log('processing');
} else {
console.log('paused');
}
}, 100);
As an example, this basic http server application will start the server, make a request, and close the server without ever calling process.exit.
import http from 'node:http';
const server = http.createServer((_req, res) => {
res.writeHead(200);
res.end();
server.closeAllConnections();
server.close();
});
server.listen(23456, () => {
console.info('listening');
http.get('http://localhost:23456', () => {});
});
Surely some equivalent exists for ending stdin?
Scamers target ComfyUI extensions developers - be aware
Hello, I'm a ComfyUI extension developer. And I have received this email, right now. it's a blatant scam. They trick you to install a random npm package, or even .sh script via curl | sh. I have not inspected it - but it's obviously in contains the same npm package, but portable
But maybe this trick can work on somebody. I assume they target ComfyUI extensions to steal GitHub and ComfyUI Registry credentials and inject malicious code in the extensions. So it can harm ComfyUI users as well
It's shame that small awareness of that npm, pip, and other package managers are just curl wrappers, is heavily abused by scammers. And the small target base allow bypassing spam detection. I'll cross-post this into node subreddit too
Can you report it somehow, I have zero knowledge of npm. The package is runaic/aic
Walks the full cmd/compile pipeline in order: package names, data structures, and the SSA construction that drives inlining, escape analysis, bounds-check elimination, and register allocation, with flags to observe each phase directly.
This one took a while, it's probably the longest thing I've written on this blog. I wanted to do a proper end-to-end walkthrough of cmd/compile: real package names, real data structures, diagrams for the AST and SSA CFG, and the flags you actually need (-m, -m=2, GOSSAFUNC, -S) to observe each phase yourself rather than just take my word for it.
Covers the full pipeline: lexer → parser → type checker → IR lowering → SSA construction → optimization passes (inlining, escape analysis, BCE, nil check elimination, register allocation) → architecture-specific code emission.
Hope it's useful — happy to answer questions or push back on anything that looks wrong.
What are you using to manage application secrets?
I’m curious what everyone’s workflow looks like for managing API keys, environment variables, database credentials, and other application secrets.
How do you handle different environments like development, staging, and production? How do you share secrets with your team and coordinate changes? Do you use a dedicated secrets manager, cloud provider tools, .env files, or something else?
What’s working well with your current setup, and what’s your biggest source of friction?
Full disclosure: we’re building a secrets manager ourselves, which is why we’re interested in hearing how other developers approach this problem. We’re looking to learn what works well today and where existing workflows still fall short.
I built Kretase — an open-source game server panel on Node.js/React with automated plugin, mod, and world managers
Hey everyone,
Over the past couple of weeks, I’ve been working on an open-source, self-hosted project called Kretase. It’s a game server management panel designed for Minecraft, built from scratch using Node.js and React.
I started this project because most of the existing solutions in this space felt bloated, dated, and lacked proper optimization. I wanted to tackle these issues head-on by building a modern, lightweight TypeScript stack that keeps resource consumption to a minimum while offering robust automation features.
Instead of making users handle manual file uploads, I spent a lot of time engineering built-in automation managers.
Core features and tech stack:
- Backend: Node.js (highly optimized telemetry, child process isolation, and stream-based file management).
- Frontend: React (slick, modern, and resource-efficient UI).
- Automated Plugin & Mod Manager: Handles direct fetching, installation, and dependency management without manual uploads.
- Built-in World Browser: Browse, install, backup, and download maps directly via CurseForge integration.
- Multi-node support: Manage multiple server nodes from a single dashboard.
- Live telemetry: Real-time CPU, RAM, and disk tracking.
- Deployment: A highly optimized, one-command install script for Ubuntu/Debian.
The project is fully open-source under the MIT license. To comply with link filters, I’ll drop the full GitHub repository and setup documentation in the comments below!
I’m really looking for some honest feedback from the Node.js community regarding the backend architecture, the way I'm handling file streams for mod/plugin downloads, and overall performance optimization.
Let me know your thoughts!
I built a canvas-based timeline visualisation library with virtualised rendering in Typescript
I wanted a library like vis.js but needed it canvas-based for server-side rendering without a headless browser in node, so I built one. I'd love to get some feedback.
Optique 1.1.0: Command discovery, value parsers, and ordered grammars
github.comHow we tied Slint's event loop into Node's libuv so the UI stops polling every 16 ms
slint.devdeno desktop can now convert typescript project into a mac, windows and linux app and instead unlike electron we can now opt for webview. also --compress option gets the packaged app size down from 65MB to 19MB
Deno 2.9 canary now can convert any typescript projects into self contained desktop apps for different OSes and unlike electron users can default OS web view or a bundled chromium backend.
Also, --compress option gets packaged app sizes down from 65MB to 19MB in my test with a basic app.
Official link https://docs.deno.com/runtime/desktop/
Should Node also have something similar?
Built a lightweight open-source Durable Objects runtime for Node.js
Tired of wiring up Redis + WebSockets + sticky sessions every time I wanted realtime features (chat, presence, collab cursors, etc.).
So I made Nalo — a single-node runtime where each live thing gets a stable address like /ws/room/lobby. One object owns state, connected clients, and event ordering. Zero heavy deps, simple persistence, and some fun browser demos.
Still v0.1 but works nicely.
Would love feedback!
Does adding features like RTR and immediate multi-device logout to JWT authentication eventually turn it into session-based authentication?
So, I've been learning about the differences between JWT and session-based authentication. I went with JWT for my project. But as I've taken the time to plan it out, I realized that after trying to make it feature-rich with things like immediate logout from another device, refresh token rotation (RTR), and reuse detection, I basically just reinvented session-based authentication, just in a more complicated way.
Each of these steps is adding an extra feature/part to JWT which at the end leads to it becoming stateful not stateless.
1) Let's start with a normal JWT authentication flow. Let's say I want to make it more secure and add RTR. That's fine, but I'd have to prevent old refresh tokens from working, which means I'd need to store the current refresh token (or its hash) in Redis or a database. But that's still fine because, unlike session-based authentication, I only have to access Redis/the database whenever the access token is refreshed, not on every request.
2) Then, to make logging in from multiple devices possible, I keep track of each device's valid refresh token using a family_id or device_id of some sort. Whenever I rotate a refresh token, I keep the same family_id because it's still the same device. I only create a new family_id whenever the users sign up or log in, that way I know its its own device.
3) Then I want to add immediate logout from other devices. I'd have to delete or invalidate the refresh token for the family_id of the device I want to log out. But there will still be a short window where the access token is valid, so the user stays logged in until it expires.
4) If I want to get rid of that window and make logout truly immediate, I'd have to keep track of revoked access tokens in Redis and check on every request whether the access token has been revoked.
But doesn't that defeat the whole purpose of JWT being stateless? I'm still checking Redis on every request. It feels like I just reinvented session-based authentication, except in a more complicated way.
Am I misunderstanding something, or trying to make the system too secure or what are your thoughts?
[NodeBook] Volume 2 has been released!
Hi all,
Nodebook's Volume 2 is now available to read online.
There have been a couple of changes to the curriculum. I've pushed the chapters on worker threads and child processes down to Volume 3, and moved the networking chapters - Networking Fundamentals, TLS, HTTPS & HTTP/2, and Realtime Streaming - up into Vol 2.
I've always wanted to keep this book targeted at intermediate-level Node/JS devs, but I added a networking fundamentals chapter because I feel many devs who work with Node don't really understand the underlying networking stuff.
As always, feedback is welcome.