String-concatenated paths break on Windows and when scripts run from another folder.
Never glue paths with + "/" +. The node:path module knows the platform's separator and normalises .. and duplicate slashes:
path.join("a", "b", "../c.txt")→a/c.txt— joins and normalises segments.path.resolve("data", "x.json")→ an absolute path, resolved against the current working directory unless a segment is already absolute.path.dirname,path.basename(p, ".js"),path.extname— take paths apart;path.parsereturns all parts as an object.path.relative(from, to)— the path from one location to another.path.sepis/on POSIX and\on Windows;path.posixandpath.win32force a style (useposixfor URL-like paths).
The crucial distinction is where relative paths resolve: against process.cwd(), the directory the user launched Node from. To find a file next to your module regardless of where the process started, anchor on the module itself: path.join(import.meta.dirname, "templates", "email.html").
ES modules identify themselves with a file URL (import.meta.url, e.g. file:///home/me/app/main.js). Most fs functions accept a URL directly, and node:url converts both ways with fileURLToPath and pathToFileURL. new URL("./data.json", import.meta.url) is a neat way to locate a sibling file.
The node:os module answers questions about the machine: os.cpus().length (or better, os.availableParallelism()) for sizing worker pools, os.tmpdir(), os.homedir(), os.EOL, os.totalmem() / os.freemem(), os.platform().
Example
import path from "node:path";
import os from "node:os";
import { fileURLToPath } from "node:url";
import { readFile } from "node:fs/promises";
console.log(path.join("logs", "2025", "..", "app.log")); // logs/app.log
console.log(path.extname("photo.final.jpeg")); // .jpeg
console.log(path.parse("/srv/app/index.js").name); // index
// Anchor on this module, not on process.cwd()
const tpl = path.join(import.meta.dirname, "templates", "welcome.txt");
console.log(path.relative(process.cwd(), tpl));
// URL-based alternative
const dataUrl = new URL("./package.json", import.meta.url);
console.log(fileURLToPath(dataUrl));
const pkg = JSON.parse(await readFile(dataUrl, "utf8")); // fs accepts URLs
console.log(os.availableParallelism(), "cores,", os.tmpdir());Remember
- Use
path.join/path.resolve, never string concatenation - Relative paths resolve against
process.cwd(), not the module's folder - Anchor on
import.meta.dirnameornew URL(..., import.meta.url)
Watch out for
- Using
path.jointo build URLs on Windows — it inserts backslashes; usepath.posixorURL.