1 URL = 1 Resource
The three protocol pillars — HTTP, HTML, and URLs — aren't just separate technologies. Together they create a specific model: the web is a system of named, addressable, linked resources. Every URL identifies a resource. HTTP defines the operations you can perform on it. HTML (and other formats) are the representations delivered. Understanding this model is what separates "using the web" from "building for the web."
A resource is any concept worth naming: a document, an image, a user profile, a search result set, a product listing, an API endpoint. The URL is its stable, globally unique address.
This is the web's fundamental unit of organization. Unlike desktop applications (where internal states have no addresses), every meaningful thing on the web can have a URL.
The address is the identity. /products/42 and /products/43 are different resources. /search?q=javascript and /search?q=python are different resources (different result sets).
Addressability — The Web's Superpower
Anything with a URL can be:
- Linked to — another page can point to it
- Bookmarked — a user can save it for later
- Shared — paste the URL in an email, chat, or social media
- Cached — browsers and CDNs store it for faster retrieval
- Indexed — search engines can discover and rank it
| Addressable (has URL) | Non-Addressable (no URL) |
|---|---|
A search results page: /search?q=javascript&page=3 |
A modal dialog that appears on click |
A product detail page: /products/42 |
An in-app state with no URL change |
A filtered view: /catalog?color=red&size=L |
A client-only filter toggle |
When a SPA changes what the user sees without updating the URL, it breaks addressability. The user can't bookmark, share, or navigate back to that state. The History API (pushState, replaceState) exists precisely to fix this — it lets JavaScript update the URL without a page reload, preserving the resource model.
Resources vs Representations
A resource is the concept. A representation is the format delivered. The same resource can have multiple representations:
/users/42→ HTML (browser renders a profile page)/users/42→ JSON (API client gets structured data)/users/42→ PDF (print-friendly version)
The client signals which representation it prefers via the Accept header. The server responds with the appropriate format and declares it via Content-Type. This is content negotiation. This is not limited to encoding; it also applies to the language used, such as English, Spanish, or Chinese. This will be signaled by the Accept-Language header. Given that a single URL could have multiple representations, we may need to employ the HTTP Vary header to distinguish between different cached versions of a URL resource.
Resource: /products/42
│
├── Accept: text/html → <html>...product page...</html>
├── Accept: application/json → {"id": 42, "name": "Widget"}
├── Accept: application/pdf → [PDF binary]
│
└── HTTP methods operate on the resource:
GET = retrieve a representation
PUT = replace the resource
DELETE = remove the resource
POST = submit data to the resource
Hypermedia — Links as Navigation
The web isn't just resources — it's linked resources. HTML's <a href="..."> is the fundamental navigation mechanism. A page that links to other pages creates a traversable graph of information.
This is what "HyperText" means — text that links to other text. The web is a hypertext system at scale.
In APIs, the same concept is called HATEOAS (Hypermedia As The Engine Of Application State) — responses contain links to related resources, letting clients navigate the API without hardcoding URLs.
The link is arguably the web's most important invention. Without it, the web would be a collection of isolated documents. With it, the web is a connected graph of knowledge.