メインコンテンツへスキップ
Series · The web as a system capability

How a website became a system you have to operate

Robert
ARCArchitectureWebsite

Once a site has a lot of content, users and business state, a database tends to become the natural choice. Scattering articles, accounts, permissions and transactions across server directories does not produce anything you can really maintain. A content management system gave editing and publishing a common entrance. An application server gave rules and data access a clear place to run. A database made content queryable, sortable, updatable and access-controlled.

That architecture changed the web. A site was no longer about which file the server returns. It became: the web server hands the request to an application, the application fetches state from the data layer, and a suitable response is generated. Java Servlets, JSP and J2EE-style server applications made application servers, databases and transactional logic a major route. Rails and Django, arriving in 2004 and 2005, then folded routing, ORM, migrations, templates and scaffolding into a more opinionated experience. They did not invent MVC, databases or modern web practice, but they brought the model to far more teams. For products that have to be operated for years, this was an important maturation rather than technical bloat.

It changed how people actually used websites too. Take a typical content site of the 2000s. An editor no longer replaces an HTML file over FTP. They log into an admin area in the browser, fill in a title and body, and click publish. The article, its author and its category go into a database. When a reader opens that same article, the server fetches the record on request, drops it into a template, and sends the page back. The author sees a CMS, the reader sees a web page, and whoever runs the thing sees an application service plus a data system that has to be backed up, upgraded and monitored. If the application runtime breaks, the images may still be on disk and the article may still be impossible to regenerate. Those three people are no longer looking at the same folder.

It also changed the default cost of publishing. Updating a piece of content once meant replacing a file. Later it typically meant entering a CMS, connecting a database, running a build, deploying a service, maintaining permissions, handling backups and upgrades. Writing the content did not get harder. The system around it became infrastructure every publisher had to face.

The browser became a runtime, and complexity grew in both directions

As Ajax spread, the browser stopped repainting a whole page after every request. An application could hold state on the client, load data asynchronously and update part of the interface. Single-page applications moved much of routing and presentation into the browser. Component models like React let large frontends be organised better, and made a web page look more and more like an application running continuously in the browser.

Further along, a reader receives an application shell first, the browser downloads JavaScript, then requests data from an API and updates the page locally. Development work split accordingly into frontend builds, backend services, interface contracts, deployment environments and caching strategy. For online collaboration, a console or a complex form, this feels far more natural than full-page reloads. But an article that only wants to be read started being planned inside the same engineering method.

This solved real problems as well. A dashboard, a collaborative document or a complex form genuinely needs continuous interactive feedback. For content sites, though, new problems appeared. How does the initial page get read quickly? How do deep links work? What do search engines and social crawlers actually see? So server rendering, static generation and hybrid rendering became important choices again.

There is no single right direction here. Browser runtimes, server rendering and pre-generated pages are tools for different interaction and publishing needs. What is genuinely unnecessary is treating them as a full application architecture that every page must select and deploy from scratch.

Object storage and Git-driven static publishing eased this problem elegantly for a while. Amazon S3's static website feature and GitHub Pages each showed that a storage layer and version control could carry part of the public web's job directly, and Netlify productised Git builds and Deploy Previews in 2015 and 2016. ZEIT's now started from simplifying deployment, later became Vercel, and carried the Git to preview to shipping workflow forward while also handling the server rendering, function/API routes and edge runtime work that goes beyond static delivery. None of them was first, they are not the same implementation, and they do not solve every backend or full-stack need for a team. What they collectively demonstrated is that many sites really need a reliable publishing path rather than an application server that runs forever.

ArcBlock took a different route. What shipped in 2020 was ABT Node 1.0, renamed Blocklet Server in late 2021. It is a runtime you can deploy and manage yourself, used to install, compose, run and manage static or dynamic blocklets, bringing routing, DID/identity, authorization and lifecycle into one running environment. What it shares with Netlify or Vercel is reducing deployment and operational friction; they are not substitutes for each other. From 2023, v0 moved prompt-generated React/Tailwind/shadcn UI to the front of the process, and Lovable in 2024 and 2025 organised prompt-driven building, preview and explicit publishing together. Natural language made starting easier. Deployment, data, identity, permissions and runtime remained boundaries someone still has to own.

Separating publishing from running an application, again

ARC's Web Device takes a deliberately narrow position here. It does not try to decide whether all websites should use static generation, server rendering or a browser runtime, and it does not require dynamic data to disappear. It moves the work that publishing pages have in common into the system layer: discovering site declarations, pages and content resources, assembling HTML, previewing, checking links and basic SEO, and running the publish workflow.

Importantly, the system does not require those publishing facts to be copied into a separate CMS first and then extracted by another service. AFS can organise real data sources, content, configuration and callable capability inside one path model. The Web Device is only responsible for composing reader-facing document output from that. When data needs updating, an index needs rebuilding or special logic needs to run, the relevant provider carries its own responsibility, and the publishing layer does not have to pretend it owns the whole business.

This also gives "static" a more accurate meaning. For publishing pages, stable pre-generated output is an advantage: fast to load, indexable, easy to check and deploy. But as soon as a page depends on a continuing session, live collaboration or runtime state, it should not be dressed up as a static site. In those cases ARC hands the work to the UI Device or an appropriate runtime target instead of forcing every need into the Web Device.

The next part turns to a problem the application stack obscured. Even when a piece of content can be published beautifully, how does a reader respond to it, and how does the author handle that response without giving up their own space and data?

Further reading