JavaScript 68 🧬 Node.js basics
For most of JavaScript’s life, it ran only in the browser. Node.js changed that. It takes the V8 engine — the same one inside Chrome — and wraps it with an environment that can read files, open sockets, spawn processes, and run on servers. Suddenly JavaScript could do what PHP, Python, and Ruby did.
Node isn’t a framework or a language. It’s a runtime — a platform that executes JavaScript outside the browser, with a set of built-in modules for talking to the operating system. Understand those modules and you can build servers, CLIs, build tools, and scripts in the same language you use on the front-end.
Key point: Node.js is single-threaded and event-driven. It handles many connections at once not by spawning threads, but by never blocking — every I/O operation is asynchronous, and the event loop juggles them. That’s the mental model that makes Node feel different from Java or Python.
a – What is Node.js
Node is a JavaScript runtime built on Chrome’s V8 engine. It provides a set of built-in modules for files, networking, processes, and streams, and it includes npm — the largest package registry in the world.
What Node is not:
- Not a browser — no
window, nodocument, no DOM - Not a framework — no opinion about how you structure code
- Not multi-threaded by default — one main thread, async I/O
- Not just for servers — CLIs, build tools, scripts, and desktop apps use it
The two globals you get instead of window:
console.log(process.version);
console.log(process.platform);
console.log(process.cwd());
console.log(process.env.NODE_ENV);
The process object is how Node talks about itself. globalThis replaces window as the global object.
The built-in modules:
| Module | Purpose |
|---|---|
fs | Files and directories |
path | Path manipulation |
http / https | Servers and requests |
os | System info |
events | Event emitters |
stream | Streaming data |
crypto | Hashing, encryption |
url | URL parsing |
child_process | Run other programs |
worker_threads | True parallelism |
util | Utilities (promisify, inspect) |
Importing modules — two styles:
// CommonJS (older, still default for .js in most projects)
const fs = require('fs');
// ESM (modern, used in .mjs or "type": "module")
import fs from 'fs';
CommonJS is synchronous and simple. ESM is the standard. New projects should use ESM.
Running a script:
node script.js
Node executes the file, prints any output, and exits when the event loop is empty.
The REPL:
node
> 2 + 2
4
> process.version
'v20.10.0'
The interactive shell is useful for quick experiments.
Global objects unique to Node:
| Global | Purpose |
|---|---|
process | Runtime info, env vars, exit |
Buffer | Binary data |
__dirname | Directory of the file (CommonJS) |
__filename | Full path of the file |
global | Global object (like window) |
globalThis | Standard global |
In ESM, __dirname and __filename don’t exist — you derive them from import.meta.url.
The main selling points:
- One language across the stack — JavaScript on both ends
- Non-blocking I/O — high concurrency with low overhead
- Huge ecosystem — npm has millions of packages
- Fast startup — good for CLIs and serverless
- Built-in tooling — server, file system, streams, without extra installs
Where Node runs well:
- REST and GraphQL APIs
- Real-time apps (chat, collaboration)
- Build tools and bundlers
- CLIs and scripts
- Serverless functions
- Desktop apps (Electron)
Where Node struggles:
- CPU-intensive work — one thread, one core
- Heavy numeric computing — Python or C++ win
- Video encoding, image processing — native tools win
For CPU-bound work, use worker_threads or spawn a separate process.
b – File system and modules
The fs module is your interface to the disk. It reads, writes, renames, and deletes files and directories — synchronously or asynchronously.
The three API styles:
| Style | Example | When |
|---|---|---|
| Callback | fs.readFile(p, cb) | Legacy |
| Sync | fs.readFileSync(p) | Startup, scripts |
| Promise | fs.promises.readFile(p) | Modern async |
Reading a file:
import { readFile } from 'fs/promises';
const content = await readFile('data.txt', 'utf8');
console.log(content);
fs/promises gives you Promise-based methods. Always prefer this over callbacks in modern code.
Writing a file:
import { writeFile } from 'fs/promises';
await writeFile('output.txt', 'Hello, Node!');
writeFile overwrites by default. Use { flag: 'a' } to append.
Sync versions for startup code:
import { readFileSync } from 'fs';
const config = JSON.parse(readFileSync('config.json', 'utf8'));
Sync is fine for reading config at startup — the app isn’t serving anyone yet. Avoid sync in request handlers.
Directory operations:
import { readdir, mkdir, rm } from 'fs/promises';
const files = await readdir('./src');
await mkdir('./build', { recursive: true });
await rm('./tmp', { recursive: true, force: true });
readdir lists a directory. mkdir creates. rm deletes. Both mkdir and rm need { recursive: true } for nested paths.
Checking existence:
import { access } from 'fs/promises';
try {
await access('file.txt');
console.log('exists');
} catch {
console.log('missing');
}
access throws if the file doesn’t exist — cleaner than existsSync, which has race conditions.
Watching files:
import { watch } from 'fs';
watch('./src', { recursive: true }, (event, filename) => {
console.log(event, filename);
});
Fires when files change. Used by dev servers and build tools.
The path module:
Path concatenation is deceptively tricky across operating systems. Use path, not string concatenation.
import path from 'path';
path.join('src', 'utils', 'file.js'); // 'src/utils/file.js'
path.resolve('./src'); // '/absolute/path/to/src'
path.basename('/a/b/c.txt'); // 'c.txt'
path.dirname('/a/b/c.txt'); // '/a/b'
path.extname('file.txt'); // '.txt'
path.parse('/a/b/c.txt'); // { root, dir, base, ext, name }
join combines with the right separator for the OS. resolve produces an absolute path. The others extract pieces.
Paths in ESM:
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const configPath = join(__dirname, 'config.json');
import.meta.url is a file URL. fileURLToPath converts it to a normal path. This is the ESM equivalent of __dirname.
Creating your own modules:
// math.js
export function add(a, b) { return a + b; }
export const PI = 3.14159;
// main.js
import { add, PI } from './math.js';
Node supports ESM modules natively. Bare imports ('react') resolve from node_modules; relative imports ('./math.js') resolve from the file.
npm — Node’s package manager:
npm init -y
npm install express
npm install --save-dev jest
npm run test
npm installs packages into node_modules and records them in package.json. --save-dev marks a package as a development-only dependency.
The package.json file:
{
"name": "my-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node src/index.js",
"test": "node --test"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"jest": "^29.0.0"
}
}
type: "module"— enables ESMscripts— custom commands run withnpm rundependencies— needed at runtimedevDependencies— needed only for development
Common fs operations:
| Operation | API |
|---|---|
| Read file | readFile |
| Write file | writeFile |
| Append | writeFile(f, data, { flag: 'a' }) |
| Delete | rm / unlink |
| Rename | rename |
| List dir | readdir |
| Create dir | mkdir |
| Delete dir | rmdir / rm |
| Stat | stat |
| Watch | watch |
| Copy | copyFile |
Streaming large files:
Reading a 5GB file into memory is a bad idea. Use streams:
import { createReadStream } from 'fs';
const stream = createReadStream('big.log', 'utf8');
stream.on('data', chunk => process(chunk));
stream.on('end', () => console.log('done'));
Streams process data in chunks — memory stays low regardless of file size.
c – HTTP servers and the event loop
Node’s http module lets you build web servers without a framework. It’s minimal, but understanding it means understanding how frameworks like Express work underneath.
A basic server:
import { createServer } from 'http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, world!');
});
server.listen(3000, () => {
console.log('Listening on http://localhost:3000');
});
createServer takes a function that runs on every request. req is the request, res is the response.
Routing by hand:
const server = createServer((req, res) => {
if (req.method === 'GET' && req.url === '/') {
res.end('Home');
} else if (req.method === 'GET' && req.url === '/users') {
res.end('Users');
} else {
res.writeHead(404);
res.end('Not found');
}
});
Frameworks exist to make this cleaner — but the primitive is just a function that inspects method and url.
Sending JSON:
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ users: [] }));
Always set the Content-Type header. The browser won’t parse the response as JSON otherwise.
Reading the request body:
let body = '';
req.on('data', chunk => (body += chunk));
req.on('end', () => {
const data = JSON.parse(body);
res.end('received');
});
The body arrives as a stream. Collect the chunks, then parse. For large bodies or file uploads, stream to disk instead of buffering.
The events module:
Node is built on EventEmitter — the observer pattern from JavaScript 64.
import { EventEmitter } from 'events';
const emitter = new EventEmitter();
emitter.on('greet', name => console.log(`Hello, ${name}`));
emitter.emit('greet', 'Alice');
Everything that streams or fires events — servers, sockets, files — is an EventEmitter. Understanding it is understanding Node.
The event loop in Node:
┌──────────────────────────────────────────────┐
│ Node.js Event Loop │
│ │
│ 1. Timers (setTimeout, setInterval) │
│ 2. Pending callbacks (I/O) │
│ 3. Idle / prepare (internal) │
│ 4. Poll (incoming I/O) │
│ 5. Check (setImmediate) │
│ 6. Close callbacks │
│ │
│ Between each phase: │
│ - process.nextTick queue │
│ - Promise microtasks │
│ │
└──────────────────────────────────────────────┘
The phases cycle. Non-blocking operations schedule callbacks. When the loop has nothing to do, it blocks on the poll phase until an event arrives.
process.nextTick vs setImmediate:
process.nextTick(() => console.log('nextTick'));
setImmediate(() => console.log('immediate'));
Promise.resolve().then(() => console.log('promise'));
// Output:
// [ nextTick ]
// [ promise ]
// [ immediate ]
process.nextTick— runs before the loop continues, after the current operation- Promise
.then— microtask, same idea setImmediate— runs in the check phase of the next loop iteration
Why this matters: Never block the event loop. A synchronous loop over a million items stops everything — other requests, timers, and callbacks wait.
Blocking vs non-blocking:
// ❌ Blocks the event loop
const data = fs.readFileSync('big.json');
// ✅ Non-blocking
const data = await fs.promises.readFile('big.json');
The sync version works — but every other request during that read is stuck. In a server, that’s a denial-of-service.
Environment variables:
const PORT = process.env.PORT || 3000;
const DB_URL = process.env.DATABASE_URL;
Config comes from the environment, not hardcoded values. Use dotenv to load a .env file in development.
Graceful shutdown:
process.on('SIGTERM', () => {
server.close(() => {
console.log('Shut down cleanly');
process.exit(0);
});
});
Catch termination signals, close connections, then exit. Otherwise in-flight requests fail.
A minimal Express-like server:
import { createServer } from 'http';
const routes = new Map();
function get(path, handler) {
routes.set(`GET ${path}`, handler);
}
get('/users', (req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify([{ id: 1, name: 'Alice' }]));
});
const server = createServer((req, res) => {
const key = `${req.method} ${req.url}`;
const handler = routes.get(key);
if (handler) handler(req, res);
else {
res.writeHead(404);
res.end('Not found');
}
});
server.listen(3000);
Express and Fastify build on this. Knowing the primitive helps when debugging, even if you use a framework.
Complete Example Session
// ============================================
// PART 1: PROCESS INFO
// ============================================
console.log(process.version);
// [ 'v20.10.0' ]
console.log(process.platform);
// [ 'linux' ]
console.log(process.cwd());
// [ '/home/user/project' ]
// ============================================
// PART 2: READ A FILE
// ============================================
import { readFile } from 'fs/promises';
const content = await readFile('data.txt', 'utf8');
console.log(content);
// [ file contents ]
// ============================================
// PART 3: WRITE A FILE
// ============================================
import { writeFile } from 'fs/promises';
await writeFile('output.txt', 'Hello, Node!');
// ============================================
// PART 4: LIST DIRECTORY
// ============================================
import { readdir } from 'fs/promises';
const files = await readdir('./src');
console.log(files);
// [ [ 'index.js', 'utils.js', 'api.js' ] ]
// ============================================
// PART 5: PATH UTILITIES
// ============================================
import path from 'path';
console.log(path.join('src', 'utils.js'));
// [ 'src/utils.js' ]
console.log(path.basename('/a/b/c.txt'));
// [ 'c.txt' ]
console.log(path.extname('file.txt'));
// [ '.txt' ]
// ============================================
// PART 6: ESM __DIRNAME
// ============================================
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log(join(__dirname, 'config.json'));
// [ '/home/user/project/config.json' ]
// ============================================
// PART 7: BASIC HTTP SERVER
// ============================================
import { createServer } from 'http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, world!');
});
server.listen(3000, () => {
console.log('http://localhost:3000');
});
// ============================================
// PART 8: ROUTING
// ============================================
const server2 = createServer((req, res) => {
if (req.url === '/') {
res.end('Home');
} else if (req.url === '/users') {
res.end(JSON.stringify([{ id: 1 }]));
} else {
res.writeHead(404);
res.end('Not found');
}
});
// ============================================
// PART 9: EVENT EMITTER
// ============================================
import { EventEmitter } from 'events';
const emitter = new EventEmitter();
emitter.on('greet', name => console.log(`Hello, ${name}`));
emitter.emit('greet', 'Alice');
// [ Hello, Alice ]
// ============================================
// PART 10: PROCESS.NEXTTICK VS SETIMMEDIATE
// ============================================
process.nextTick(() => console.log('nextTick'));
setImmediate(() => console.log('immediate'));
Promise.resolve().then(() => console.log('promise'));
// Output:
// [ nextTick ]
// [ promise ]
// [ immediate ]
// ============================================
// PART 11: ENV VARIABLES
// ============================================
const PORT = process.env.PORT || 3000;
console.log(`Starting on port ${PORT}`);
// [ Starting on port 3000 ]
// ============================================
// PART 12: GRACEFUL SHUTDOWN
// ============================================
process.on('SIGTERM', () => {
console.log('Shutting down');
server.close(() => process.exit(0));
});
// ============================================
// PART 13: READING JSON CONFIG
// ============================================
import { readFileSync } from 'fs';
const config = JSON.parse(readFileSync('config.json', 'utf8'));
console.log(config.port);
// [ 3000 ]
// ============================================
// PART 14: STREAMING A FILE
// ============================================
import { createReadStream } from 'fs';
const stream = createReadStream('big.log', 'utf8');
stream.on('data', chunk => {
// process each chunk
});
stream.on('end', () => console.log('done'));
// ============================================
// PART 15: SIMPLE CLI
// ============================================
// $ node greet.js Alice
const name = process.argv[2] || 'World';
console.log(`Hello, ${name}`);
// [ Hello, Alice ]
// ============================================
// PART 16: SPAWN A PROCESS
// ============================================
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
const { stdout } = await execAsync('ls -la');
console.log(stdout);
Quick Reference
Global Objects
| Object | Purpose |
|---|---|
process | Runtime info, env, exit |
global | Global object |
globalThis | Standard global |
Buffer | Binary data |
__dirname | File’s directory (CJS) |
__filename | Full path (CJS) |
import.meta.url | File URL (ESM) |
process Properties
| Property | Meaning |
|---|---|
process.version | Node version |
process.platform | OS |
process.cwd() | Current dir |
process.env | Environment vars |
process.argv | CLI arguments |
process.pid | Process ID |
process.exit(code) | Exit |
process.nextTick(fn) | Run before next phase |
fs/promises API
| Method | Purpose |
|---|---|
readFile(p, enc) | Read file |
writeFile(p, data) | Write file |
appendFile(p, data) | Append |
readdir(dir) | List dir |
mkdir(p, opts) | Create dir |
rm(p, opts) | Delete |
rename(a, b) | Rename |
stat(p) | File info |
copyFile(a, b) | Copy |
access(p) | Check exists |
path Module
| Method | Returns |
|---|---|
path.join(...) | Joined path |
path.resolve(...) | Absolute path |
path.basename(p) | Filename |
path.dirname(p) | Directory |
path.extname(p) | Extension |
path.parse(p) | Parts object |
http Module
| Method | Purpose |
|---|---|
createServer(handler) | Create server |
server.listen(port, cb) | Start |
server.close(cb) | Stop |
res.writeHead(status, headers) | Status + headers |
res.write(data) | Write chunk |
res.end(data) | Finish |
Event Loop Phases
| Phase | Handles |
|---|---|
| Timers | setTimeout, setInterval |
| Pending | I/O callbacks |
| Poll | New I/O |
| Check | setImmediate |
| Close | Close callbacks |
Microtask Priority
| Source | Priority |
|---|---|
process.nextTick | Highest |
Promise .then | High |
setImmediate | Loop phase |
setTimeout | Loop phase |
CLI Arguments
| Code | Meaning |
|---|---|
process.argv[0] | Node path |
process.argv[1] | Script path |
process.argv[2..] | User args |
Best Practices
✅ Do This:
// Use fs/promises for async work
import { readFile } from 'fs/promises';
// Use path.join for cross-platform paths
const p = path.join('src', 'file.js');
// Use import.meta.url in ESM
const __dirname = dirname(fileURLToPath(import.meta.url));
// Use env vars for config
const PORT = process.env.PORT || 3000;
// Handle SIGTERM for graceful shutdown
process.on('SIGTERM', () => server.close(() => process.exit(0)));
// Use streams for large files
createReadStream('big.log').pipe(dest);
// Prefer async over sync in servers
const data = await readFile('data.json');
// Set Content-Type headers
res.writeHead(200, { 'Content-Type': 'application/json' });
❌ Don’t Do This:
// Don't block the event loop
const data = readFileSync('big.json'); // ❌ in server
// Don't concatenate paths with strings
const p = 'src' + '/' + 'file.js'; // ❌ cross-platform
// Don't hardcode config
const PORT = 3000; // ⚠️ use env
// Don't forget Content-Type
res.end(JSON.stringify(data)); // ❌ client can't parse
// Don't ignore SIGTERM
// (in-flight requests fail) // ❌
// Don't read huge files into memory
const big = await readFile('5GB.log'); // ❌ use streams
// Don't use __dirname in ESM
console.log(__dirname); // ❌ ReferenceError
// Don't block startup with unnecessary sync calls
readFileSync('big.json'); // ⚠️ slow startup
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
__dirname in ESM | ReferenceError | Use import.meta.url |
| Sync I/O in server | Blocks event loop | Use async |
| Path string concat | Breaks on Windows | path.join |
| Missing Content-Type | Client can’t parse | Set header |
| No SIGTERM handler | Requests fail on restart | Handle signal |
| Read whole file | Memory blowup | Stream |
require in ESM | SyntaxError | Use import |
Forgot type: module | import fails | Set in package.json |
| Blocking CPU work | Everything waits | worker_threads |
Real-World Examples
1. Read a file
import { readFile } from 'fs/promises';
const text = await readFile('data.txt', 'utf8');
The modern async read.
2. Write a file
import { writeFile } from 'fs/promises';
await writeFile('log.txt', 'entry\n', { flag: 'a' });
Append with { flag: 'a' }.
3. List a directory
import { readdir } from 'fs/promises';
const files = await readdir('./src');
Returns filenames as an array.
4. Join paths
import path from 'path';
const file = path.join('src', 'utils', 'helper.js');
Cross-platform path building.
5. ESM __dirname
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
The ESM equivalent of the CommonJS global.
6. Basic HTTP server
import { createServer } from 'http';
createServer((req, res) => res.end('Hi')).listen(3000);
The smallest useful server.
7. JSON endpoint
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true }));
Set the header, serialize the object.
8. Event emitter
const emitter = new EventEmitter();
emitter.on('data', handler);
emitter.emit('data', payload);
Node’s core communication primitive.
9. Read env var
const port = process.env.PORT || 3000;
Config from the environment.
10. Graceful shutdown
process.on('SIGTERM', () => {
server.close(() => process.exit(0));
});
Close cleanly when the OS asks you to stop.
Visual: Node’s Architecture
┌──────────────────────────────────────────────┐
│ Your JavaScript │
│ │
│ app.js, routes, handlers │
│ │
└─────────────────┬────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Node.js APIs │
│ │
│ fs, http, path, events, streams │
│ │
└─────────────────┬────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ libuv │ V8 │ C++ bindings │
│ │
│ Event loop, thread pool, file system, │
│ networking, JavaScript engine │
│ │
└──────────────────────────────────────────────┘
Visual: The Event Loop in Node
┌──────────────────────────────────────────────┐
│ ┌───────────┐ │
│ │ timers │ setTimeout, setInterval │
│ └─────┬─────┘ │
│ ▼ │
│ ┌───────────┐ │
│ │ pending │ I/O callbacks │
│ └─────┬─────┘ │
│ ▼ │
│ ┌───────────┐ │
│ │ poll │ new I/O │
│ └─────┬─────┘ │
│ ▼ │
│ ┌───────────┐ │
│ │ check │ setImmediate │
│ └─────┬─────┘ │
│ ▼ │
│ ┌───────────┐ │
│ │ close │ cleanup callbacks │
│ └─────┬─────┘ │
│ │ │
│ └──────► repeat │
│ │
│ Between phases: nextTick and microtasks │
│ │
└──────────────────────────────────────────────┘
Visual: Sync vs Async I/O
┌──────────────────────────────────────────────┐
│ Sync │
│ │
│ Request 1 ──► readFileSync ──► blocks │
│ Request 2 ──► waits │
│ Request 3 ──► waits │
│ │
│ One at a time, slow │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ Async │
│ │
│ Request 1 ──► readFile ──► schedules │
│ Request 2 ──► readFile ──► schedules │
│ Request 3 ──► readFile ──► schedules │
│ │
│ All in flight at once, fast │
│ │
└──────────────────────────────────────────────┘
Summary
| Concept | Module | Example |
|---|---|---|
| Runtime | process | process.version |
| Files | fs/promises | readFile, writeFile |
| Paths | path | path.join |
| HTTP | http | createServer |
| Events | events | EventEmitter |
| Streams | stream | createReadStream |
| URL | url | fileURLToPath |
| Child processes | child_process | exec |
| Config | process.env | PORT |
| CLI args | process.argv | argv[2] |
| Graceful exit | process.on | SIGTERM |
| ESM dirname | import.meta.url | fileURLToPath |
| Package manager | npm | npm install |
| Project config | package.json | scripts, deps |
Key takeaways:
- Node.js is a JavaScript runtime — JavaScript outside the browser
- It provides built-in modules:
fs,path,http,events,stream,crypto processreplaceswindow— it exposes env vars, argv, and runtime infofs/promisesis the modern way to work with files — always prefer async over sync in servers- Use
path.joinfor cross-platform paths, never string concatenation - In ESM, derive
__dirnamefromimport.meta.urlandfileURLToPath http.createServeris the primitive under Express, Fastify, and every Node frameworkEventEmitteris Node’s core communication pattern — servers, sockets, and streams all use it- The event loop runs phases in order: timers, pending, poll, check, close
process.nextTickand Promises run before the next phase — highest priority- Never block the event loop — sync I/O and CPU loops stall everything
- Use streams for large files and network data — memory stays low
- Configure via
process.env, not hardcoded values - Handle
SIGTERMfor graceful shutdown — close servers, finish requests, exit clean - npm installs packages into
node_modulesand records them inpackage.json - Set
"type": "module"to use ESM natively
Remember: Node.js is JavaScript with an operating system underneath. It’s fast at I/O because it never blocks, and simple because it has one thread. Learn fs/promises, path, http, and events and you can build servers, CLIs, and scripts without a framework. Understand the event loop and you’ll know why sync code is dangerous. Configure with env vars, shut down gracefully, and stream large data. Master Node basics, and you can write JavaScript for servers with the same language you use in the browser.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!