It's like a web view, but native

amatheus2 pts0 comments

It’s like a web view, but native | Marcus Lewis

I think modern operating systems should support something I call the outerframe. An outerframe is like a web view, but it runs compiled machine code and uses the underlying operating system’s APIs to create UI.

A fundamental reason web views are useful is that they let the user experience be driven by something external, rather than confining the app to only use rigid built-in native app logic. The web view serves as a safeguard, preventing the external code from doing something dumb or nefarious.

The problem with the conventional web is its inefficiency, sacrificing the quality of the final product to make life easier for developers. For example, in my benchmark last year, web apps had a ~6x reduction in efficiency compared to their equivalent outerframe app. Up until recently, these costs have actually been fine, because high-end phones and laptops have been getting more powerful without a clear use case for all that power. But now there’s a renewed need for efficiency, both on high-end laptops and low-power devices. At the high end, there is a race to build useful local AI into the device, and this local AI can use every transistor and watt that we can free up. Meanwhile at the low end there’s a race to build a compelling AR / VR headset, which could conceivably move a lot of our work out of desktops and laptops and into the physical space of our rooms. It’s time for conventional software to get out of the way and fit into a smaller footprint, making room for local AI and new classes of devices. And, luckily, we simultaneously have a rise of AI code generation, which makes this practical.

With this blog post, I am open-sourcing an outerframe for macOS. The outerframe is a key part of Outer Loop, which uses it for SSH-based apps. The outerframe repo also contains “Outer Frame”, a simple web browser that you can build and launch from Xcode on a Mac. Try vibe-coding your own outerframe content, or try putting an outerframe in your own app.

Top: The first outerframe app

Because the first app to use the outerframe is an SSH client, the first outerframe app that I’m shipping is a modern top app. I call it Top (with a capital ‘T’).

Here’s a video walkthrough.

The Top backend can be run on any Linux or Mac device, and Outer Loop can install it for you with one click. See more here.

How it works

Broadly: The browser downloads a dynamically loaded library (a .dylib / .dll / .so file) and loads it into a sandboxed process. The sandboxed process renders the window contents. The browser and the sandboxed process send messages back and forth for various user interaction events and APIs.

I designed the outerframe for an ambitious possible future where it becomes part of the open web. The philosophy of the web would shift to being multi-platform, rather than cross-platform, while still using HTML where it makes sense. Webservers could choose to serve multiple implementations of their web apps, one per platform. Here I’ll describe how a browser and webserver negotiate which code to run. Then I’ll describe how the macOS-specific outerframe works.

The HTTP requests and the file formats

We need a cross-platform protocol that hands off to platform-specific behavior. Here’s the current spec for browsers and web views supporting the outerframe.

On navigation, the browser sends the additional HTTP header Outerframe-Accept: application/vnd.outerframe. (Ideally it would instead do this in the Accept header, but Apple’s web view doesn’t expose a way to modify Accept on navigation requests, so I chose to add a new Outerframe-Accept header.) If a server wants to respond with outerframe content, its response HTTP headers should include Content-Type: application/vnd.outerframe. When the browser sees this header, it parses the response body as:

byte 0..3 The ASCII string "OUTR", as a "magic" sanity-check<br>byte 4..7 UInt32 little-endian format version, currently 1<br>bytes 8..15 UInt64 little-endian offset to beginning of path<br>bytes 16..23 UInt64 little-endian length of path<br>bytes 24..31 UInt64 little-endian offset to beginning of data<br>bytes 32..39 UInt64 little-endian length of data<br>remaining Variable length region, where path and data live

This is the outerframe’s analog of an “.html” file, and I call it the “.outer” file. Its contents are simply a format version, a path, and a data blob. Right up front, you see how this philosophy is different from the conventional web. This is not just plaintext, instead it’s an extremely-fast-to-parse binary format. You’ll generate this blob programmatically (e.g. using a simple Python script), or edit it with a hex editor. Making this format binary is planting a cultural flag: we put users, not developers, first. HTML already exists, so this platform gets to focus on the other extreme.

The browser parses the path and appends a platform string, for example this macOS implementation appends “/macos-arm” (or “/macos-x86” on Intel Macs)....

outerframe browser platform view macos little

Related Articles