December 2016

Many inventions are accidents that get repurposed. Glue designed to build airplanes came out weak but gave birth to Post-it notes. The first potato chips were meant as an insult by an angry chef (nearly burned, heaps of salt, thinly sliced) but the customer loved the taste.

So an invention's most important use can be as far as the opposite of its initial goal.

Same with the web. The web started as a publishing medium, to link text and pictures together and passively read them like a newspaper. By now the web is anything but passive, like a genie in the lamp where your wish is its command. The web got repurposed. The web is no longer a publishing medium but one, big distributed computer program.

Here's the problem: the web is a horrifically badly designed program.

It's still hard to program for the web. What kept programming easy was ignored when we transitioned from the desktop to the network. [1] A lot was added that was missing, but to make something better isn't only to add to it. It's also to remove from it. What was added to the web was far from elegant and it never got fixed.

I thought I'd write down what I noticed that never got fixed. If the signs point we're at the end of an architectural era for the web, as they did for databases ten years ago, the verdict is also the same: it's time for a complete rewrite.

1. HTML isn't short

It's impossible to write user interfaces in HTML in the shortest amount of code. The glaring problem is you need to write the ending tag. It's only a few more characters per tag, but writing it manually adds up, and forgetting to add it in the right place can break everything.

2. HTML must be autogenerated to be short

Because HTML isn't short, one needs a separate programming language or tool to generate HTML that is as short as possible.

Now there are two things you need to know. HTML, and how to use the tool that generates the HTML. This gets complicated further when HTML and the tool that generates it are both used at the same time.

3. HTML is wasteful

Having to type the opening and ending tag is one of the smaller problems with HTML. The bigger problem is HTML has more elements and properties than the minimum one needs to write user interfaces.

Why have a button element if you can get the same result with links and styling? Why have both a readonly and a disabled property with the distinction that disabled doesn't send form data back? How did the input tag become this inconsistent? A UI language like HTML can have fewer elements.

4. CSS is inconsistent

Inconsistency is a common theme throughout the web stack. Just as there is inconsistency in HTML, there is inconsistency in CSS. Not all HTML elements can be styled with CSS with a style tag. [2]

Some elements can't be styled at all without browser-specific tweaks, like the placeholder in a textbox. Other elements can be styled only in a global .css file, not per element.

Here's an example. If you're trying to style a checkbox, you can do it only by defining some attributes in a global .css file:

input[type="checkbox"]:checked { ... }

You can't write something like the following, because CSS doesn't recognize the :checked selector when used directly in an element:

<input type="checkbox" style=":checked{ ... }"></input>

Here's a second example with a CSS event. If on hover you want to make a different div visible, you have to add multiple divs and write multiple CSS sections like:

<div class="showparent">
  <div class="showchild">show on hover</div>

.showchild{ display: none; }
.showparent:hover .showchild{ display: block; }

A third example; supposedly a div can be centered vertically with CSS alone, but I've never seen anyone get it to work.

It might be easier to understand what's going on if properties are changed with commands, not declarations, and it would probably take fewer lines of code.

5. Writing CSS needs multiple passes

Because CSS is inconsistent, one needs to make multiple passes to figure out what CSS to generate when. One pass to figure out what UI elements should be styled, and another pass to generate global CSS only for these elements. Without multiple passes one generates more CSS than necessary, like CSS for elements that aren't used in the web page that's displayed.

For example, it'd be easier to write a single function that generates a checkbox, but with CSS it's impossible to just call checkbox(params) and be done with it.

6. Dynamic code needs Javascript

Writing good apps often means writing Javascript that figures out dynamically what to display when. For onClick and onKeypress events, for animations, timers, etc.

This means the web now needs three separate languages to write apps. Two for showing stuff on the screen (HTML and CSS), and a separate one for control flow (Javascript).

The proof Javascript is integrated badly with HTML/CSS is jQuery. One wouldn't need a special framework if UI and language were built from the ground up to work well together.

7. The web needs HTTP

Besides using three languages, the web also uses a separate protocol to coordinate how to run code. That's the fourth thing it needs.

We didn't need a separate protocol to run desktop apps. Apps just ran. They called functions in memory or saved data on disk, and we didn't have to write special code to program for the network. [3]

