Introduction to JavaScript & Development Environment Setup
What is JavaScript?
Where Does JS Live?
Your First JavaScript Code
Choosing a Code Editor
Browser Developer Tools
Your First Console Command
What is Node.js?
Installing Node.js
Running JS with Node.js
Integrated Terminal
Project Folders & Files
Comments: Your Code's Notes
Basic Debugging Tips
Code Readability Matters
Next Steps in JS
Variables, Data Types, and Type Coercion
What's a Variable?
Declaring with var
Declaring with let
Declaring with const
var, let, const: Differences
What are Data Types?
Strings: Text Data
Numbers: Numeric Data
Booleans: True or False
Null and Undefined
Symbols and BigInt
Checking Data Types
What is Type Coercion?
Coercion in Action
Explicit Coercion
Operators: Arithmetic, Assignment, Comparison, Logical
Basic Math with Numbers
The Remainder Operator
Increment & Decrement
Order of Operations
Simple Assignment
Compound Assignments
Equality: Loose vs. Strict
Inequality: Loose vs. Strict
Greater/Less Than
Logical AND (&&)
Logical OR (||)
Logical NOT (!)
Combining Logical Ops
The Nullish Coalescing Op
The Optional Chaining Op
Conditional Statements: If/Else, Switch
Why Conditions Matter
The 'If' Statement
Adding 'Else' to 'If'
Multiple Choices: 'Else If'
Nesting Conditions
Logical Operators in Ifs
Ternary Operator Basics
Ternary in Action
Introducing 'Switch'
Switch Cases and Break
Fall-Through in Switch
Comparing If vs. Switch
Conditional Best Practices
Debugging Conditions
Mini-Project: Decision Maker
Looping Constructs: For, While, Do-While
Why Loops?
Looping Basics
The 'for' Loop: Basics
Counting with 'for' Loops
Iterating Over Strings
Nested 'for' Loops
The 'while' Loop: Basics
Avoiding Infinite Loops
User Input with 'while'
The 'do-while' Loop
When to 'do-while'
Breaking Out of Loops
Skipping with 'continue'
Looping Best Practices
Loops: A Quick Review
Functions: Declaration, Expression, Arrow Functions
What's a Function?
Declaring Your First Function
Function Declaration Hoisting
Functions as Expressions
Expression Hoisting Behavior
Named Function Expressions
Meet the Arrow Function
Implicit Returns
Arrow Functions & 'this'
When to Use What?
Functions as Callbacks
Immediate Invocation
Functions in Practice
Debugging Functions
Best Practices for Functions
Function Parameters, Return Values, and Scope
What are Parameters?
Passing Arguments
Default Parameters
Why Return Values?
The 'return' Keyword
Returning Different Data Types
What is Scope?
Global Scope
Function Scope
Block Scope with let/const
Lexical Scope
Scope Chain Explained
Variable Shadowing
Best Practices for Scope
Arrays: Creation, Manipulation, Iteration
What's an Array?
Creating Your First Array
Accessing Array Elements
Modifying Array Elements
Adding Elements to Arrays
Removing Array Elements
Adding/Removing Anywhere
Copying & Slicing Arrays
Combining Arrays
Finding Elements in Arrays
Looping Through Arrays
Transforming Arrays with map()
Filtering Arrays with filter()
Reducing Arrays with reduce()
Sorting Arrays
Objects: Properties, Methods, JSON
What's an Object?
Creating Your First Object
Accessing Object Properties
Bracket Notation for Properties
Modifying Object Properties
Deleting Object Properties
What are Object Methods?
Defining Object Methods
The 'this' Keyword
Iterating Object Properties
JSON: What and Why?
JSON Syntax Rules
JSON to JavaScript Object
JavaScript Object to JSON
JSON in Real-World Apps
ES6+ Features: Destructuring, Spread/Rest, Template Literals
What is ES6+?
Template Literals Basics
Tagged Template Literals
Array Destructuring Intro
Array Destructuring Defaults
Object Destructuring Intro
Object Destructuring Defaults
Nested Destructuring
Spread for Arrays
Spread for Objects
Spread in Function Calls
Rest Parameters in Functions
Rest in Destructuring
ES6+ for Cleaner Code
Common Use Cases
Understanding Asynchronous JavaScript: Callbacks
Sync vs. Async
The Call Stack Explained
Event Loop & Task Queue
What are Callbacks?
Callbacks in Action
Error Handling with Callbacks
Simulating Async Operations
Loading Data with Callbacks
Multiple Async Callbacks
Nesting Callbacks
The Pyramid of Doom
Limitations of Callbacks
Refactoring Callbacks
The Need for Promises
Async Recap & Next Steps
Promises: Introduction and Chaining
Sync vs. Async Code
The Problem with Callbacks
Why Promises?
What is a Promise?
Creating Your First Promise
Simulating Async Tasks
Handling Success with .then()
Handling Errors with .catch()
Always with .finally()
Chaining Promises
Error Handling in Chains
Promise.all() for Parallel
Promise.race() for Speed
Promise.any() & .allSettled()
Async/Await: Simplifying Asynchronous Code
Why Async/Await?
Your First Async Function
Async Function Returns
Awaiting a Promise
Awaiting Non-Promises
Sequential Await
From Callbacks to Async/Await
From Promises to Async/Await
Parallel Await
Async IIFEs
Async Event Handlers
Async Loops
Error Handling with Try/Catch
When Not to Use Async/Await
Async/Await in Practice
Error Handling in Asynchronous Operations
What Can Go Wrong?
Catching Sync Errors
Promises and Rejections
Chaining .catch()
The .finally() Method
Error First Callbacks (Review)
Async/Await & Try/Catch
Catching Multiple Awaits
Error Propagation in Async
Error Objects & Info
Graceful Degradation
Centralized Error Handling
Logging Errors
User Feedback on Errors
Why Robust Error Handling?
Working with the Fetch API for HTTP Requests
What is HTTP?
Why Fetch API?
Your First Fetch Request
Checking Response Status
Parsing JSON Data
Handling Text and Other Data
Understanding Response Headers
Catching Fetch Errors
Error Handling Best Practices
Fetching Public Data
Displaying Fetched Data
Loading States & UI Feedback
Query Parameters in GET
Setting Request Headers
Fetch with Async/Await
Consuming RESTful APIs: Best Practices
What is REST?
Resources and URIs
HTTP Methods for REST
Statelessness in REST
API Response Formats
Fetching Data with GET
Sending Data with POST
Updating Data with PUT/PATCH
Deleting Data with DELETE
Query Parameters & Headers
HTTP Status Codes
Graceful Error Handling
Loading States & UX
API Response Best Practices
Refactoring API Calls
The Document Object Model (DOM) Introduction
What is the DOM?
DOM vs. HTML Source
The DOM as a Tree
Selecting and Traversing DOM Elements
What's an Element ID?
Get Element by ID
What's an Element Class?
Get Elements by Class Name
Get Elements by Tag Name
Query Selector: The First Match
Query Selector All: All Matches
CSS Selectors Refresher
Choosing the Right Selector
Meet the DOM Tree
Finding Your Parent
Finding Your Children
Finding Your Siblings
First & Last Child
Putting Traversal to Use
Modifying DOM Element Content and Attributes
What's in a Text?
textContent vs. innerText
Updating Text with textContent
Updating Text with innerText
Clearing Text Content
HTML Inside Elements
Changing HTML with innerHTML
Adding HTML with innerHTML
innerHTML: Security Concerns
What are Attributes?
Getting Attributes with getAttribute
Setting Attributes with setAttribute
Removing Attributes
Common Attribute Gotchas
Putting It All Together
Manipulating DOM Element Styles and Classes
Intro to Element Styling
Inline Styles with .style
Getting Current Inline Styles
Why Use CSS Classes?
Adding a Class
Removing a Class
Toggling a Class
Checking for a Class
Replacing a Class
Multiple Classes at Once
The className Property
Computed Styles vs. Inline
Styling Best Practices
Project: Dynamic Theme Switcher
Project: Accordion Menu
Project: Form Validation Feedback
Creating and Appending New DOM Elements
What is an Element?
Meet document.createElement()
Adding Text to New Elements
Setting Attributes on Elements
Styling New Elements
The appendChild() Method
Where Does It Go?
The insertBefore() Method
insertBefore() in Action
Putting It All Together
The removeChild() Method
Removing 'This' Element
Removing All Children
Dynamic Element Management
Best Practices for DOM Ops
Event Handling: Introduction to Event Listeners
What are Browser Events?
Common Event Types
The Event Flow
Meet addEventListener()
First Click Listener
Listening for Key Presses
Functions as Handlers
Anonymous Functions
The Event Object
Changing Content on Click
Toggling Element Visibility
Form Submission Events
Removing Event Listeners
Multiple Listeners
Event Handling Tips
Advanced Event Handling: Event Object, Delegation, Propagation
What's in an Event?
Targeting the Right Element
Stopping Default Actions
Keyboard Event Details
Mouse Event Details
The Event Journey
Bubbling Up the DOM
Capturing Down the DOM
Stopping the Flow
Immediate Stop
Events on Many Elements
Delegating Your Events
Implementing Delegation
Delegation for Dynamic Content
When Not to Delegate
Browser Storage: LocalStorage and SessionStorage
Why Store Data Locally?
Meet Web Storage API
LocalStorage Basics
Retrieving Data from Local
Removing Local Data
SessionStorage Basics
Retrieving Session Data
Removing Session Data
LocalStorage vs. SessionStorage
Storage Event Listener
Storing Complex Data
Handling Storage Limits
Security Considerations
Debugging Storage Issues
Web Storage in Action
Setting Up the Node.js Development Environment
What is Node.js?
Why Node.js for Full-Stack?
Your First Node.js App
Installing Node.js
Verify Your Installation
Node.js Interactive Shell
The Event Loop Explained
Modules in Node.js
Global Objects in Node.js
Running Scripts with Node
Command Line Arguments
Environment Variables
Basic Debugging in Node.js
Node.js Best Practices
Next Steps with Node.js
Node Package Manager (NPM) Essentials
What is NPM?
Your First NPM Project
Meet package.json
Installing Packages
Dependencies in package.json
The node_modules Folder
package-lock.json Explained
Updating & Uninstalling Packages
Running Scripts with NPM
Common NPM Commands
Semantic Versioning (SemVer)
NPM Best Practices
Troubleshooting NPM Issues
Node.js Core Modules: File System and Path
What are Core Modules?
Sync vs. Async Operations
Introducing the 'fs' Module
Reading Files: Async
Reading Files: Sync
Reading Files: Promises
Writing Files: Async
Appending to Files: Async
Writing Files: Promises
Checking File Existence
Introducing the 'path' Module
Joining Paths
Resolving Absolute Paths
Path Info & Extensions
Introduction to Express.js: Building a Basic Server
What is Express.js?
Setting Up Your Project
Your First Express Server
What's a Route?
Hello, Express!
Sending HTML Responses
What is JSON?
Sending JSON Responses
Handling Multiple Routes
Choosing a Port
Console Logging for Debugging
Handling 404 Not Found
Restarting Your Server
Basic Error Handling
What's Next?
Express.js Routing and Request Handling
What's a Route?
Your First Express Route
Handling Different Paths
HTTP Methods: The Verbs
Routing by HTTP Method
Dynamic Routes: Parameters
Multiple Route Parameters
Query Strings: Filters
Using Params and Queries
All Methods: `app.all()`
Route Handlers Array
Express.Router Basics
Modular Routes with Router
Route Chaining
Handling 404 Not Found
Handling HTTP Methods: GET and POST Requests
What are HTTP Methods?
GET: Retrieving Data
POST: Sending Data
Basic GET Route Setup
GET with Route Params
GET with Query Strings
Basic POST Route Setup
Accessing Request Body
JSON Body Parser Middleware
URL-Encoded Body Parser
Creating a Simple API
Handling Data in POST
Status Codes for GET/POST
Error Handling in GET/POST
Testing with Postman
Express.js Middleware: Concepts and Usage
What is Middleware?
The 'next' Function
Global Middleware
Custom Logger Middleware
Authentication Check
Error Handling Middleware
JSON Body Parser
URL-Encoded Body Parser
Serving Static Files
Route-Specific Middleware
Order Matters!
Middleware Chaining
Third-Party Middleware
Middleware Best Practices
Middleware in Action: Recap
Building RESTful API Endpoints: Data Retrieval (GET)
What is a RESTful API?
HTTP GET: The Basics
Resource Naming Conventions
Setting Up Your First GET
Mock Data for APIs
Structuring JSON Responses
GET by ID: Route Parameters
Handling Not Found (404)
Structuring Single Responses
Query Parameters for Filtering
Query Parameters for Sorting
Query Parameters for Pagination
Building a Product API
API Response Best Practices
Testing Your GET Endpoints
Building RESTful API Endpoints: Data Manipulation (POST, PUT, DELETE)
POST: The Creation Story
Setting Up a POST Endpoint
Accessing Request Body Data
Implementing Resource Creation
POST Response & Status Codes
PUT vs. PATCH: The Update Duo
Setting Up PUT Endpoints
Implementing Full Resource Update
Setting Up PATCH Endpoints
Implementing Partial Resource Update
DELETE: The Eraser
Setting Up a DELETE Endpoint
Implementing Resource Deletion
DELETE Response & Status Codes
Error Handling for Data Ops
Introduction to Database Integration (Conceptual Overview)
What's a Database?
Databases in Full-Stack
Data Storage Challenges
SQL: Structured Data
NoSQL: Flexible Data
Choosing Your Database
Database Drivers & ORMs
Connection Strings & Config
The Connection Process
Basic Data Operations
Async Database Calls
API to DB Flow
Error Handling in DB Ops
Scaling & Performance (Intro)
Introduction to Progressive Web Apps (PWAs)
What's a PWA?
Why PWAs Matter
PWA Building Blocks
Reliable: Offline Access
Fast: Performance Matters
Engaging: App-like Experience
The Web App Manifest
Service Workers: The Basics
HTTPS: The Security Layer
Installability & Discovery
Push Notifications (PWA)
Background Sync (PWA)
PWA vs. Native Apps
PWA vs. Responsive Websites
PWA: A Hybrid Approach
The Web App Manifest: Configuration and Installation
What's a Web App Manifest?
Linking Your Manifest
Manifest Structure Basics
Name & Short Name
Start URL & Display Mode
Icons: The Face of Your PWA
Theme & Background Color
Orientation & Scope
Categories & Screenshots
Related Applications
Add to Home Screen Magic
Testing Your Manifest
Manifest Best Practices
Manifest for E-commerce
Manifest & SEO
Service Workers: Registration and Lifecycle
What's a Service Worker?
Service Worker vs. Main Thread
Service Worker Scope
Is Your Browser Ready?
Registering the Worker
Registration Success & Failure
The Install Event
The Activate Event
The Fetch Event
Updating Your Service Worker
Skipping the Waiting Phase
Controlling Clients
Debugging Service Workers
Service Worker Best Practices
When Not to Use SWs
Caching Strategies with Service Workers: Cache-First
Why Cache?
Service Worker's Cache Role
Meet the Cache API
What is Pre-caching?
Pre-caching in Action
Updating Pre-cached Assets
Cache-First Explained
Implementing Cache-First
Adding to Cache on Fetch
Handling Cache Misses
Cache-First for Dynamic Assets
Cache Management & Cleanup
Offline Page Fallback
Debugging Cache Issues
Cache-First Best Practices
Caching Strategies with Service Workers: Network-First & Stale-While-Revalidate
Why New Strategies?
Network-First: The Concept
Coding Network-First
Network-First in Action
When to Use Network-First
SWR: The Best of Both?
Coding SWR: Part 1
Coding SWR: Part 2
SWR in Action
When to Use SWR
Strategy Selection Factors
Static vs. Dynamic Content
Handling Different Routes
Putting It All Together
Caching Best Practices
Implementing Offline Capabilities with Service Workers
Why Offline Matters
The Offline Challenge
Offline Page Strategy
Pre-caching the Offline Page
Serving the Offline Page
Fallback for Other Assets
Detecting Online/Offline State
Handling Form Submissions Offline
User Feedback for Offline
Dynamic Content Offline
Error Handling Offline
Syncing Offline Data
Testing Offline Behavior
Offline UX Best Practices
Recap: Offline PWA
Background Sync and Push Notifications (Conceptual)
What is Background Sync?
Why Sync Matters Offline
How Background Sync Works
Use Cases for Background Sync
Sync vs. Fetch: Key Differences
What are Push Notifications?
Why Push Notifications?
Push Notification Components
Push Notification Flow
User Consent for Push
Subscribing to Push
Server-Side Push Logic
Service Worker Push Event
Displaying Notifications
Notification Click Handling
PWA Deployment and Best Practices
What Makes a PWA Installable?
The Web App Manifest Check
Service Worker & HTTPS
Responsive Design for PWAs
User Engagement Signals
Hosting Your PWA
Using Static Site Hosts
Cloud Platforms for PWAs
Domain & DNS Setup
HTTPS Certificates
Performance Auditing Tools
Optimizing Load Times
User Experience (UX) Tips
Accessibility in PWAs
Monitoring & Maintenance
E-commerce Data Models: Products, Users, Orders
What's a Data Model?
Entities: The Building Blocks
Attributes: Entity Details
Modeling the Product Entity
Modeling the User Entity
Modeling the Order Entity
Relationships: Connecting Data
Modeling Order Items
Modeling Categories & Reviews
Data Models & APIs
API for Products
API for Users & Orders
API for Shopping Cart
API for Reviews
API Versioning & Docs
Client-Side Product Listing Display and Filtering
Where do products live?
Getting Products with Fetch
Displaying Products: The Plan
Building Product Cards
Listing All Products
Filtering: The Concept
Adding Filter Controls
Applying Filters to Data
Updating the Display
Sorting: Order Up!
Adding Sort Controls
Applying Sort to Data
Combining Filters & Sorts
Product Image Handling
User Experience Polish
Implementing a Dynamic Shopping Cart (Add, Remove, Update)
What's a Shopping Cart?
Cart Data Structure
Displaying the Cart UI
Add to Cart Button
Adding Logic: First Item
Adding Logic: Existing Item
Updating Cart Total
Remove Item Button
Removing Logic
Quantity Input Fields
Updating Quantity Logic
Clear Cart Functionality
Cart Item Validation
User Feedback & UX
Refactoring Cart Code
Persisting Shopping Cart Data (Client-Side)
Why Persist Cart Data?
Meet Browser Storage
LocalStorage Basics
Retrieving from LocalStorage
Removing from LocalStorage
JSON for Complex Data
JSON to JavaScript
Storing Your Cart
Loading Your Cart
Updating the Stored Cart
Cart on Page Load
Handling Empty Cart
Ensuring Cart Survival
When to Clear the Cart
Best Practices for Cart
Building Product Detail Pages and User Reviews
What's a Product Page?
HTML Structure for PDP
Fetching One Product
Displaying Product Data
Handling Missing Products
Reviews: Why They Matter
Review Data Structure
Displaying Reviews UI
Fetching Product Reviews
Rendering Reviews Dynamically
Review Form HTML
Handling Form Submission
Sending Review to API
Updating UI After Review
Review Submission Flow
Conceptualizing the Checkout Process and Order Placement
What's a Checkout?
Key Checkout Steps
User Experience in Checkout
Collecting Shipping Info
Shipping Options & Costs
Collecting Payment Info
Payment Gateways Intro
Order Data Structure
Placing the Order API Call
Backend Order Processing
Handling Order Responses
Order Confirmation Page
Error Handling in Checkout
Security in Checkout
Guest vs. User Checkout
Introduction to Web Security and Common Vulnerabilities
Why Web Security Matters
Who's Attacking Your App?
What's a Vulnerability?
The Impact of Breaches
XSS: Malicious Scripts
SQL Injection: Database Hijack
CSRF: Forging Requests
Broken Authentication
Insecure Design
Security Misconfiguration
Injection Beyond SQL
Sensitive Data Exposure
Server-Side Request Forgery
Unsafe Deserialization
Insufficient Logging & Monitoring
Input Validation and Sanitization Techniques
Why Validate Inputs?
Validation vs. Sanitization
Client-Side Validation Basics
HTML5 Validation Attributes
JavaScript for Custom Validation
Real-time Validation Feedback
Why Server-Side Validation?
Basic Server-Side Validation
Validation for Data Integrity
When to Sanitize Inputs
Basic Sanitization Techniques
Sanitization Libraries (Conceptual)
Validation & Sanitization Flow
Error Handling for Inputs
Review & Best Practices
Preventing Cross-Site Scripting (XSS) Attacks
What is XSS?
Why XSS is Dangerous
Reflected XSS Explained
Stored XSS Explained
DOM-based XSS Explained
The Golden Rule: Output Encode
HTML Encoding for Text
Attribute Encoding for HTML
JavaScript Encoding
URL Encoding
What is CSP?
CSP Directives Explained
Implementing CSP
CSP and Inline Scripts
CSP Best Practices
Understanding and Mitigating Cross-Site Request Forgery (CSRF)
What is CSRF?
How CSRF Attacks Work
CSRF Attack Examples
Introducing CSRF Tokens
Generating CSRF Tokens
Implementing CSRF Tokens
Token Validation & Errors
SameSite Cookies Explained
Implementing SameSite Cookies
Double Submit Cookie Pattern
Origin Header Validation
User Interaction & CAPTCHA
Defense in Depth
CSRF Best Practices
Secure Authentication Principles: Password Hashing and Salting
Why Passwords Matter
The Plain-Text Problem
Real-World Breaches
What is Hashing?
Hashing Passwords: The Basics
Common Hashing Algorithms
Rainbow Table Attacks
Introducing Salt
How Salting Works
Beyond Simple Hashing
Key Derivation Functions
Bcrypt in Action
Choosing the Right KDF
Password Security Summary
Basic Session Management and Cookie Security
Why Sessions Matter
What is a Session?
Session IDs: The Key
Cookies: What Are They?
How Cookies Carry Session IDs
Setting Cookies in Express.js
Reading Cookies in Express.js
Express Sessions: Setup
Using Session Data
Session Lifecycle & Destruction
HttpOnly Flag: The Shield
Secure Flag: HTTPS Only
SameSite Flag: CSRF Defense
Cookie Path and Domain
Session Security Checklist