The node:path module provides utilities for joining, resolving, normalizing, and inspecting file and directory paths cleanly across Windows (\) and POSIX (/ on Linux/macOS) systems. Never concatenate file paths with string + '/' +—let node:path handle separators and edge cases automatically.
Use path.join() to combine relative segments safely and path.basename(), path.dirname(), and path.extname() to inspect parts of a filepath.
import path from 'node:path';
const uploadsDir = path.resolve(import.meta.dirname, 'storage', 'uploads');
const targetFile = path.join(uploadsDir, '2026', 'invoice-104.pdf');
console.log('Full path:', targetFile);
console.log('Folder:', path.dirname(targetFile));
console.log('Filename:', path.basename(targetFile));
console.log('Name only:', path.basename(targetFile, path.extname(targetFile)));
console.log('Extension:', path.extname(targetFile));
Note the subtle difference between path.join() and path.resolve(): path.join('/a', '/b') returns '/a/b', whereas path.resolve('/a', '/b') treats '/b' as a new root path and returns '/b'.
path.relative()When accepting a user-supplied file name inside a static or download handler, verify that the resolved path never climbs out of the intended root folder using .. segments.
function safeResolve(baseDir, userPath) {
const resolvedBase = path.resolve(baseDir);
const resolvedTarget = path.resolve(resolvedBase, userPath);
const rel = path.relative(resolvedBase, resolvedTarget);
if (rel.startsWith('..') || path.isAbsolute(rel)) {
throw new Error('Blocked unsafe path traversal');
}
return resolvedTarget;
}
path.join() for URL strings: On Windows, path.join('api', 'users') produces 'api\users' with backslashes, which breaks HTTP URLs. Use new URL() or path.posix.join() for URL paths.path.join() blocks .. traversal: path.join('/app/public', '../../etc/passwd') dutifully simplifies to '/etc/passwd'. Always verify the resolved path stays inside baseDir.. with .split('.').pop(): Multi-dot names like archive.tar.gz or extensionless files behave inconsistently. Use path.extname() or path.parse().path.parse('/dir/app.config.json') return?It returns an object { root, dir, base, ext, name } so you can read every segment of a filepath in one call.
path.posix explicitly?Use path.posix when manipulating URL paths, Docker container Linux paths, or S3 object keys on a Windows development machine.
path.sep?path.sep holds the OS-specific path separator ('/' on Linux/macOS and '\' on Windows).
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.