Skip to content

Web Foundations: HTTP, Semantic HTML, and Responsive CSS

Step 1 of 45

Browser HTTP Requests and the Front-End Developer Workflow

Introduction

Browser HTTP requests and a reliable developer workflow are the foundation of front-end development. This first lesson 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. Meta's Professional Certificate is a nine-course learning pathway with assessments and projects; the study tips here do not imply a separate proctored certification exam.

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:

  1. Explain the responsibilities of front-end, back-end, and full-stack developers.
  2. Break a URL into its parts and describe what a browser does with it.
  3. Read an HTTP request and response, including method, status code, and headers.
  4. Use the Network, Console, and Elements panels of browser developer tools to find a problem.
  5. Install Node.js, create a project with npm, and explain what package.json and package-lock.json do.
  6. 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:

Text
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; omitted from the HTTP request target

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 navigation request. JavaScript can read the fragment and explicitly send its value elsewhere, so it is not a place to hide secrets.

What the browser does

  1. Parse the URL and decide what to request.
  2. Resolve the host through DNS to an IP address.
  3. Open a connection (and for HTTPS, negotiate encryption).
  4. Send an HTTP request.
  5. Receive the response, normally an HTML document.
  6. Parse the HTML into the DOM (Document Object Model), a tree of objects representing the page.
  7. Discover more resources (stylesheets, scripts, images) and request each one.
  8. Apply CSS to compute styles, lay out the elements, and paint pixels.
  9. Run JavaScript as its loading and execution rules permit; it can run during HTML parsing, before first paint, or later, and can trigger new layout and paint.

These steps overlap. Cached DNS and connections can avoid setup work, while caches or service workers can satisfy resources without a fresh network exchange.

The key insight: the first response is only the beginning. One HTML document, one external stylesheet, one external script, and six images can require nine resource fetches if all are loaded. Caching, inline resources, and lazy loading change the number and timing of actual network 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. A request normally receives one final response, possibly preceded by one or more informational 1xx responses.

A request

Text
GET /workshops/pottery HTTP/1.1
Host: harbor.example
Accept: text/html
  • The method says what to do. GET retrieves, POST creates or submits, PUT or PATCH updates, DELETE removes.
  • 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

Text
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 did not find a current representation, or is unwilling to disclose that one exists. For a missing stylesheet, inspect the path first. A 403 means the server refuses the request, without proving whether the resource exists. A 500 reports an unexpected server condition, not necessarily a crashed process. Inspect the failing request and server evidence; a CSS styling edit does not repair server-side logic.

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 Response Content-Type Size
pottery 200 text/html 4.1 kB
styles.css 404 text/html 0.3 kB
app.js 200 text/javascript 12 kB
kiln.jpg 200 image/jpeg 180 kB

Reasoning, step by step.

  1. The document loaded (200), so fetching the document succeeded; its resource references can still be wrong.
  2. styles.css returned 404, and its type is text/html: the server answered with its "not found" page instead of CSS. That explains why the page appears unstyled.
  3. The script and image fetched successfully. That alone does not prove every interaction works, but the missing stylesheet explains the plain appearance.
  4. 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/.
  5. The file actually lives at /css/styles.css. With this site deployed at the origin root, use href="/css/styles.css". A site deployed under a subpath needs its configured base path instead. This reasoning assumes no <base> element changes URL resolution.

Why not the alternatives? Rewriting the CSS would change nothing, because the file never arrives. A 404 response can be cached. Check whether the row came from a cache, then confirm the response with cache disabled before changing paths. Clearing unrelated cookies does not establish where the file lives. Reading the Network panel first saved the time.

Build on this with semantic HTML and accessible page structure.

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.

JavaScript
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.

Study 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:

Bash
node --version
npm --version

Each prints its installed version. Match the project's supported Node/npm versions and the build tool's current requirements; the version printed alone does not prove compatibility. If the command is "not found", the installer did not add Node to your PATH; reopen the terminal or reinstall.

Build on this with shell navigation and project commands.

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.json lists the project name, scripts, and the packages it requires, using version ranges.
  • package-lock.json records the exact versions that were installed. Commit it to Git. npm ci requires a matching lockfile and manifest and refuses to update them; it is suited to automated builds. Use compatible Node/npm versions and the same dependency-related configuration. Platform-specific or optional packages and omitted development dependencies can still differ. npm install may update the lockfile.

Create a minimal project:

Bash
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:

JSON
{
  "name": "harbor-workshops",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "greet": "node greet.js"
  }
}

Create greet.js:

JavaScript
const workshops = ["Pottery", "Bread baking", "Bike repair"];
console.log(`Harbor offers ${workshops.length} workshops: ${workshops.join(", ")}`);

Run npm run greet. Predicted output:

Text
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

Bash
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 projects often use JSX, a syntax extension that browsers cannot run directly. JSX is optional in React. A build tool transforms JSX into plain JavaScript, bundles many files into a few, and provides a development server with fast reloading.

React's documentation recommends a framework for new apps. Starting from scratch with a build tool such as Vite is also appropriate for learning fundamentals or specific project constraints. The older Create React App is deprecated. 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:

Bash
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:

Text
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 to investigate: check whether Vite is declared, whether Node is compatible, and whether development dependencies were omitted. With a matching committed lockfile, npm ci --include=dev can restore declared build tools; it cannot fix an undeclared dependency or an incompatible runtime. 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 and fetch, behave differently or are blocked. Use a dev server.
  • Case sensitivity. Styles.css and styles.css are different files on most servers even if they match on your laptop.
  • Relative versus root-relative paths. css/a.css and ./css/a.css are equivalent. ../css/a.css goes up a directory; /css/a.css starts at the origin root.
  • 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_modules or secrets.
  • Confusing a 404 from the API with a 404 for the page. Check the Request URL.

Study 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 ci follows 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.

  1. Why does the same href succeed on one page and fail on another?
  2. What is the minimal fix?
  3. Which evidence would confirm the fix?

Solution.

  1. The path styles/main.css is relative to the current URL's directory. On / it resolves to /styles/main.css, which exists. On /workshops/pottery it resolves to /workshops/styles/main.css, which does not. The laptop worked because the developer opened a flat folder where every page sat next to styles/.
  2. For this deployment at the origin root, change the link to a root-relative path: href="/styles/main.css", so it resolves identically on every page. For a subpath deployment, use the configured application base. A <base> element also affects relative URL resolution and must be considered explicitly.
  3. Reload with the Network panel open: the row now shows /styles/main.css, status 200, type text/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, and npm run <script>.
  • I know why package-lock.json is committed and node_modules is not.
  • I can explain why Vite and React are different tools.

Official sources