In fairness the network is a new resource the desktop didn't have. Networks may always need protocols. But a big problem with protocols is they stop working as soon as the problem changes, and as we've seen with inventions change is not only common but also uncontrolled. [4]

If you want to see HTTP is having trouble to adapt, have a look at the list of HTTP error codes. There are some practically no one uses, like Unprocessable Entity, Failed Dependency, and Upgrade Required. And there are new ones that were added when new protocols like WebDAV and Twitter were created. But no individual application can add new error codes.

Web apps raise errors beyond what the list of HTTP errors covers and as a result web apps write an extra layer to return error codes on top of HTTP. Why must there be two layers to do the same thing?

And that's just on error codes, not features. This is a big deal if you need to change how the web works, like make file uploads get encrypted automatically. It's impossible to add new features to HTTP on the fly for everyone that runs a web server.

8. You don't know what happens when or where with the UI

UI work that should be simple isn't always simple with the web. Something as simple as setting the selectedIndex for a dropdown breaks because some other container was automatically added around the dropdown by a third-party control. Making an input or textarea wider or taller doesn't just work or do what you want. You don't always or easily know if a framework automatically modifies your controls, when, where or how.

This used to be simpler. Writing a UI in 2001 with Visual Basic or MS Access was simpler than writing a UI in 2016 with the web. [5] If you wanted to change the width, height, or some other property in the UI, there was only one place where you had to look to change it and it just worked. Now there are too many places to look and it doesn't.

9. Refreshing web pages is a bad UX

Refreshing web pages is slow enough to damage the user experience. You have to wait for a page to refresh unless the web app is written ahead of time with something like React or Angular that automatically repaints the screen without issuing a request back to the server.

This wasn't a problem with desktop apps. It may always be necessary to send some requests back to the server but it doesn't have to happen on the main thread at the cost of locking up the UI.

10. There's a separate server language

Besides HTML, CSS, and Javascript for the client, and HTTP as the protocol, the web also uses a programming language for the server. That's the fifth thing the web needs. One could use Javascript on the server too but most times that's not what happens.

11. There's a separate database language

The server language often needs to save data in a database. A database often uses SQL. That's the sixth language the web needs.

Server languages try to compensate for this by using an ORM to bridge the gap to SQL. But very often frameworks have holes that force you to write SQL. It's rare to completely avoid the database language.

Why must there be such a thing as a database language, or a database to begin with? Why can't the language do it all?

12. Local storage is limited

With a web app one is forced to save data on the server. There's no option for the user to save data locally like a desktop app. And even if there was, the browser has a built-in limit of saving no more than 10MB of data locally. Ever wondered why?

It's partly because it makes app distribution easier, but there is a less optimistic explanation. That this serves the interests of companies that make browsers. The benefit of being given a free browser comes at the cost of saving data on company servers and having personal data taken away. Sometimes the goal isn't to put the user first but to increase the thickness of the wall around the garden.

A truly open browser would let the user save an unlimited amount of data locally.

13. Web apps don't run without network access

This is one of those limitations we've been gradually conditioned to take for granted. If I already downloaded an app before, why can't I run it without Internet access? Why can't some parts of the app run offline, like email clients that used to run in disconnected mode? [6]

Most desktop apps run without Internet access. Install them once and they work.

The irony here is that developers already prefer offline access when it comes to their own tools. They prefer editing code in a local text editor and terminal instead of a browser. And they prefer offline source code version control with Git. These tools are as much of the center of the universe for a developer as email and calendar are for everyone else.

If offline mode is the better choice, why can't web users have one?

14. Web apps can't run indefinitely

With a desktop app you can run the app for as long as you like. With a web app you are forced to use the latest version whether you like it or not. This isn't always the best option for the user.

Forcing the user to upgrade also isn't always the best option for the app. It may be better to stop maintaining the current app and write a new app, in a promising area no one explored before. [7]

15. Users can't modify apps

Running the same version of an app forever is a special case of choosing which version to run. The general case is to not only choose the version but also to create it: to let the user modify the app.

We used to do this, in fact. One of the most successful precursors of the web is Hypercard, a desktop app that let users edit and create new pages live. Modifying apps live was a new concept back then so it's not hard to imagine how Hypercard became addictive for developers.

But I wouldn't call it progress that today, nearly 30 years later, modifying apps live went from addictive to impossible.

