From documents to applications

Published:

Open an early web page and a modern web application in two browser tabs. At first they seem to belong to different media.

The first is a document. It has a title, some text, perhaps an image, and links to other documents. The second may contain a live map, a collaborative editor, an infinite stream of messages, or a complete video-production suite. It responds to keystrokes, remembers unfinished work, synchronizes with other users, and updates while the current page remains visible.

Both arrive through a URL and eventually become elements in a browser. Their defining difference lies in what the browser is being asked to do—and what the user is being asked to manipulate.

The history of the web interface can be read as a sequence of changing units of interaction:

document → page transition → page fragment → application state

At every step, more of the interaction moved from the server into the browser. Product teams continued to decide the shape of that interaction. The page, the form, and later the component tree were designed before a particular user arrived.

The document as the interface #

The early web inherited its basic model from publishing. A browser requested a resource identified by a URL, and a server returned a document, usually written in HTML. The browser interpreted that document and displayed it.

The server could produce the HTML from a file or generate it from a program. That distinction mattered to developers while leaving the interaction model largely unchanged. From the browser's point of view, the result was still a document. From the user's point of view, the primary actions were still reading and following links.

The term static applies most accurately to the interaction model of the early web. A server could generate a different document for every request, while the relationship between the user and the page remained comparatively fixed. The browser displayed a completed representation, and the user consumed it.

A link was the essential interactive control. Its primary action was to select another document.

URL
 ↓
request
 ↓
HTML document
 ↓
read or follow another URL

The interface was therefore inseparable from navigation. To do something new was, in most cases, to go somewhere new.

Beyond reading #

Forms expanded the web beyond reading. A user could enter a search query, sign in, submit an order, or send a message. The page grew from a publication into a way to collect an instruction.

The document model continued to govern the exchange. A form submission sent a new request to the server, and the response replaced the current page with another document. Even when the user thought, "Add this item to my basket," the browser performed something closer to:

collect fields
    ↓
send request
    ↓
receive another HTML document
    ↓
replace the page

Applications built this way could be sophisticated. They maintained sessions, looked up records, applied business rules, and produced pages personalized to the signed-in user. Online shops, forums, email clients, and banking services all existed within this model.

Their interfaces were organized as graphs of pages. The server decided which page followed an action and rendered the whole representation again. The browser served as a capable document viewer and a thin application runtime.

This arrangement also shaped design. A product was described as a collection of screens and transitions: search results lead to product details; product details lead to the basket; the basket leads to checkout. To understand the application was to understand its map of pages.

Selective updates #

The next important change introduced selective page updates while preserving the surrounding view.

JavaScript could make a request in the background, receive a smaller response, and update part of the document already on screen. Search suggestions could appear while a user typed. A message could be posted while the surrounding conversation remained visible. A new row could be added while the rest of the table remained intact.

The unit of interaction became smaller:

whole document → fragment of a document

Responsibility moved beneath the familiar surface of a web page. The server remained the authority over data and business rules, while the client began to own immediate feedback and local presentation. The network exchange changed with it. The server could return a complete HTML document, a fragment of markup, or a structured piece of data. The browser would decide where that result belonged in the existing page.

Interaction became possible within the current view. A user could act while remaining in place.

SPA #

Single-page applications carried that shift further. The browser would load an application shell and enough JavaScript to manage substantial parts of the experience itself. The client kept track of interface state, requested data through APIs, handled navigation internally, and rendered new component trees as the state changed.

In the server-rendered model, the server commonly answered:

Here is the next page.

In the client-rendered model, it increasingly answered:

Here is the data you requested.

The client then decided how that data affected the visible interface.

user action
    ↓
client-side state transition
    ↓
optional data request
    ↓
component update
    ↓
DOM update

This made the web capable of interactions that once belonged mainly to desktop software. A route could identify a state inside a running application as well as a document stored or assembled on a server. The back button, address bar, and history still mattered, and they now sat on top of an interaction model that extended far beyond the browser's original document model.

The terminology reflected the change. The vocabulary shifted from pages, fragments, documents, and page responses toward frontends, components, state, and APIs. The web had become a software-distribution platform whose most visible artifact happened to be rendered through browser technologies.

Moving boundaries #

The movement between server and client followed a complex path. Large client applications introduced their own costs: slow initial loads, duplicated logic, inaccessible intermediate states, poor behavior on weak devices, and complicated synchronization between server and browser.

Modern systems consequently mix the earlier models. A server may render the first view, the browser may hydrate it into an interactive application, and subsequent updates may arrive as data, HTML fragments, streams, or descriptions of component state. Some interactions happen entirely in the browser; others cross the network and return incrementally.

This history reveals an ongoing renegotiation of responsibility between server and client:

Question Document web Application web
What does the server return? Primarily a document Data, documents, fragments, or streamed state
What does the browser manage? Presentation and navigation Presentation, interaction, and application state
What does the user manipulate? Documents and links Objects, controls, and live models
What is the usual update unit? The whole page Any part of the visible application

Contemporary web architecture can place each responsibility on either side of the network. The browser now maintains a continuous interactive world that extends beyond a succession of documents.

Predefined interface #

This transformation made interfaces far more responsive and expressive. It changed where rendering happened, how much state the browser held, and how small an update could be. It did not usually change when the conceptual structure of the interface was decided.

A server-rendered application and a single-page application may implement an accounts screen in very different ways. To the user, both can still present the same authored table, navigation, and actions. The values change at runtime; the categories through which the user understands them were chosen earlier.

The web evolved from documents into applications by moving responsibility across the network. Its next change may concern a different boundary: when and for whom its structure is decided.

To see that boundary clearly, we first need to separate dynamic data from a dynamic interface.