Browsers, HTTP, and the Developer Workflow
Introduction
This is the first lesson of the course and it maps to course 1 of the Meta Front-End Developer pathway, Introduction to Front-End Development. Before you write a single line of React, you need a clear mental model of what happens between typing a web address and seeing a page, and you need a development environment that anyone on your team can reproduce. Most beginner bugs, "my CSS does not load", "the page is blank", "it works on my machine", are not React bugs at all. They are request, path, or tooling bugs.
Throughout the course we build one original project, Harbor Workshops: a responsive catalog and booking interface for community workshops such as pottery, bike repair, and bread baking. All briefs, code, and tests in this course are original OnLevelUp material. This lesson prepares the ground for that project.
By the end you will be able to describe the client/server model, read an HTTP exchange in the browser's developer tools, set up a reproducible Node-based project, and diagnose the most common "resource did not load" failure.
Learning objectives
After this lesson you can:
- Explain the responsibilities of front-end, back-end, and full-stack developers.
- Break a URL into its parts and describe what a browser does with it.
- Read an HTTP request and response, including method, status code, and headers.
- Use the Network, Console, and Elements panels of browser developer tools to find a problem.
- Install Node.js, create a project with
npm, and explain whatpackage.jsonandpackage-lock.jsondo. - Distinguish a build tool (Vite) from a UI library (React).
1. Who does what: front end, back end, full stack
A website is a conversation between two programs. The client is the browser running on the visitor's device. The server is a program on another machine that answers requests. The role you hold depends on which side of that conversation you build.
| Role | Works on | Typical technologies | Example task for Harbor Workshops |
|---|---|---|---|
| Front-end developer | What runs in the browser: structure, appearance, interaction | HTML, CSS, JavaScript, React | Build the workshop card grid and the booking form |
| Back-end developer | Servers, databases, business rules, security | Node.js, Python, SQL, REST APIs | Store bookings and refuse a booking when a workshop is full |
| Full-stack developer | Both sides | A mix of the above | Build the form and the endpoint that receives it |
A front-end developer does not only "make it pretty". Typical responsibilities include semantic structure, accessibility, responsive layout, state management, calling APIs, testing, and performance. Notice that the browser runs code that the user controls. Anything in front-end code is visible to the visitor, so a front-end developer never stores secrets such as API keys in it and never relies on front-end checks alone for security. Validation in the browser improves the experience, but the server must validate again.
Concrete example. A visitor clicks "Reserve" on a bread-baking class that has one seat left. The front end disables the button and shows "Reserving…". The back end checks seat availability inside a database transaction. If two people click at the same moment, only the back end can decide who gets the seat. The front end's job is to display the outcome honestly, either a confirmation or "Sorry, this class just filled up".
2. From URL to pixels
Anatomy of a URL
Consider this address:
https://harbor.example/workshops/pottery?level=beginner&sort=date#reviews
| Part | Value | Meaning |
|---|---|---|
| Scheme (protocol) | https |
How to talk to the server; HTTPS encrypts the traffic |
| Host | harbor.example |
Which server (found through DNS) |
| Port | not shown (443 for HTTPS, 80 for HTTP) | Which door on the server |
| Path | /workshops/pottery |
Which resource |
| Query string | ?level=beginner&sort=date |
Extra parameters, key=value pairs separated by & |
| Fragment | #reviews |
A position inside the page; never sent to the server |
The fragment detail matters. The browser removes #reviews before making the request and uses it afterwards to scroll to the element with id="reviews". This is why single-page applications can change the fragment without triggering a server request.
What the browser does
- Parse the URL and decide what to request.
- Resolve the host through DNS to an IP address.
- Open a connection (and for HTTPS, negotiate encryption).
- Send an HTTP request.
- Receive the response, normally an HTML document.
- Parse the HTML into the DOM (Document Object Model), a tree of objects representing the page.
- Discover more resources (stylesheets, scripts, images) and request each one.
- Apply CSS to compute styles, lay out the elements, and paint pixels.
- Run JavaScript, which may change the DOM and trigger layout and paint again.
The key insight: the first response is only the beginning. A page with one HTML file, one CSS file, one script, and six images triggers at least nine requests. If any one fails, the page may look broken even though the HTML arrived.
3. HTTP in practice
HTTP is a request/response protocol. The client sends a request; the server sends exactly one response.
A request
GET /workshops/pottery HTTP/1.1
Host: harbor.example
Accept: text/html
- The method says what to do.
GETretrieves,POSTcreates or submits,PUTorPATCHupdates,DELETEremoves. - The path names the resource.
- Headers carry metadata such as the host, accepted formats, and cookies.
- A request may have a body, for example JSON in a
POST.
A response
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=300
<!doctype html>
<html lang="en">...
The status code tells the client how things went. Learn the families:
| Range | Meaning | Common examples |
|---|---|---|
| 1xx | Informational | 101 Switching Protocols |
| 2xx | Success | 200 OK, 201 Created, 204 No Content |
| 3xx | Redirection | 301 Moved Permanently, 302 Found, 304 Not Modified |
| 4xx | Client error | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests |
| 5xx | Server error | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable |
The most useful single habit in front-end debugging is reading the status code first. A 404 means "the server does not know this path", usually a typo or a wrong relative path. A 403 means "I know it, but you may not have it". A 500 means the server crashed, and no amount of editing front-end code will fix it.
The Content-Type header tells the browser how to treat the body. A stylesheet served as text/html (for example, because the server returned an error page instead of the CSS file) will not be applied. Developer tools show this mismatch clearly.
Worked example 1: reading an exchange
Open the Harbor page, open the Network panel, and reload. You see these rows:
| Name | Status | Type | Size |
|---|---|---|---|
pottery |
200 | document | 4.1 kB |
styles.css |
404 | text/html | 0.3 kB |
app.js |
200 | script | 12 kB |
kiln.jpg |
200 | jpeg | 180 kB |
Reasoning, step by step.
- The document loaded (200), so the HTML is not the problem.
styles.cssreturned 404, and its type istext/html: the server answered with its "not found" page instead of CSS. That explains why the page appears unstyled.- The script and the image are fine, so the page works but looks plain.
- Click
styles.css, look at the Request URL:https://harbor.example/workshops/css/styles.css. The HTML says<link rel="stylesheet" href="css/styles.css">, a relative path resolved against/workshops/. - The file actually lives at
/css/styles.css. Fix: use a root-relative pathhref="/css/styles.css".
Why not the alternatives? Rewriting the CSS would change nothing, because the file never arrives. Clearing the cache would not help either: a 404 is not a stale-cache symptom. Reading the Network panel first saved the time.
4. Developer tools: your instruments
Every major browser ships with developer tools (open with F12 or Ctrl/Cmd + Shift + I). Learn four panels.
| Panel | Use it to | Typical question it answers |
|---|---|---|
| Elements | Inspect the live DOM and applied CSS rules | "Why is this button blue and not green?" |
| Console | See errors and warnings, run JavaScript | "What did the script complain about?" |
| Network | See every request, status, timing, headers | "Did the file load? How big was it?" |
| Application (or Storage) | Inspect cookies, local storage | "What did the app save?" |
Two details worth practicing. First, the Elements panel shows the DOM after JavaScript, which can differ from "view source". Second, a red entry in the Console includes a file and line number you can click.
console.log("booking count:", 3);
console.table([{ name: "Pottery", seats: 2 }, { name: "Bread", seats: 0 }]);
The first line prints booking count: 3. The second prints a readable table with the columns name and seats. console.table is a quick way to inspect arrays of objects.
Exam tip. When a question describes a symptom ("the page is unstyled", "the image is missing"), decide which panel gives the fastest evidence. Missing resources point to Network; script errors point to Console; wrong styles point to Elements.
5. The developer workflow: editor, terminal, Node, npm
The tools
- A code editor such as Visual Studio Code gives syntax highlighting, search, and extensions.
- A terminal lets you run commands. You will use it every day; lesson 3.1 covers it in depth.
- Node.js runs JavaScript outside the browser. We use it to run development servers, build tools, and tests. Always install a currently supported long-term-support (LTS) release, and check the Node.js website for which versions are supported when you read this.
- npm is Node's package manager. It downloads libraries (packages) and runs scripts.
Check your installation:
node --version
npm --version
Each prints a version number such as v22.x.x or 10.x.x. If the command is "not found", the installer did not add Node to your PATH; reopen the terminal or reinstall.
Creating a reproducible project
A reproducible project is one that a teammate can clone and run with the same result. Two files make this possible.
package.jsonlists the project name, scripts, and the packages it requires, using version ranges.package-lock.jsonrecords the exact versions that were installed. Commit it to Git.npm ciinstalls exactly what the lockfile says and is the right command in automated builds;npm installmay update the lockfile.
Create a minimal project:
mkdir harbor-workshops
cd harbor-workshops
npm init -y
npm init -y writes a package.json with default values. Edit it so it contains a script:
{
"name": "harbor-workshops",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"greet": "node greet.js"
}
}
Create greet.js:
const workshops = ["Pottery", "Bread baking", "Bike repair"];
console.log(`Harbor offers ${workshops.length} workshops: ${workshops.join(", ")}`);
Run npm run greet. Predicted output:
Harbor offers 3 workshops: Pottery, Bread baking, Bike repair
"private": true prevents accidental publication to the npm registry. "type": "module" makes .js files use modern import syntax, which we use heavily later.
Dependencies and devDependencies
npm install react react-dom
npm install --save-dev vite
Packages needed when the app runs go in dependencies. Tools needed only to build or test go in devDependencies. The node_modules folder holds the downloaded code; it can be huge and is regenerated from the lockfile, so you never commit it. A .gitignore file containing node_modules keeps it out of Git.
Semantic versioning
A version 1.4.2 is MAJOR.MINOR.PATCH. In a range, ^1.4.2 allows 1.x.y updates at or above 1.4.2, while ~1.4.2 allows only 1.4.x. Major versions can break your code, which is why you read release notes before upgrading across one.
6. Tooling is not React
Beginners often say "I installed React" when they mean "I created a project with a toolchain". Separate the two ideas.
| Concept | What it is | Example |
|---|---|---|
| UI library | Code your app imports to describe interfaces | React |
| Build tool / dev server | Compiles, bundles, and serves your code during development | Vite |
| Test runner | Runs your tests | Jest |
| Package manager | Installs and records dependencies | npm |
Why do we need a build tool? Browsers understand HTML, CSS, and JavaScript. React code uses JSX, a syntax extension that browsers cannot run directly. A build tool transforms JSX into plain JavaScript, bundles many files into a few, and provides a development server with fast reloading.
Today the maintainers of React recommend starting new projects with a framework or a modern build tool such as Vite; the older Create React App is deprecated and should not be your default for new projects. Always confirm current recommendations on the official React documentation at react.dev when you start a project, because tooling evolves faster than courses do.
A Vite project starts like this:
npm create vite@latest harbor-app -- --template react
cd harbor-app
npm install
npm run dev
Vite prints a local address such as http://localhost:5173/. Open it, edit a file, save, and the browser updates without a manual reload. The structure includes:
harbor-app/
index.html # the single HTML page
package.json
src/
main.jsx # entry point that mounts React
App.jsx # first component
public/ # files served as-is
Concrete example of why the distinction matters. A teammate's build fails with "Cannot find module 'vite'". That is a tooling problem: dependencies were not installed. Running npm ci fixes it. Rewriting React components would be wasted effort.
Environment variables: a warning
Front-end build tools can inject environment variables into the browser bundle. Anything injected becomes public. Never put a database password or a private API key in front-end code. Only values safe for anyone to read, such as a public API base URL, belong there.
7. Common pitfalls
- Opening the HTML file with a double-click (
file://URL). Some features, such as module scripts andfetch, behave differently or are blocked. Use a dev server. - Case sensitivity.
Styles.cssandstyles.cssare different files on most servers even if they match on your laptop. - Relative versus root-relative paths.
css/a.css,./css/a.css,../css/a.css, and/css/a.cssresolve differently. - Trusting the cache. If an edit has no effect, a hard reload or disabling cache in the Network panel rules out stale files.
- Committing
node_modulesor secrets. - Confusing a 404 from the API with a 404 for the page. Check the Request URL.
Exam tips
- Memorize the status code families and the five or six codes you meet daily.
- Know that the fragment is not sent to the server.
- "Which tool shows whether a stylesheet loaded?" is a Network question; "which shows the computed width?" is Elements.
- A library and a build tool are different things, and
npm cifollows the lockfile exactly.
Mini case study: the vanishing stylesheet
Situation. The Harbor team deploys the site to a staging server. The home page looks fine, but /workshops/pottery appears with plain black text on white. On the developer's laptop everything looks right. The page's <head> contains <link rel="stylesheet" href="styles/main.css">. The Network panel on staging shows styles/main.css with status 404 for the pottery page, while the home page loads styles/main.css with 200.
Questions.
- Why does the same
hrefsucceed on one page and fail on another? - What is the minimal fix?
- Which evidence would confirm the fix?
Solution.
- The path
styles/main.cssis relative to the current URL's directory. On/it resolves to/styles/main.css, which exists. On/workshops/potteryit resolves to/workshops/styles/main.css, which does not. The laptop worked because the developer opened a flat folder where every page sat next tostyles/. - Change the link to a root-relative path:
href="/styles/main.css", so it resolves identically on every page. (Setting a<base>element is possible but easy to misuse.) - Reload with the Network panel open: the row now shows
/styles/main.css, status 200, typetext/css, and the Elements panel shows rules applied to the body.
Why other fixes are worse: copying the CSS file into /workshops/styles/ duplicates files and breaks again for /workshops/pottery/photos; inlining all CSS in every page removes caching.
Key terms
- Client / server: the requesting program (browser) and the program answering.
- URL: address of a resource: scheme, host, port, path, query, fragment.
- HTTP: the request/response protocol of the web; HTTPS adds encryption.
- Status code: three-digit result of a request.
- DOM: tree of objects the browser builds from HTML.
- Developer tools: browser panels for inspecting and debugging.
- Node.js / npm: JavaScript runtime outside the browser / its package manager.
package.json/ lockfile: declared dependencies / exact installed versions.- Vite: a build tool and dev server. React: a UI library.
Summary checklist
- I can state what a front-end, back-end, and full-stack developer own.
- I can split a URL into scheme, host, path, query, and fragment.
- I can read a status code and name its family.
- I can use Network, Console, and Elements to locate a problem.
- I can run
node --version,npm init -y, andnpm run <script>. - I know why
package-lock.jsonis committed andnode_modulesis not. - I can explain why Vite and React are different tools.
Official sources
- Meta Front-End Developer Professional Certificate (opens in a new tab)
- Course 1: Introduction to Front-End Development (opens in a new tab)
- MDN: How the web works (opens in a new tab)
- MDN: HTTP response status codes (opens in a new tab)
- React: Start a new React project (opens in a new tab)
- Vite: Getting started (opens in a new tab)