(On second thought the addiction is still present but it moved. Apps are modified only on the server and only by developers, not users.)

Why can't the user customize his copy of the app to save new types of data on the server, for example? Why must there be a distinction between a client side and a server side?

I want to customize the HackerNews frontpage-rank function to sort content differently. I can't with today's browser alone. I need to modify server code to do that, which I don't have access to. [8]

Modifying the client side of an app isn't easy to do either. I can't easily filter out stories and comments in HN based on my own analysis. Writing a browser plugin isn't and will never be as easy as writing a new function in a text file.

16. Writing a browser plugin is too much work

This brings me to one of the most annoying things for me over the past year. I want a better browser and there's no easy way to get one.

Besides modifying apps being a lot of work, modifying the browser is a lot of work too. If one goes the route of trying to write a browser plugin, there are several steps and lot of docs to go through.

Meeting a browser plugin spec, creating a developer account, submitting the plugin for review, waiting for feedback, changing the plugin because the browser forbids users from calling parts of Javascript, and possibly paying.

Plus any steps added by the features in the plugin.

The worst part is the browser doesn't load the plugin when the browser gets updated. Imagine doing all this work and the browser saying "sorry, I won't let you run anymore the software you spent so much time writing."

17. Browser plugins aren't browsers

I want encryption for my data and I can imagine encryption in a browser plugin working. [9] But I doubt the UI is the right place in the software stack to fix the problem. It's not just that it complicates the user experience; that can be worked out. The bigger problem is it complicates the developer experience. It adds several extra steps for developers that can't easily be abstracted away.

And since there are several steps for encryption specifically, there are probably several steps for other features in general. Every one of these steps complicates the web experience for developers.

So allowing for browser plugins doesn't solve everything because some features belong in the browser itself. The tough part is finding the right balance, choosing which parts of the browser can be programmable and which can't.

18. The web is hard to setup and debug

Debugging is probably on top of programmers' minds when they're about to choose new tech to use. Is it easy to install? Will I be able to fix it when it breaks?

Installing apps wasn't an issue with desktop apps. It was easy to copy a directory containing an app from one machine to another and have it run without problems. Moving a web app around machines is nowhere as easy.

Every time my website breaks it's because I upgrade the web server and something goes wrong with the upgrade. (Same with my email server.) And that's if I manage to configure the web server and all the plugins it needs for a web app to begin with. Configuring SSL for encryption is still a gamble. Every time there's a web app I want to write I get deterred by the thought of setting it up.

19. Server code can't fix the browser

How did we get this far if there are so many problems with the web? By relying on the server. Today's server frameworks are the modern equivalent of highly optimizing compilers.

Sadly no server can fix what's beyond its reach. The server can't change the client. This problem is architectural. The big thing to change is the browser.


[1]  I don't think we should be worried about this. No one knew what would keep programming easy in the network, so we may as well view it is as a valuable research experiment we would have had to carry out anyway. We'd have to go through version one of programming for the network before figuring out version two.

[2]  I don't know if this is an inconsistency in CSS's definition or implementation.

[3]  There may be more room here to simplify the Internet than most people realize. A good place to look for insight is earlier, successful operating systems.

Ken Thompson, one of the inventors of UNIX, had this to say about the Internet:

My ideal for the future is to develop a file system remote interface (a la Plan 9) and then have it implemented across the Internet as the standard rather than HTML. That would be ultimate cool.

[4]  The protocol should be easy to change live. For example, by sending code that replaces the old protocol instead of just sending data for the protocol to use.

[5]  Programming for mobile is just as bad. Both XCode and Android Studio are light years behind the simplicity of Visual Basic 3.1 from 1993.

[6]  Yes, this is a problem for me. I lose Internet access many times a day. Offline access is not an unreasonable feature.

[7]  In 2006, eight years after Windows 98 was released, there were still 50 million copies installed. Users were happy enough that they didn't want to upgrade. This should have been a sign for Microsoft that the next big thing to work on was anything other than a brand new desktop operating system.

Imagine how the Internet would look today if ten years ago one started building a browser that worked differently.

[8]  I realize the data are available separately and can be used to write a new UI, but I want to sort content differently in the fewest lines of code possible: by changing only the sorting function.

[9]  When you log in a website the password encryption happens on the server, not the browser. The website can see your password in plaintext.