With the environment installed and the escena-viva/ folder created, it is time to write code. In this lesson we will build the project's first real program: src/catalog.js, a script that defines Escena Viva's event catalog and prints it to the console, with the option of filtering it by venue from the command line.
Along the way you will discover the practical differences between running JavaScript in the browser and in Node.js, meet the process object, learn to tell standard output apart from error output, and find out what a program's exit code means. These concepts look minor and turn out to be fundamental the moment your code stops being an exercise and starts living inside a server or a deployment pipeline.
Contents
- Writing and running your first script
- The browser and Node.js: what is there and what is not
- The
processobject: your window onto the system - The Escena Viva catalog:
src/catalog.js - Displaying data:
console.log,console.tableand template literals - Reading arguments with
process.argv console.error, stdout and stderr- Exit codes and
process.exit - Debugging the classic syntax error
- What this program does not do yet
- Writing and Running Your First Script
Move into the project folder and create a test file inside src/:
Create src/hello.js with this content:
// src/hello.js
// The first program of the course: checking that Node runs our code.
console.log('Escena Viva: environment up and running');
console.log('Node version:', process.version);
console.log('Working directory:', process.cwd());Run it:
Escena Viva: environment up and running Node version: v24.5.0 Working directory: /home/user/projects/escena-viva
Three important details about this first run:
- The path is relative to the directory you run
nodefrom, not to the file. If you were insidesrc/, the command would benode hello.js. - The
.jsextension is optional:node src/helloworks too. Write it anyway; it is clearer. - There is no compilation and no prior configuration. You do not need a
package.json, you do not need to install anything, and you do not need to declare amain. Node reads the file and runs it.
- The Browser and Node.js: What Is There and What Is Not
If you come from front-end development, your instinct will be to reach for things that do not exist here. Let's check:
// src/differences.js
// Which global objects exist in Node and which do not.
console.log('typeof window :', typeof window); // undefined
console.log('typeof document :', typeof document); // undefined
console.log('typeof alert :', typeof alert); // undefined
console.log('typeof global :', typeof global); // object
console.log('typeof process :', typeof process); // object
console.log('typeof console :', typeof console); // object
console.log('typeof fetch :', typeof fetch); // functiontypeof window : undefined typeof document : undefined typeof alert : undefined typeof global : object typeof process : object typeof console : object typeof fetch : function
A summary of the equivalences:
| Task | Browser | Node.js |
|---|---|---|
| Global object | window |
global |
| Global object (standard in both) | globalThis |
globalThis |
| Displaying information | console.log, alert |
console.log (there is no alert) |
| Manipulating the interface | document.querySelector(...) |
Does not exist: there is no interface |
| HTTP request | fetch (with CORS restrictions) |
fetch (no CORS) or the http/https modules |
| Storing data locally | localStorage |
Files (fs) or a database |
| Reading input parameters | location.search |
process.argv |
| Configuration variables | Baked into the bundle | process.env |
| Ending execution | Closing the tab | process.exit() |
| Timers | setTimeout, setInterval |
The same ones, plus setImmediate |
console.log works in both environments, but it does not do the same thing: in the browser it writes to the developer tools console; in Node it writes to the process's standard output, which is what you see in the terminal and what can be redirected to a file or to another program. We will come back to this in section 7.
- The
process Object: Your Window onto the System
process Object: Your Window onto the Systemprocess is a global object representing the operating system process your program runs in. It is the gateway to everything surrounding your code.
| Property or method | What it gives you |
|---|---|
process.argv |
An array with the command-line arguments |
process.env |
An object with the environment variables |
process.version |
The Node version (v24.5.0) |
process.platform |
'linux', 'darwin', 'win32' |
process.cwd() |
The current working directory |
process.uptime() |
How many seconds the process has been alive |
process.memoryUsage() |
Memory usage in bytes |
process.exit(code) |
Ends the process with an exit code |
process.exitCode |
Sets the exit code without cutting execution short |
process.stdout / process.stderr |
The standard output and error streams |
A handy example for diagnosing environments:
// src/environment.js
// A quick diagnosis of Escena Viva's runtime environment.
const memory = process.memoryUsage();
console.log(`Node : ${process.version}`);
console.log(`Platform : ${process.platform}`);
console.log(`Directory : ${process.cwd()}`);
console.log(`Heap memory : ${Math.round(memory.heapUsed / 1024 / 1024)} MB`);
- The Escena Viva Catalog:
src/catalog.js
src/catalog.jsNow for the real program. Escena Viva runs events at three venues: the Teatro Almendra, the Sala Bóveda and the Auditorio Ribera. Every event has one or more sessions, and every session has a date, a capacity, a number of tickets sold and a price.
One design decision we adopt from the very first minute: prices are stored in cents, as whole numbers. Never 25.50, always 2550. The reason is that JavaScript's number type is floating point and produces surprises like 0.1 + 0.2 === 0.30000000000000004. With money, that is unacceptable. We will formalize this and other conventions in The Course Project.
Create src/catalog.js:
// src/catalog.js
// Escena Viva event catalog.
// For now the data is written in the file itself; in module 3
// we will read it from data/events.json.
const catalog = [
{
id: 'evt-001',
title: 'Concierto de Otono',
venue: 'Teatro Almendra',
category: 'concert',
durationMinutes: 95,
sessions: [
{ id: 'ses-001-1', dateTime: '2026-10-03T20:00:00', capacity: 420, sold: 180, priceCents: 2500 },
{ id: 'ses-001-2', dateTime: '2026-10-04T19:00:00', capacity: 420, sold: 96, priceCents: 2200 }
]
},
{
id: 'evt-002',
title: 'Noche de Monologos',
venue: 'Sala Boveda',
category: 'comedy',
durationMinutes: 80,
sessions: [
{ id: 'ses-002-1', dateTime: '2026-10-10T21:30:00', capacity: 120, sold: 118, priceCents: 1800 },
{ id: 'ses-002-2', dateTime: '2026-10-11T21:30:00', capacity: 120, sold: 45, priceCents: 1800 },
{ id: 'ses-002-3', dateTime: '2026-10-17T21:30:00', capacity: 120, sold: 12, priceCents: 1500 }
]
},
{
id: 'evt-003',
title: 'Festival de Jazz de Primavera',
venue: 'Auditorio Ribera',
category: 'festival',
durationMinutes: 240,
sessions: [
{ id: 'ses-003-1', dateTime: '2027-04-17T19:00:00', capacity: 900, sold: 640, priceCents: 3800 },
{ id: 'ses-003-2', dateTime: '2027-04-18T19:00:00', capacity: 900, sold: 720, priceCents: 4200 }
]
}
];Notice one deliberate detail: the text values that will end up inside identifiers or file names avoid accents and ñ (Concierto de Otono, Sala Boveda). In the data shown to the end user we will eventually use the correct spelling, but while we are working at the console and with technical names, keeping things simple saves us encoding headaches. It is a project convention, not a limitation of Node.
- Displaying Data:
console.log, console.table and Template Literals
console.log, console.table and Template LiteralsNext, in the same file, add one function that formats the price and another that prints the catalog.
// --- Presentation helpers ---
// Turns 2500 (cents) into the string "25.00 EUR".
function formatPrice(cents) {
const euros = Math.floor(cents / 100);
const remainder = String(cents % 100).padStart(2, '0');
return `${euros}.${remainder} EUR`;
}
// Turns "2026-10-03T20:00:00" into "03/10/2026 20:00".
function formatDate(isoDate) {
const date = new Date(isoDate);
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${day}/${month}/${year} ${hours}:${minutes}`;
}An explanation of the new pieces, for anyone arriving with only basic JavaScript:
- Template literals (backticks):
`${euros}.${remainder} EUR`lets you embed expressions inside a string without concatenating with+. It is more readable and it accepts real line breaks. padStart(2, '0'): pads on the left until the string reaches 2 characters. It turns5into"05", which is what we want for dates and cents.Math.floor(2500 / 100)gives the whole euros;2500 % 100gives the leftover cents. By always working with integers there are no rounding errors.
Now the listing itself:
// --- Catalog presentation ---
function showCatalog(events) {
console.log('');
console.log('==========================================');
console.log(' ESCENA VIVA - EVENT CATALOG');
console.log('==========================================');
for (const event of events) {
// Total tickets available, adding up every session.
let totalAvailable = 0;
for (const session of event.sessions) {
totalAvailable += session.capacity - session.sold;
}
console.log('');
console.log(`${event.title} [${event.id}]`);
console.log(` Venue : ${event.venue}`);
console.log(` Category : ${event.category}`);
console.log(` Duration : ${event.durationMinutes} min`);
console.log(` Sessions : ${event.sessions.length}`);
console.log(` Available : ${totalAvailable} tickets`);
for (const session of event.sessions) {
const available = session.capacity - session.sold;
const occupancy = Math.round((session.sold / session.capacity) * 100);
console.log(
` - ${formatDate(session.dateTime)} ` +
`${formatPrice(session.priceCents)} ` +
`${available}/${session.capacity} available (${occupancy}% full)`
);
}
}
console.log('');
}console.table: an effortless table
Node includes console.table, which draws an array of objects as an ASCII table. It is perfect for inspecting data quickly.
// A compact table view.
function showSummaryTable(events) {
// We build a "flat" array: console.table expects simple objects.
const rows = events.map((event) => {
let totalCapacity = 0;
let totalSold = 0;
for (const session of event.sessions) {
totalCapacity += session.capacity;
totalSold += session.sold;
}
return {
Event: event.title,
Venue: event.venue,
Sessions: event.sessions.length,
Capacity: totalCapacity,
Sold: totalSold,
Occupancy: `${Math.round((totalSold / totalCapacity) * 100)}%`
};
});
console.table(rows);
}Output:
┌─────────┬─────────────────────────────────┬────────────────────┬──────────┬──────────┬──────┬───────────┐ │ (index) │ Event │ Venue │ Sessions │ Capacity │ Sold │ Occupancy │ ├─────────┼─────────────────────────────────┼────────────────────┼──────────┼──────────┼──────┼───────────┤ │ 0 │ 'Concierto de Otono' │ 'Teatro Almendra' │ 2 │ 840 │ 276 │ '33%' │ │ 1 │ 'Noche de Monologos' │ 'Sala Boveda' │ 3 │ 360 │ 175 │ '49%' │ │ 2 │ 'Festival de Jazz de Primavera' │ 'Auditorio Ribera' │ 2 │ 1800 │ 1360 │ '76%' │ └─────────┴─────────────────────────────────┴────────────────────┴──────────┴──────────┴──────┴───────────┘
Other console methods worth knowing:
| Method | Use |
|---|---|
console.log(...) |
Normal output (stdout) |
console.error(...) |
Error output (stderr) |
console.warn(...) |
Same as error: it goes to stderr |
console.table(array) |
ASCII table |
console.dir(obj, { depth: null }) |
Inspects a nested object without truncating it |
console.time('t') / console.timeEnd('t') |
Measures how long a block takes |
console.count('x') |
Counts how many times a point is reached |
- Reading Arguments with
process.argv
process.argvWe want to be able to run:
and see only the events at that venue. Arguments arrive in process.argv, an array of strings.
[ '/home/user/.nvm/versions/node/v24.5.0/bin/node', '/home/user/projects/escena-viva/src/catalog.js', 'Sala Boveda', '--table' ]
The structure is always the same:
| Index | Content |
|---|---|
0 |
The absolute path of the Node executable |
1 |
The absolute path of the script being run |
2 onwards |
The arguments the user typed |
Hence the usual idiom: process.argv.slice(2).
// --- Reading the arguments ---
const args = process.argv.slice(2);
// The first argument that does not start with "--" is read as a venue.
const venueFilter = args.find((arg) => !arg.startsWith('--'));
const useTable = args.includes('--table');
// We filter the catalog if a venue was given.
let displayedEvents = catalog;
if (venueFilter) {
displayedEvents = catalog.filter(
(event) => event.venue.toLowerCase() === venueFilter.toLowerCase()
);
}Comparing in lower case with toLowerCase() makes the filter forgiving: "sala boveda" and "Sala Boveda" both work. It is a small detail with a big effect on the usability of a command-line tool.
For more complex arguments (options with values, combined flags), Node includes
util.parseArgs, and the ecosystem offers packages such ascommanderoryargs. We will look at them when we reach npm in Module 5.
console.error, stdout and stderr
console.error, stdout and stderrEvery operating system process has two separate output channels:
- stdout (standard output): the program's useful result.
- stderr (error output): error messages, warnings and diagnostics.
They are separate for a practical reason: it lets you redirect the result to a file without mixing errors into it.
# Only the catalog goes to the file; errors still show up on screen
node src/catalog.js > reports/catalog.txt
# Redirect the errors to another file as well
node src/catalog.js > reports/catalog.txt 2> reports/errors.txtflowchart LR
P["Node process<br/>src/catalog.js"] -->|"stdout (1)<br/>console.log"| A["Terminal or<br/>reports/catalog.txt"]
P -->|"stderr (2)<br/>console.error"| B["Terminal or<br/>reports/errors.txt"]
If you mix errors into console.log, anyone redirecting your output to a file will find error messages embedded among the data. Rule: data through console.log, everything else through console.error.
Let's apply it to the venue filter:
// --- Validating the filter ---
if (venueFilter && displayedEvents.length === 0) {
// This is a diagnostic, not data: it goes to stderr.
console.error(`Error: there are no events at venue "${venueFilter}".`);
console.error('Available venues:');
for (const venue of new Set(catalog.map((event) => event.venue))) {
console.error(` - ${venue}`);
}
process.exit(1);
}new Set(...) removes duplicates: if two events share a venue, it only appears once. We will look at this more calmly in Modern JavaScript for Node.js.
- Exit Codes and
process.exit
process.exitWhen a program ends, it returns an integer to the operating system: the exit code.
| Code | Conventional meaning |
|---|---|
0 |
Success |
1 |
Generic error |
2 |
Incorrect usage (badly written arguments) |
> 2 |
Specific codes defined by your application |
You can check it after running a command:
This is what lets you chain commands safely in a deployment:
# The report is only generated if the catalog validated correctly
node src/catalog.js --validate && node src/report.jsUsing process.exit() responsibly
process.exit(1) kills the process immediately. It is a blunt instrument: if there are pending file writes or network responses, they may be left half done.
The recommended alternative in most cases is to assign process.exitCode and let the program finish naturally:
// Preferable: sets the exit code but lets things wind down cleanly
if (venueFilter && displayedEvents.length === 0) {
console.error(`Error: there are no events at venue "${venueFilter}".`);
process.exitCode = 1;
return; // If we are inside a function
}| Form | When to use it |
|---|---|
process.exitCode = 1 |
Almost always: safe, lets pending tasks complete |
process.exit(1) |
Fatal errors in simple scripts, or when you have no choice but to stop |
We close the file with the execution itself:
// --- Execution ---
if (useTable) {
showSummaryTable(displayedEvents);
} else {
showCatalog(displayedEvents);
}
console.log(`Total: ${displayedEvents.length} event(s) shown.`);Try it out:
node src/catalog.js # The whole catalog, detailed format
node src/catalog.js --table # The whole catalog, table format
node src/catalog.js "Teatro Almendra" # A single venue
node src/catalog.js "Nonexistent Venue" # Handled error, exit code 1
- Debugging the Classic Syntax Error
Introduce a fault deliberately: delete a closing brace in the catalog array and run the script.
/home/user/projects/escena-viva/src/catalog.js:34
];
^
SyntaxError: Unexpected token ']'
at wrapSafe (node:internal/modules/cjs/loader:1281:20)
at Module._compile (node:internal/modules/cjs/loader:1321:27)
...
Node.js v24.5.0How to read this message, from top to bottom:
.../src/catalog.js:34: the file and line where Node noticed the problem.- The code fragment and the
^: the exact token that did not fit. SyntaxError: Unexpected token ']': the type of error.- The call stack (
at wrapSafe...): in syntax errors these are Node's internal functions; ignore it, it tells you nothing.
A key point that confuses a lot of people: the line Node reports is where the parser choked, not necessarily where the mistake is. If you forget a brace on line 20, the error may point at line 34. Search upwards from the reported line.
Common errors and their messages:
| Message | Usual cause |
|---|---|
SyntaxError: Unexpected token '}' |
An extra or badly closed brace, parenthesis or bracket |
SyntaxError: Unexpected end of input |
A closing symbol is missing at the end of the file |
ReferenceError: catalog is not defined |
A misspelled name, or a variable used before it was declared |
TypeError: Cannot read properties of undefined (reading 'sessions') |
You accessed a property of something whose value is undefined |
Error: Cannot find module '/path/src/catalog.js' |
The wrong file name or path |
That last one is very typical at the beginning: Cannot find module almost always means you ran node catalog.js from the project root instead of node src/catalog.js.
An editor with ESLint would have flagged the error before you even saved. That is why the previous lesson insisted on setting it up.
- What This Program Does Not Do Yet
Knowing what you have built matters as much as knowing what you are still missing:
| Current limitation | Where it gets solved |
|---|---|
The data is written inside the .js; changing the catalog means touching code |
Module 3: we will read data/events.json with fs |
| It only shows up in the terminal; there is no way to query it from a browser | Module 4: we will serve the catalog over HTTP |
| All the code lives in a single file | Module 2: we will split it into modules with require/module.exports |
| There is no persistence for orders or users | Module 7: the escena_viva database |
| Argument parsing is hand-rolled | Module 5: specialized packages |
That is exactly the path this course takes: that very same src/catalog.js will grow and transform module by module until it becomes a real API.
Common Mistakes and Tips
Mistake 1: using window, document or alert.
They do not exist in Node. If a tutorial uses them, it is talking about the browser.
Mistake 2: believing that process.argv[0] is the user's first argument.
It is the path of the Node executable. The user's arguments start at index 2; always use process.argv.slice(2).
Mistake 3: sending errors through console.log.
It pollutes the data output. Errors and warnings go through console.error.
Mistake 4: calling process.exit() in the middle of an operation.
It kills the process without waiting for pending writes to finish. Prefer process.exitCode.
Mistake 5: running the script from the wrong directory.
Cannot find module usually means exactly that. Check process.cwd().
Mistake 6: looking for the syntax error precisely on the line Node reports. The parser points at where it failed, not at where the slip is. Look at the preceding lines.
Tip 1: use console.table to inspect data. It is far more readable than a console.log of an array of objects.
Tip 2: measure with console.time. Wrapping a block between console.time('load') and console.timeEnd('load') is the cheapest way to find out what is slow.
Tip 3: think of your scripts as commands. Clear arguments, data on stdout, errors on stderr and a correct exit code. That way you can chain them with other tools.
Exercises
Exercise 1: environment information
Create src/environment.js that prints a table (with console.table) containing these rows: Node version, platform, architecture (process.arch), working directory, number of arguments received, and heap memory used in MB. Run it with and without extra arguments and check that the count changes.
Exercise 2: maximum price filter
Extend src/catalog.js to accept a second filter: --max=2000 should show only the events that have at least one session whose priceCents is less than or equal to that value. Requirements:
- It must combine with the venue filter:
node src/catalog.js "Sala Boveda" --max=1600. - If the value of
--maxis not a valid number, write a message throughconsole.errorand finish with exit code2.
Exercise 3: occupancy report with an exit code
Create src/capacity-alert.js that walks the catalog and lists through console.log every session with fewer than 20% of its tickets sold (the ones that need promoting). Rules:
- Format of each line:
evt-002 | ses-002-3 | 17/10/2026 21:30 | 10% sold. - If no session is in that situation, write
No sessions at riskand finish with code0. - If there is at least one, finish with exit code
1, so that an alerting system can detect it.
Solutions
Solution 1
// src/environment.js
// Runtime environment diagnosis, presented as a table.
const memory = process.memoryUsage();
const args = process.argv.slice(2);
const data = [
{ Item: 'Node version', Value: process.version },
{ Item: 'Platform', Value: process.platform },
{ Item: 'Architecture', Value: process.arch },
{ Item: 'Directory', Value: process.cwd() },
{ Item: 'Arguments', Value: args.length },
{ Item: 'Heap used (MB)', Value: Math.round(memory.heapUsed / 1024 / 1024) }
];
console.table(data);Solution 2
// --- Maximum price filter ---
// We look for an argument shaped like --max=NNNN
const maxArg = args.find((arg) => arg.startsWith('--max='));
if (maxArg) {
// Everything after the "=" sign is the value.
const rawValue = maxArg.split('=')[1];
const maxPrice = Number(rawValue);
// Number('abc') returns NaN; Number('') returns 0, which is no good here either.
if (!Number.isInteger(maxPrice) || maxPrice <= 0) {
console.error(`Error: invalid value in --max ("${rawValue}").`);
console.error('Usage: node src/catalog.js [venue] [--max=CENTS] [--table]');
process.exit(2); // 2 = incorrect usage
}
displayedEvents = displayedEvents.filter((event) =>
// some() returns true if AT LEAST one session meets the condition.
event.sessions.some((session) => session.priceCents <= maxPrice)
);
}This block must be placed after the venue filter, so that the two combine: each filter narrows down the result of the previous one.
node src/catalog.js --max=2000 # Noche de Monologos (1800 and 1500)
node src/catalog.js "Sala Boveda" --max=1600 # Only because of the 1500 session
node src/catalog.js --max=abc # Error, exit code 2Solution 3
// src/capacity-alert.js
// Lists the sessions with low sales so promotional action can be taken.
const catalog = require('./catalog-data.js'); // (see the note at the end)
const PERCENT_THRESHOLD = 20;
const atRisk = [];
for (const event of catalog) {
for (const session of event.sessions) {
const percentage = Math.round((session.sold / session.capacity) * 100);
if (percentage < PERCENT_THRESHOLD) {
atRisk.push({ event, session, percentage });
}
}
}
if (atRisk.length === 0) {
console.log('No sessions at risk');
process.exitCode = 0;
} else {
for (const item of atRisk) {
console.log(
`${item.event.id} | ${item.session.id} | ` +
`${formatDate(item.session.dateTime)} | ${item.percentage}% sold`
);
}
// A non-zero code so that an alerting system picks it up.
process.exitCode = 1;
}Expected output with our data:
A note on the require in the first line: for this second script to use the same data, we would have to export it from a shared file. We have not seen how to do that yet — it is the subject of CommonJS Modules and require() — so for now copy the catalog array and the formatDate function into src/capacity-alert.js. The fact that this duplication feels uncomfortable is precisely why modules exist.
Conclusion
You have written and run your first real Node.js program. Along the way you have seen that JavaScript on the server has no window and no document, but it does have process, the object that connects you to the operating system: arguments, environment, working directory, memory and exit code.
You have built src/catalog.js with Escena Viva's three founding events — the Concierto de Otoño at the Teatro Almendra, the Noche de Monólogos at the Sala Bóveda and the Festival de Jazz de Primavera at the Auditorio Ribera — formatted it with template literals and console.table, filtered it with process.argv and learned to keep data (stdout) apart from diagnostics (stderr), closing with a coherent exit code. You also know how to read a SyntaxError without panicking: file, line, token, and then look upwards.
You have done all of this by editing a file, saving it and running it again. There is a far quicker way to try out isolated ideas — an expression, a transformation of the catalog, a doubt about how a method behaves — without that save-and-run cycle. In the next lesson, The Node.js REPL, you will learn to use the interactive interpreter to explore Escena Viva's data live and try transformations out before writing them into the script.
Node.js Course: From Beginner to Advanced
Module 1: Introduction to Node.js
- What Is Node.js?
- Installing and Setting Up the Environment
- Your First Node.js Program
- The Node.js REPL
- Modern JavaScript for Node.js
- The Course Project: the Escena Viva Platform
Module 2: Core Concepts
- Node.js Architecture
- The Event Loop
- Callbacks and Asynchronous Programming
- Promises and async/await
- Events and EventEmitter
- CommonJS Modules and require()
- ES Modules and Interoperability
Module 3: File System and I/O
- Reading and Writing Files
- The fs Module in Depth
- Cross-Platform Paths with the path Module
- Working with Streams
- Transform Streams and pipeline
- Buffers and Binary Data
Module 4: HTTP and Web Servers
- Creating a Simple HTTP Server
- Handling Requests and Responses
- Manual Routing
- Serving Static Files
- Receiving Data: Request Bodies and JSON
- Consuming External APIs from Node.js
Module 5: NPM and Package Management
- Introduction to NPM and package.json
- Installing and Using Packages
- Semantic Versioning and package-lock
- npm Scripts and Project Automation
- Creating and Publishing Packages
- Dependency Security and Maintenance
Module 6: The Express.js Framework
- Introduction to Express.js
- Setting Up an Express Application
- Routing in Express
- Middleware
- Essential Third-Party Middleware
- Input Data Validation
- Error Handling
Module 7: Databases and ORMs
- Introduction to Databases
- Using MongoDB with Mongoose
- CRUD Operations
- Relationships, Population and Advanced Queries
- Using SQL Databases with Sequelize
- Migrations, Transactions and Seed Data
Module 8: Authentication and Authorization
- Introduction to Authentication
- User Registration and Password Hashing
- Sessions and Cookies with Passport.js
- Authentication with JWT
- Role-Based Access Control
- API Security Best Practices
Module 9: Testing and Debugging
- Introduction to Testing
- Unit Testing with Mocha and Chai
- Test Doubles with Sinon
- Integration Testing
- Coverage and Test Automation
- Debugging Node.js Applications
Module 10: Advanced Topics
- The Cluster Module
- Worker Threads
- Caching and Job Queues with Redis
- Performance Optimization
- Building RESTful APIs
- GraphQL with Node.js
Module 11: Deployment and DevOps
- Configuration and Environment Variables
- Logging and Monitoring in Production
- Using PM2 for Process Management
- Packaging with Docker
- Deploying to Heroku and Other PaaS
- Continuous Integration and Deployment
