{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreid33gcn53soz5mw76iwbygnlq6zzinxalbzlpi7fkknslo7mfvomi",
"uri": "at://did:plc:vrrdgcidwpvn4omvn7uuufoo/app.bsky.feed.post/3ki4aujwm372u"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreic2epiakyz6c7cuitmxglfnmpjl6tjy4f3qwrroe2rbfhp75flspm"
},
"mimeType": "image/png",
"size": 48847
},
"description": "A one-dimensional spectrum can't sufficiently capture the tradeoffs involved in web development.",
"path": "/words/the-website-vs-web-app-dichotomy-doesnt-exist/",
"publishedAt": "2024-01-03T00:00:00Z",
"site": "at://did:plc:vrrdgcidwpvn4omvn7uuufoo/site.standard.publication/3mmyfl3pxzi2a",
"tags": [
"css",
"html",
"javascript",
"localfirst"
],
"textContent": "You don't need to wade far into web development discourse to hear about the website vs. web app dichotomy.\nIt posits that websites can be grouped into two categories: mostly static \"documents\" with little user interaction beyond following links, and \"applications\" that involve rich dynamic behavior.\nUsually, people invoke it to talk about the use, abuse or avoidance of JavaScript frameworks.\n\nA more nuanced view is that there's a spectrum between website and web app, and that where a project sits determines which technologies are appropriate to build it.\nThe implication is that at some point, it makes sense to use a JavaScript framework rather than progressively enhanced HTML.\nWeb developers tend to divide themselves into roughly two camps here — and depending on which camp you ask, the location of that inflection point varies widely.\n\nOne camp says that everything to the left of Google Docs is a website that should function without JavaScript if possible.\n\nThe other camp says that anything to the right of a WordPress blog is a web app that should be built with a JavaScript framework.\n\nSvelte creator Rich Harris speaks to this in his 2021 talk Have Single-Page Apps Ruined the Web?.\nHis position is that neither camp is fully correct; that most websites span regions of the spectrum rather than single points.\nHe proposes the term \"transitional apps\" to describe websites that are neither fully \"document\" nor \"application\".\n\nWhile I agree that most websites defy binary categorization, I don't buy the overall \"website vs. web app\" framing.\nThey're both nebulous terms that attempt to describe what a site is rather than what it does.\nMoreover, I don't think a one-dimensional spectrum can sufficiently capture the tradeoffs involved in web development.\n\nI like to think about websites along two axes:\n\nStatic vs. dynamic — how much of the page updates in response to user interaction?\n\nOnline vs. offline — how much functionality requires a persistent Internet connection?\n\nObviously, this is still a pretty crude survey, but I think it broadly captures the most important architectural constraints.\nLet's call the intersections informational, transactional, realtime and local.\nEveryone loves a good quadrant chart!\n\nInformational Websites\n\nWe'll start at the bottom left, at the intersection of static and offline: informational websites.\n\nI've called out WordPress, Medium and Wikipedia, but most of the web lives here: pages of unmoving text and images, connected by hyperlinks.\nOur measure of static vs. dynamic is how much of the page updates in response to user interaction, and websites in this category tend to just swap the whole thing out at once.\nBlogs, business sites, newspapers and online courses all fall under this umbrella.\nWordPress alone powers over 40% of all websites!\n\nThe key technologies in this quadrant are HTML and CSS.\nWhen JavaScript is used, it's usually for features like animations or interactive visuals that complement the textual content.\nAt that point, people often bring in a JavaScript framework — vastly overpowered for the majority of the website — to accommodate the most dynamic parts of the page.\nMore on this later.\n\nOne observation about this quadrant is that even though it doesn't require an Internet connection to be usable, precious little of it is actually available offline.\nWhen you're off the grid, each browser tab teeters precariously on the brink of annihilation.\nOne errant refresh and it's gone until you reconnect!\n\nTransactional Websites\n\nIf we move up to the intersection of static and online, we get transactional websites.\n\nThese are so named because interaction mostly takes the form of transactions with a web server: the user clicks a button or submits a form, an HTTP request triggers a state change on the server and the whole page updates to reflect the new state.\nFor websites in this quadrant, the server is a necessary component of all meaningful interaction.\n\nAny service that involves literal financial transactions — like Amazon, or your bank's website — probably lives here.\nSo do social networks and search engines.\nIn fact, when we exclude informational websites, most remaining websites are transactional.\n\nThis quadrant tends to be the most contentious.\nWhen the JavaScript community talks about web apps, they're often referring to transactional websites — even though many are every bit as static as this blog.\n\nMaybe that's why the JavaScript community has spent the past couple years pouring resources into improving the user experience in this quadrant.\nAt this point, every major frontend framework includes server-side rendering out of the box.\nNewer features like React Server Components and Qwik's resumability push even further, blending client-side and server-side code to more easily express behavior that spans network boundaries.\n\nAt the same time, a more traditional approach to building transactional websites is becoming en vogue again, treating HTML as a hypermedia that describes interactions rather than just as a rendering target for JavaScript.\nIn the essay When Should You Use Hypermedia?, htmx creator Carson Gross describes the ideal use case as \"text-and-image heavy, with coarse-grain [UI] updates\".\nThat certainly describes most transactional websites, where more immersive multimedia is rare and it's common to update large swaths of the page at once.\n\nRealtime Websites\n\nAt the intersection of dynamic and online, we have realtime websites.\n\nThese are websites that require faster and more fine-grained updates than HTTP requests to a web server can reasonably accommodate.\n\nIn 2024, the realtime website with which we're all most familiar is probably Zoom.\nAnother popular one is Discord.\nIn the extreme top right corner is RuneScape, a massively multiplayer online 3D video game playable in a browser.\n\nRealtime websites often use persistent bidirectional connections like websockets or WebRTC in addition to the request/response model.\nThe server's responsibility is mostly to transmit updates between clients and to ensure that its central database remains consistent.\n\nWhereas informational and transactional websites can get by without JavaScript if they really want to, realtime websites don't have that option: they are client-side apps by necessity, and JavaScript is the only game in town.\nThis is where frontend frameworks shine, and I think even their most hardened critics would acknowledge that it's a justified use case.\n\nLocal Websites\n\nThe final quadrant is at the intersection of dynamic and offline: local websites.\n\nBefore the Internet, these were just normal apps: programs where all computation happened on your computer, operating on data also stored on your computer.\nInfeasible before JavaScript became a powerful programming language, local websites are the newest quadrant.\nThese are the true single-page apps: everything happens on one page, because there's no web server at all.\n\nBelieve it or not, these website are everywhere. Every counter app and todo list made to demo a JavaScript framework is a local website.\nAlthough they're harder to monetize, they share the same advantages that informational apps enjoy: namely, that the lack of outside infrastructure makes them cheaper and easier to maintain.\n\nIn the age of software as a service, prominent local websites that aren't tech demos are harder to find.\nOne fun example is Wordle!\nEverything from the gameplay to the word list to the share functionality runs without a server.\nAnother is Photopea, a Photoshop-esque raster image editor that runs entirely in a web browser.\n\nLocal websites are closely related to progressive web apps — a loose term for websites that can be installed on a device, work offline and integrate more deeply with operating system features.\nThe promise was that these websites would combine the capabilities of native apps with the reach of web apps.\nIn practice, though, the buzz has far outstripped actual adoption, and local websites remain a marginal category compared to the other three.\n\nDeclarative Dynamism\n\nFrom a more traditional point of view, you'd reach for a JavaScript framework to build websites in this area of the chart:\n\nIf you consider yourself a JavaScript developer, the area for which you'd use a JavaScript framework might look more like this:\n\nEither way, it's clear that dynamism — real or perceived — is a driver of JavaScript framework adoption.\nIncreasingly, though, we're seeing people experiment with ways to express more dynamic interactions declaratively in HTML and CSS.\n\nThe foremost example here is probably htmx, which extends HTML with attributes for controlling network exchanges with a web server.\nBy making it easy to replace smaller regions of a page with new content, htmx allows developers to add more dynamic interactions to their websites without replacing the entire stack.\n\nThere's also precedent for how this hypermedia approach might extend to local interactions. One example is Lea Verou's Mavo, which lets developers use HTML attributes to create reactive single-page web apps. In a similar vein, the Invokers proposal — which has been experimentally implemented by all three major browsers — defines a declarative way to trigger events on HTML elements such as <dialog> and <audio>.\n\nMoving even further toward the dynamic side of the chart, an architecture called islands is picking up steam.\nCoined by Katie Sylor-Miller and popularized by the Astro web framework, islands are self-contained dynamic areas within a static HTML document.\n\nThe most commonly cited example of islands architecture is probably GitHub, which embeds dynamic widgets such as rich text areas in server-side rendered pages.\nBut the pattern shows up all over the web.\nThe Svelte framework was originally created for building interactive visualizations within New York Times articles.\nEven the interactive demos on this blog are examples of islands architecture!\n\nOne technology driving adoption of the islands architecture is web components, which let people create their own HTML elements.\nCustom behavior is implemented in JavaScript and controlled using attributes and browser events.\nThat mirrors how built-in HTML elements are implemented with native languages — after all, deep in the belly of the browser, it's all imperative code.\n\nWeb components significantly lower the bar to adding dynamism to HTML without imposing additional architectural constraints.\nAs I wrote in Web Components Eliminate JavaScript Framework Lock-in, they can act as a glue layer that allows framework code to be embedded without directly using the framework itself — in effect, turning them from competing technologies into complementary ones.\n\nIronically, one of the most compelling examples of declarative dynamism is a React library: React Three Fiber, which lets people create 3D scenes by using JSX to control the imperative Three.js library.\nIn spirit, React Three Fiber is an example of islands architecture — a <canvas> island rendering 3D visuals within a DOM-based React app.\nIndeed, we're starting to see similarly ambitious web components, such as Lea Rosema's <shader-art>.\n\nAsync; Await Optional\n\nOne common thread in the top right corner of the chart is the replication of existing desktop apps with added multiplayer capabilities.\n\nThe most prominent example here is Figma: a vector graphics editor with live collaboration.\nIn contrast to realtime websites, this collaboration is often asynchronous.\nIn fact, the editing itself can happen offline, with changes synced to the server when the user regains their Internet connection.\n\nSuch apps are often referred to as local-first software.\nCoined by Ink & Switch in a paper of the same name, local-first describes a set of principles embodying the idea that we — not our software — should own our work.\nComputation must take place on our own computers, with the network being relegated to an optional syncing service rather than a critical component of the system as a whole.\n\nThrough this lens, apps like Figma that depend on a network service for core functionality are not true local-first software.\nLet's call apps that follow local-first principles other than data ownership asynchronous — communicating with a server can be deferred, but it must happen at some point.\nWhether an app is local-first or asynchronous is usually a business decision rather than a technical constraint.\n\nIt's not just highly dynamic websites that can work this way.\nLinear is a transactional project management app known for its offline sync capabilities.\nThis introduces tension within the quadrant: transactional websites tend toward coarse-grained updates via network exchanges with a web server, which makes them a good fit for hypermedia rather than imperative implementation.\nBut right now, offline functionality is difficult to introduce even using a JavaScript framework — let alone declaratively in HTML!\n\nLocal-first websites are even less common.\nThey're the most difficult to build, since collaboration features require distributed clients to resolve conflicts with no central server enforcing data integrity.\nOften, they take the form of creative tools that operate on local files and monetize with subscriptions for multiplayer collaboration.\nTwo examples are Muse — created by the same Ink & Switch that coined the local-first moniker — and Excalidraw.\n\nPeople are starting to chip away at the problem space.\nOne particularly promising technology is the Conflict-free Replicated Data Type, or CRDT: a kind of data structure that can consistently sync edits made by multiple peers with no central server.\nMany technologies in this area are either based on or inspired by CRDTs, and there's a burgeoning community that has emerged to provide the building blocks for asynchronous and local-first functionality.\n\nThese are subcategories I would love to see flourish — especially local-first, which is a fundamentally more empowering paradigm (as opposed to asynchronous, which is merely more convenient).\nToday, building local-first means leaning heavily on JavaScript frameworks; looking further ahead, we again see hints of how such websites might be built declaratively in Mavo, which can store data locally or in cloud services.\n\nWhat Next?\n\nSome thoughts about the future:\n\nAs new W3C standards, web components and libraries like htmx make HTML more powerful, I hope to see more declarative ways to build dynamic interactions without the need to fully buy into a JavaScript framework.\n\nThe last point notwithstanding, I hope to see more JavaScript usage for functionality that is difficult or impossible to replicate without it, such as robust offline support.\n\nThere's no technical reason that most informational and local websites should require an Internet connection; I hope more websites use service workers and that browsers start prioritizing offline use.\n\nLocal-first software has the potential to give us real data ownership in the age of cloud computing, and I hope we see a lot more movement there.\n\nThe website vs. web app dichotomy doesn't exist.\nBut I don't think any one way of building websites is going to swallow all the rest.\nIf there's one takeaway from all this, it's that the web is a flexible medium where any number of technologies can be combined in all sorts of interesting ways.",
"title": "The Website vs. Web App Dichotomy Doesn't Exist"
}