The Lenovo ThinkVision P27h-20 screen I get from work is a decent 27 inch screen. Coming from the Retina screen of my laptop that I worked on for a long time, I was initially (and still am) not impressed by the resolution of 2560Γ1440. It took some time to get used to the low resolution on such a big screen, but it gets the job doneβ¦
My biggest gripe with the screen was that it just randomly turned off when connected to my MacBook Pro in clamshell mode. I finally found the culprit after combing through the Console system logs for any trace for the longest time. I found out that the MacBook Pro thought the power was changing from grid to battery and vice versa (all while being constantly on-power), and whenever it did that, the screen would turn off.
The solution was to disable the "Smart Power" option in the screen's settings. According to the manual, the "Smart Power" option does the following:
Smart Power intelligently distributes power to connected USB and USB Type-C devices, maximizing power supply efficiency while also reducing overall consumption.
Turns out, it wasn't so smart after all. I saw it range between 65W and 90W, but after turning the option off, the laptop gets a constant 65W, all my USB-C devices still work, and I'm happy to report that the screen no longer randomly turns off. This is the blog post I wish I had found when I was looking for a solution, so I hope it helps someone else.
The WebAssembly meetup in Munich has a history that
reaches back to 2018.
After a long Covid-related hiatus and a lack of organizers to pick up the ball
again, A Wasm New Year! was the first event under the new organizing team.
Google always had a strong presence at the events, so to continue the tradition
I happily agreed to offer a talk at the first post-Covid meetup.
Compiling to and Optimizing Wasm with Binaryen π
Speaker: Thomas Steiner
In the first half of the talk, I showed at the example of a toy programming
language that I called ExampleScript how to write a compiler with Binaryen that
compiles the toy programming language to WebAssembly. In the second half, I then
demonstrated various optimization techniques in Binaryen and ways to use them
from JavaScript with Binaryen.js and from the command line with tools like
wasm-opt and wasm-merge.
In this talk, Sven showed three ways of how Wasm helps with interacting with
large language models (LLM): in the browser, on the command line, and in the
cloud. His running example was the task of creating a bedtime story from the PAW
Patrol ecosystem for his daughter. First, the speaker demonstrated
WebLLM running variants of
Llama 2 and
Mistral-7B right in
the browser. He mentioned the challenges of keeping large models cached, and
also showed how these models have trouble with seemingly simple tasks like
creating a list of the
PAW Patrol members, where
the model would plain hallucinate a member that never existed. Second, Sven
showed how to use the
run-llm.sh script to get an
LLM running on-device with WasmEdge. He noted the
usefulness of this approach to mock an OpenAI API response due to the
compatibility of the responses. Finally, he showed
Fermyon's Spin solution to
create serverless WebAssembly apps,
run them locally, and finally deploy them to the
Fermyon cloud.
There was huge interest for Wasm on the server. People were particularly curious
about
WASI,
the WebAssembly System Interface. It's an API in the process of standardization
that provides access to several operating-system-like features, including files
and filesystems, Berkeley sockets, clocks, and random numbers. (There's also a
proposal for wasi-nn, a WASI API for
performing ML inference modeled closely after
WebNN.)
The 2023 edition of the World Wide Web Consortium (W3C) Technical Plenary and
Advisory Committee (TPAC) meeting took place from September 11 to 15 in the
MeliΓ£ hotel in Seville,
Spain. The hotel is located right next to the
Plaza de EspaΓ±a,
a major Spanish tourist destination. The setup of the meeting was hybrid, and on
site, strict Covid precautions were enforced, even though the pandemic was
declared to be "over". Despite these methods, several people caught it. This is
my personal report as a representative of the Chrome DevRel team at Google.
I attended the
Web Applications Working Group meetings on
Monday and Tuesday. After a quick rundown of all the APIs in scope for the
working group, the first topic was the
Screen Orientation API,
which was mostly driven by questions and improvement proposals the WebKit folks
had after implementing it.
Next, the group discussed the Badging API, which is only available after
installation, and browsers differ on whether they make the API detectable when
the app is running in a tab.
An interesting corner case was debated in the context of the joint meeting with
the Devices and Sensors Working Group.
Apple can't join the group due to its unwillingness to implement some of the
APIs and the sheer volume of proposals the team would have to review. The
workaround is
shared deliverables,
where the APIs that there is agreement on get cross-delivered by a working
group Apple is part of.
The group made no progress on FranΓ§ois Beaufort's suggestion for a
Screen Brightness API.
On the topic of
DeviceOrientation API
vs. Generic Sensor API, the
soft-conclusion was that the new API provides not enough advantage over the
existing API. There's still disagreement about whether using the API should
require a permission, which is mostly used for fraud detection to determine if a
real user is holding a device.
For the
Geolocation API,
most discussion circulated around limiting its precision by encouraging more
coarse data. On the opposite side, there's also still the open question of
floorLevel data, which Safari exposes, but which isn't standardized. The group
briefly discussed a toJSON() method for geolocation results, but it probably
would be a breaking change due to instanceof checks. The
background geolocation
discussion was taken over repeatedly by trolls, which made proper discussion
partly impossible. It's a solve-worthy problem, albeit it's a heated space.
Geolocation Sensor had promises but
we're not sure it's worth bringing this over, since the callback can easily be
wrapped.
On Monday afternoon, I switched over to the Web Platform Incubator Community
Group (WICG) meeting. The topics I was
interested in were Low Level Device APIs and First Party Sets (now Related
Website Sets).
In the first part, Vincent Scheib presented on low level device APIs. Firefox
has rolled out
Web MIDI access based on an ad-hoc extension,
which didn't seem it would convince Apple people. Apple also had doubts whether
a permission prompt would be enough for people to understand that devices can be
abused to circumvent the same-origin model. Reilly Grant outlined that Chrome
stopped tying WebUSB to websites in an attempt to keep devices usable, even if
the original website disappears.
For First Party Sets, there are currently only a few entries in the
First Party Sets list,
following the
Submission Guidelines.
It's rolling out to Chrome slowly. Other browser vendors do not implement First
Party Sets at the moment.
On Tuesday, the big topic was installable web apps where Dan Murphy presented
our existing solutions around
Launch Handling.
Marcos from Apple and Olli from Mozilla questioned the queue model vs. an event
model and suggested to replace LaunchParams with DataTransferItem. Apple
noted that a launch handling feature is something that they would probably need.
Apple's questioning of Chrome's established solution caused me to raise a meta
question: Chromium already asked for input years ago and got no meaningful
feedback and then shipped a solution that was proven to be successful. Now
other vendors are interested, but want to change the fundamental design (and
perhaps together we can all agree on a better design). What is the process
here? Are we as Chrome supposed to unship ours?
Sangwhan Moon provided the Technical Architecture Group
(TAG) perspective that Chrome makes sure other vendors
provide input before Chrome ships. Chrome can't wait until vendors have an
active interest. The group agreed to discuss next steps.
Diego from Microsoft then presented the
Install API proposal.
There was general interest in a solution, but a lot of skepticism when it comes
to cross-origin installations, which would be an important use case for app
stores or search engines.
The group further discussed the standardization of
[iOS' proprietary navigator.standalone](https://github.com/w3c/manifest/issues/1092).
After that, we looked at the
update algorithm
discussed at the last TPAC and confirmed an update token would be the way to go.
The group briefly touched upon isolation of installed apps from the running
browser context and the challenges it introduces with OAuth etc.
Wednesday was the breakout session day. As always, there were some sessions that
I wish I could have attended, but due to scheduling conflicts I couldn't. Below
is the list of the sessions I attended.
Accelerating the Web performance by compiling Javascript code to WASM π
This session introduced JWST, a JavaScript to WebAssembly static translator
(compiler) co-developed by Huawei and a professor from a university in Beijing,
after claiming the (somewhat [citation needed]) problem of slowness of
JavaScript being a problem for web apps and the lack of DOM access of Wasm as a
major challenge. The presented compiler in their example converted a ~1.6MB
JavaScript app (which is already big) into a >20MB Wasm app that under certain
conditions slightly outperformed the JavaScript solution in their benchmark. I
asked for more details about the compiler, but there wasn't any and the Huawei
representatives said they weren't entirely sure about open-sourcing it. As it
stands, my current evaluation of the solution is that it's technology
feasibility demonstration at best.
Page Embedded Permission Control (Permission Element) π
In this session, the Chrome team introduced our current thinking of a
permission element. The reaction from both Apple and Mozilla was that they
both "don't immediately hate it". Many questions remain to be answered, mainly
around how this would deal with multiple permissions, whether it should allow
blocking permissions, the spoofability of its UI and whether that poses a risk,
the customizability of its UI, and how revoking permissions would look like with
it.
The Future of Powerful APIs on the Web Platform π
This TAG-initiated session stated the problem of powerful APIs on the Web,
leading to permission fatigue and browsers simply not implementing certain APIs
as a consequence, and motivated something like an extended trust mode for the
Web. Sangwhan Moon said that without all browser vendors agreeing, the situation
would not improve. Mozilla sort of soft-excluded the browser from the effort by
stating that they were not thinking of messing with the origin model and to not
assume that all capabilities were on the table. They also said as a community,
we shouldn't let envy of native capabilities drive this.
This session introduced the
privacy principles jointly
developed by TAG and Privacy Interest Group
(PING) and solicited feedback from the persons
in the room. The document is currently in wide review and seeks to be both
aspirational and practical. Each member of the author group outlined their
favorite sections of the document, like data minimization, device owners and
administrators, or execution context. I asked about a conscious opt-in for
objectively hard to understand things like requestStorageAccess() to which the
answer was to abstract as much as possible in the permission prompt.
The cross-browser future of Installable Web Apps π
This was a session I had organized together with Apple, Microsoft, and Intel. We
discussed a number of approaches to installability taken by the various
browsers, including new surfaces like sidebars and widgetsβa currently
proprietary approach based on Microsoft's
Adaptive Card format. Of special interest was
whether criteria should be required before a Web app can be installed. Chrome
talked about the no longer required service worker. Apple insisted no
requirements at all should be made, not even a title or icon. Apple's
requirements for installable experiences are focused on ensuring consistent
experiences. Users should know exactly where to go in their device settings to,
for example, turn off Web push notifications, which require installation on iOS.
We ended talking about extensions and whether they should be exposed in
installed apps. Currently, Chrome and Edge expose extensions, Safari doesn't.
This was again a deep-dive in Microsoft's
Web Install API
proposal. Many points or arguments were already made in the
WICG session on Tuesday
(same notes document as for the breakout session). A noteworthy new point was
the question if something like sidebar apps should be supported in a sense that
a PWA would be able to express it would like to be installed to the sidebar.
Apple said the baseline assumption of this API should not be that of an app
store; the API should be useful in itself. If stores are involved, how would
stores know if an app was already installed through another store or mechanism?
Could getInstalledRelatedApps() be the solution for this? Another point raised
was the trackability of installs, so stores could know if an installation was
triggered by them, and apps what store an install came from. Finally, we
discussed double prompting, first a bootstrap prompt whether a store may install
apps in general, and then a concrete prompt to install a given app.
Geolocation Sensor where
we went through the existing use cases for background geolocation and
geofencing again.
Screen Brightness API
with no updates since Apple's negative feedback on an imperative API and after
FranΓ§ois Beaufort's
proposal for an element
attribute for increasing the screen brightness.
Battery Status API which
might be turned into a user preference media feature.
Next, Intel gave a device market overview followed by an implementation overview
including compelling use case demonstrations for the
Device Posture API.
Fine-grained angle information was removed from the spec due to privacy
concerns.
In the following, Intel continued on presenting on the
Compute Pressure API, with
a special focus on cross-site tracking mitigations through randomization that
were proven to be effective in experiments, plus showing future extensions for
the API like memory stalls and an "it's you" hint when the current process is
responsible for CPU usage peaks.
The day ended with a look at the
Geolocation API, which is
mostly stable but could add improvements around encouraging more coarse location
access.
As a meta remark, I feel like as a working group, we didn't achieve much new
things compared to last year, mostly due to a lack of cross-implementer support
for some of the APIs like the generic sensor APIs, and only a limited appetite
to move on with things vendors at least partially agree on like screen
brightness or ambient light sensor.
On Friday, I saw an interesting
proposal for a headinglevelstart
attribute that would allow authors to embed content with a heading structure
into another context with an already existing heading structure, while overall
correctly nesting both heading structures. This was mostly driven by GitHub, who
embedREADME.md files into repository homepages and who wish to adjust heading
levels accordingly.
Next, a
focus navigation start point proposal
was brought forward, which would allow to set the start point for the next focus
point (which is not the same as the focus). Again this was driven by GitHub, who
wanted to make the file tree fully keyboard-navigable.
Noteworthy was also a
proposal for an Observable API presented
by Dominic Farolino , which would allow for more convenient event handling
scenarios and that was greeted with great interest.
In the afternoon, I attended Web Incubator Community Group
(WICG) sessions focused on the Accessibility Object Model
(AOM), the Shape Detection API, and the File System.
Unfortunately the AOM session was a little confusing and it was not entirely
clear what the status of the AOM was and which parts of it are cross-browser vs.
abandoned. The
AOM explainer contains
many abandoned sections and the AOM spec is
just a barebones skeleton, plus the
demo doesn't work (anymore).
For the
Shape Detection API,
there's some interest from Apple to implement this. They raised questions about
batch processing and synchronization challenges with video, which would likewise
apply to blurring. I pointed at my demo
that solves this with
MediaStreamTrack Insertable Media Processing using Streams.
Apple was also worried about the Chrome-specificity of the test suite and the
future venue of the proposal, hinting it could be the
WebML WG. As a final point, I
noted that Apple's implementation works, but only on the main thread and not in
workers. This is a known issue and "for reasons", according to Apple.
The File System Access session proposed by Austin Sullivan unluckily saw no
attendance from Apple or Mozilla, so the meeting was adjourned since it would
have been Googlers preaching to Googlers (and Google Developer Expert
Christian Liebel).
On the end of the day, I crashed the Web App Security WG meeting and saw Mike
West's proposal for
purposeful permissions. I
made the point for aligning with other efforts in this area in an
issue, namely the
W3C MiniApp Manifest and Isolated Web Apps permissions.
Covid measures were strictly enforced during the indoor sessions with a masking
mandate and encouraged daily testing. All the breaks and lunches were outside or
outside-ish (partially in a well-vented tent). After hours at dinners and drinks
at the hotel bar, everyone partaking in those activities took their masks off.
There were, I think, around 15 documented cases of infections.
It was really, really great to be able to do in-person events again. While the
group meetings worked pretty well with remote attendance (both from across the
world, or from the conference hotel if you caught Covid), the famous hallway
track and spending time with people at dinner or after-hours drinks is just not
replaceable by video conferencing technology.
Food was boxed lunches with the now infamous soggy potato chips and each day a
variety of pre-packed industrial sandwiches. It felt wasteful, since there was a
lot of food in a lot of packaging. Maybe a buffet-style lunch would have been
better. There was typically an early dinner train, which ended up in one of the
tourist trap-ish restaurants in old town that open early compared to local
Spanish dinner times. My food quality indicator was always to check the bread:
if it's plastic-sealed, the food will be fine; if it's fresh, it will be
amazing.
Coffee was available in the breaks, and either horrible if you got the milk
directly from the machine, or great if you got the milk separately from a
waiter.
There were (again) a lot of people from Google in attendance. This year, we made
a concerted effort to highlight more closely what team we represent, for
example, Google Chrome, rather than all of Google. More than once, I saw other
people mirror this, and introduce themselves as "from the X team at Y".
With macOS Sonoma, Apple goes all-in on the concept of installable web apps.
They're highly integrated in the overall macOS experience and don't give away
their web roots by not showing any Safari UI at all.
Tested on macOS Sonoma 14.0 Beta (23A5257q) with Safari version 17.0
(19616.1.14.11.11). It probably doesn't matter, but the testing device was a
13-inch, M1, 2020 MacBook Pro.
On macOS Sonoma, you can add a websiteβany website, not just apps with a
manifestβto your Dock. Go to the Share icon and click Add to Dock, or
use the menu item File > Add to Dock.
Adding an app via the Share icon.
Adding an app via the File menu.
You can adjust the name and icon if desired. The URL is the URL you're on for
pages without a manifest, or the start_url for pages with a manifest. It can't
be changed. For pages without an icon, Safari will create a fallback icon based on the first letter of the page's title.
π Observation: Unlike on iOS/iPadOS, you can't add the same app twice,
unless you rename it.
App name and icon are adjustable, the URL is not.
The web app icon then appears in your Dock. Maskable icons are supported, and
the typical macOS squircle shape is respected. Closing all windows of an app
leaves the app running, aligned with macOS UX paradigms.
π Observation: Unlike on Chrome, the app doesn't launch immediately and
"morph" from in-tab to in-app, but instead you remain on the tab and need to
launch the app manually.
Web app added to the Dock.
When right-clicking the Dock icon, you can uncheck Keep in Dock and still launch the app via Launchpad, Spotlight Search, or even just by double-clicking the app icon in ~/Applications/.
The out-of-the box launch experience of web apps is fantastic. Nowhere does it
give away that this is a web app. For apps with a manifest, there's no Safari UI
whatsoever, and the expectation is that such apps are single-page apps that
provide their own navigation controls. If an app is well made, lay persons
probably wouldn't be able to tell that something is a web app.
Web app running without any Safari UI.
π Observation: Different from iOS/iPadOS, credentials in cookies are copied
over, so if you were logged in when running in the tab, you're logged in when
you launch the app. No other storage means apart from cookies are copied. "When a user adds a website to their Dock, Safari will copy the website's cookies to the web app. That way, if someone is logged into their account in Safari, they will remain logged in within the web app. This will only work if the authentication state is stored within cookies. Safari does not copy over any other kind of local storage. After a user adds a web app to the Dock, no other website data is shared, which is great for privacy".
π Observation: Web Inspector (DevTools) is blocked, even with the Show features for web developers checkbox checked. There's no Develop menu item nor can you right-click and Inspect Element. This looks like a conscious decision.
π Observation: Extensions don't run and likewise aren't displayed. Also
probably a conscious decision.
π Observation: Same-origin (in-scope) links are handled in-app, cross-origin (out-of-scope) links open in the default browser. A notable exception are OAuth flow links, which are handled in-app based on a heuristic.
If a user navigates to an already installed app
in Safari, a prompt is displayed that invites the user to Open in web app.
Web apps on Mac let you focus on the websites you use all the time, separate
from the rest of your browsing. Like all Mac apps, web apps work great with
Stage Manager, Mission Control, and keyboard shortcuts like Command + Tab. Web
apps can be opened from the Dock, Launchpad, and Spotlight Search.
Web apps work with AutoFill credentials from iCloud Keychain and from
third-party apps that have adopted the
Credential Provider Extension API.
Users can grant permission to a web app to use their camera, microphone and
location in the same way they grant such permissions to other Mac apps through
system prompts and the Privacy & Security section of System Settings.
System settings with Camera permissions.
Web apps on Mac support
web push,
badging, and
all the usual web standards implemented by WebKit, just like web apps
on iOS and iPadOS.
π Observation: There seems to be a bug where the hosting Web App appears as
the app requesting the Notifications permission. Notifications then work as
expected, though, including using the correct icon.
Notifications permission prompt with the wrong app name and icon.
Web apps have their own Settings dialog. In General, the app name and
icon can be changed and navigation controls can be toggled on or off. The
theming behavior of the title bar
can be changed, too.
π Observation: Navigation controls are toggled off when there's a manifest
with "display": "standalone". In all other cases, even if a manifest exists
but with a different "display" mode,
Web app Settings dialog on the General tab.
π Observation: There's currently a bug where web apps don't correctly report matchMedia('(display-mode: standalone)'). Added to the Dock web apps think they run in a tab.
With navigation controls enabled, there's an Open in Safari icon in the
upper right corner. Despite its label, it actually respects the user's default
browser.
Open in Safari icon.
Web pages get navigation affordances in the form of a back and forward button.
There's no reload button.
Back and forward buttons.
π Observation: With navigation controls toggled to off, the title of the
web app sourced from the manifest is not shown. With navigation controls toggled
to on, the title sourced from the <title> is shown.
π Observation: When you right-click, there's a context menu with Reload or Back and Reload. This works independent from whether navigation controls are toggled on or off.
The Privacy tab allows the user to clear website data and links into the
Privacy & Security Settings of the System Settings app.
All apps are stored in ~/Applications/. The package contents of each apps are:
a _CodeSignature folder with code signature metadata
a Resources folder with just the app icons as a single
ApplicationIcon.icns file
an Info.plist file.
The package contents of an app.
The Info.plist file interestingly contains an XML version of key parts of the
manifest and metadata about the app.
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPEplistPUBLIC"-//Apple//DTD PLIST 1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plistversion="1.0"><dict><key>CFBundleIconFile</key><string>ApplicationIcon</string><key>CFBundleIdentifier</key><string>com.apple.Safari.WebApp.svgco.de.53298B34-AF7F-4074-9CA9-1EE46B7E3E83</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundleName</key><string>SVGcode</string><key>CFBundlePackageType</key><string>AAPL</string><key>CFBundleShortVersionString</key><string>1.0</string><key>CFBundleSupportedPlatforms</key><array><string>MacOSX</string></array><key>CFBundleURLTypes</key><array><dict><key>CFBundleURLSchemes</key><array><string>x-webkit-app-launch</string></array><key>LSHandlerRank</key><string>None</string></dict></array><key>CFBundleVersion</key><string>1</string><key>LSMinimumSystemVersion</key><string>14.0</string><key>LSTemplateApplication</key><true/><key>LSTemplateApplicationParameters</key><dict><key>CFBundleIdentifier</key><string>com.apple.Safari.WebApp</string><key>TemplateAppUUID</key><string>53298B34-AF7F-4074-9CA9-1EE46B7E3E83</string><key>defaultarguments</key><true/><key>teamIdentifier</key><string></string></dict><key>Manifest</key><dict><key>description</key><string>SVGcode is a Progressive Web App that lets you convert raster images
like JPG, PNG, GIF, WebP, AVIF, etc. to vector graphics in SVG
format.</string><key>display</key><string>standalone</string><key>icons</key><array><dict><key>purpose</key><string>maskable</string><key>sizes</key><string>1024x1024</string><key>src</key><string>https://svgco.de/favicon.png</string><key>type</key><string>image/png</string></dict><dict><key>purpose</key><string>any</string><key>sizes</key><string>150x150</string><key>src</key><string>https://svgco.de/favicon.svg</string><key>type</key><string>image/svg+xml</string></dict><dict><key>purpose</key><string>monochrome</string><key>sizes</key><string>150x150</string><key>src</key><string>https://svgco.de/favicon-bw.svg</string><key>type</key><string>image/svg+xml</string></dict></array><key>name</key><string>SVGcode</string><key>scope</key><string>https://svgco.de</string><key>short_name</key><string>SVGcode</string><key>start_url</key><string>https://svgco.de/</string><key>theme_color</key><string>#ffffff</string></dict><key>WKPushBundleMetadata</key><dict><key>manifestId</key><string>https://svgco.de/</string></dict></dict></plist>
Similar to iOS/iPadOS, web apps run in the context of a separate process called
Web App.app, which resides in
/System/Volumes/Preboot/Cryptexes/App/System/Library/CoreServices/Web App.app.
π Observation: Separating Safari and Web App allows both to run
independently. You can open a Web app without opening Safari, you can close
Safari without all web apps closing.
The Web App.app app in Finder.
Each web app runs as its own process of kind Web, accompanied by a number of
helper processes of kind Apple. They can all be seen in Activity Monitor.
Activity Monitor showing all processes associated with a web app.
Add support for the
File System Access API,
so users can install apps and edit files directly, rather than opening them
and then downloading a copy.
[π§Β 231706]
Add support for the
File Handling API,
so web apps can open files from Finder by double click if the web app is
registered as the default file handler for a given file type, or by right
click and then Open with if the web app can handle a file type, but isn't
the default file handler.
[π§Β 257783]
Reflect the cookie-copying logic on iOS/iPadOS. It's a very frustrating
experience if you have to log in twice, even more so if two-factor
authentication is involved.
[π§ 257786]
Allow users to turn off the Open in web app prompt.
Better respect macOS' design paradigms. Currently web app icon handling looks
not integrated and icon shapes are all over the place. The examples below are
all web apps installed via Chrome.
Web app icon shapes installed from Chrome don't respect the squircle.
Move the extension puzzle piece and the Window Controls Overlay chevron into
the three dots menu. Web apps can look so much cleaner without both in plain
sight.
Window Controls Overlay chevron and extension puzzle piece clutter the UI of
Chrome-installed apps.
With Chrome and Safari now allowing web apps to be installed on macOS, it would
be fantastic if installed apps could respect macOS UX guidelines and populate
the system-level menu. Ideally Apple and Google engage jointly on the
corresponding Project Fugu π‘ API request tracked in
crbug/1295253.
Web apps in macOS Sonoma 14 Beta seamlessly integrate into the macOS experience,
with no or very little visible Safari UI and with support for various operating
system features. There is an enormous potential for web apps on macOS to
succeed, and if Apple only works on a third of the items on my wish list, the
potential is even bigger.
There's this old mantra that Cool URIs don't change that Tim Berners Lee has been championing since 1998. And in the subtitle of the linked document it says:
What makes a cool URI?
A cool URI is one which does not change.
What sorts of URI change? URIs don't change: people change them.
And that's exactly what happened in my case: I changed them. Tim goes on later in the document:
Pretty much the only good reason for a document to disappear from the Web is that the company which owned the domain name went out of business or can no longer afford to keep the server running.
That latter part ("or can no longer afford to keep the server running") was meβa person, not a companyβin my late, money-saving student days. At the time, I owned tomayac.de, and after making the switch to tomayac.com, I let go the .de domain after a while because I didn't want to pay for it anymore.
While I did make sure to redirect everything properly (that is, using a permanent 301 redirect), the problem really was that I had referenced the .de domain in my printed Master's thesis that I couldn't change and in which I wrote about a tool I built called REST Describe & Compile. And of course over the years I had accrued the occasional external link that I likewise couldn't control.
Now all that remains is setting up DNS properly, get a certificate, set up an .htaccess, and all these things I'm not really good at and never know if I'm looking at the cached version from the DNS server or the live one, but I'll figure it out eventually and make all those cool URIs work again!
There's this old mantra that Cool URIs don't change that Tim Berners Lee has been championing since 1998. And in the subtitle of the linked document it says:
What makes a cool URI?
A cool URI is one which does not change.
What sorts of URI change? URIs don't change: people change them.
And that's exactly what happened in my case: I changed them. Tim goes on later in the document:
Pretty much the only good reason for a document to disappear from the Web is that the company which owned the domain name went out of business or can no longer afford to keep the server running.
That latter part ("or can no longer afford to keep the server running") was meβa person, not a companyβin my late, money-saving student days. At the time, I owned tomayac.de, and after making the switch to tomayac.com, I let go the .de domain after a while because I didn't want to pay for it anymore.
While I did make sure to redirect everything properly (that is, using a permanent 301 redirect), the problem really was that I had referenced the .de domain in my printed Master's thesis that I couldn't change and in which I wrote about a tool I built called REST Describe & Compile. And of course over the years I had accrued the occasional external link that I likewise couldn't control.
Now all that remains is setting up DNS properly, get a certificate, set up an .htaccess, and all these things I'm not really good at and never know if I'm looking at the cached version from the DNS server or the live one, but I'll figure it out eventually and make all those cool URIs work again!
The other day, I came across Elk Native, a native version of the rather excellent, if early-stage, Mastodon Web client Elk. To be honest, I wondered why they would build a native version, if the Web client works so well. I downloaded the 7.8Β MB Elk_0.4.0_macos_x86_64.dmg and immediately ran into Issue #74, that is, a blank screen.
To better understand the motivation behind the Elk Native developers, I tried the same for one of my apps, with different frameworks. This repository contains the same PWA, SVGcode, wrapped five times with different cross platform software frameworks.
SVGcode is included as a git submodule in each framework folder. To run the apps, you first need to build SVGcode, and then start the wrapper app. In each subfolder, run the following commands.
β οΈ I'm a Web developer, not a desktop app developer. I simply followed the "Getting started" guides and may well be holding the frameworks wrong.
While I managed to get all apps to run, none of them worked perfectly out of the box, and there was always a strange error I could not explain. SVGcode works fine on Chrome, Safari, and Firefox when run in the standalone browsers. To see what's under the hood of the frameworks, I looked at the user agent data via DevTools.
// If `navigator.userAgentData` is available, use it. copy(JSON.stringify(await navigator.userAgentData.getHighEntropyValues([ "architecture", "bitness", "model", "platformVersion", "uaFullVersion", "fullVersionList", ]),null,2));
// Else use the user agent. copy(navigator.userAgent);
I started looking into building the apps, but didn't get too far. Electron.js looks like it has the most developed toolchain, but when I ran electron-forge make, I ended up with a 332,1Β MB executable called svgcode-electron.app that only showed a white screen, despite the electron-forge start development app working mostly fine.
To build the apps, run the following command in each subfolder. (So far I have only worked on Electron.js.)
npm run build
I didn't even look into the signing part, which is required for proper distribution.
I'm not sure what to make of this. To be honest, I didn't see anything that would be more compelling than just browsing to svgco.de, clicking Install, and be good. But then I obviously didn't tap into any of the native features that cross platform frameworks allow you to do. I only noticed how features that I get for free in the Web version, like Window Controls Overlay or File Handling were broken. But again, I may just be holding these frameworks wrong. For now, it was a worthwhile exercise, but I think I'll stick to the Web.
I'm a big fan of the macOS
Continuity Camera feature, which
lets me use the camera system of my iPhone (11 Pro Max) as a webcam in macOS,
since the built-in FaceTime HD camera on my MacBook Pro (13-inch, M1, 2020) is,
well, not the greatest.
It used to work just fine everywhere in the past, but at some point it stopped
working in Chrome. It would still find the camera in native apps like
PhotoBooth, FaceTime, etc., but not in the browser. As I'm also a Ventura beta
tester and always on the latest betas, I blamed a bug there. Turns out, this is
a new-ish privacy feature and working as intended. Redditor
bonnerup filed feedback (FB11639588)
about the problem with Apple, and got the following response (sic):
Due to privacy concern with unintended camera selection, browser based video
apps only see the phone when it is in "magic pose" of landscape, screen off,
locked, motionless (not handheld), and unobstructed camera. This pose is also
used to trigger Automatic Camera Selection in supporting applications such as
FaceTime and Photo Booth.
Since this is not documented anywhere apart from a
Reddit post,
I thought I'd share it here as well. Once I put my phone in the "magic pose", it
worked just fine.
My iPhone model doesn't support all video effects yet, but
Center Stage works and
is pretty cool. It makes it look like if the camera would move and follow me. I
also use
Voice Isolation,
which helps in noisy environments.
If you want to build an app, you have several ways of doing it. You can build a
platform-specific app for the platforms you care about, for example, Windows,
Android, and iOS. In which case you would build three apps. You can also build a
(progressive) Web app, possibly in addition to platform-specific apps.
Alternatively, you can choose a cross-platform framework such as
Electron.js or
Ionic that promises to let you write once and run
anywhere. Let me begin by walking you through three extraordinary examples of
apps whose makers chose to also build for the Web, apart from building
platform-specific apps.
Beacon cases that demonstrate the Web's abilities π
I always saw Photoshop as one of the last bastions of high quality apps that
supposedly would never make it to the Web platform. Forget thatβthis last
bastion has finally fallen. With Photoshop,
Adobe, together with Chromium engineering, has managed to get a beta version of
Photoshop running in the browser that can serve as the new beacon showcase of
what is possible on the Web. In it, you can try out the commenting workflow and
test some early Photoshop editing features Adobe is piloting on the Web. You and
your collaborators can now open and view Photoshop cloud documents in the
browser, provide feedback, and make basic edits. All in one place without having
to download or launch the app.
Similarly, Microsoft has launched
Visual Studio Code on the Web,
a fully fledged, installable Web experience of its integrated development
environment (IDE) that makes developing completely in the browser possible,
including the option to open and edit files on the local file system.
Lastly Twitterβwhose progressive Web app (PWA) is
largely seen
as probably the best mainstream Progressive Web Appβhas
used
its responsive Web codebase for all platforms, mobile and desktop, via Web
browsers. On Windows, the PWA is the experience the company is confident enough
to make the Twitter experience that you get when you
install
the app from the Microsoft Store.
Twitter in the Microsoft Store
Linkability and universality: the Web's super powers π
All three companies, Adobe, Microsoft, and Twitter, in parallel with their Web
apps, have well-established, platform-specific Windows, macOS, Android, iOS, and
Linux versions of their apps Photoshop, Visual Studio Code, and Twitter
respectively. So why did they build for the Web on top? The answer lies in its
linkability and universality.
As Google's Thomas Nattestad
put it:
"The simple power of a URL is that anyone can click it and instantly access it.
All you need is a browser. There is no need to install an application or worry
about what operating system you are running on".
According to
Microsoft's Chris Dias, with Visual Studio Code
for the Web, when working with GitHub "you can make quick edits, review PRs,
and continue on to a local clone". The sole fact that you can share a link to
your work unlocks collaboration patterns that users have embraced and loved
since the birth of apps such as Google Docs. Twitter, of course, lives and dies
by its links. News sites regularly
link to newsworthy tweets,
which means "keeping it quick"is core
to ensuring people can get from an article straight into the app, where they can
read or engage with the linked tweet.
Web applications are inherently universal. They run on whatever operating system
is capable of running a Web browser and they do not need to be compiled for each
operating system separately. The same code base powers the application on all
platforms. This does not mean that there are no compatibility issuesβthere are
plenty actuallyβbut there is a
solid, shared, increasing baseline that all
applications can build upon.
While more ubiquitous on mobile, linking into a platform-specific app from the
Web on desktop is comparatively rare. On mobile (and macOS), this works via a
technology called
Universal Links on iOS (and
on macOS), and App Links on
Android. Platform-specific apps alternatively can rely on
registered protocol schemes
such as itms-apps: for when you want to deep-link into the App Store app on
macOS or iOS, or register your own custom schemes for your own apps. So while
technically possible, linking into platform-specific apps is a lot less flexible
and requires more plumbing work than simply linking into a Web app.
The slow decline of interest in cross-platform app frameworks and the rise of Flutter π
The Web isn't the only platform that promises "write once, run anywhere".
Cross-platform frameworks Γ la Electron.js do, too. With the Web becoming
powerful enough to drive apps such as Photoshop that were thought to be
impossible, we can, however, observe a slow decline of interest in
cross-platform desktop app frameworks such as
Electron.js and NW.js, and
mobile app frameworks such as Cordova or
React Native; while at the same time there is an
undeniable increase of interest in Flutter.
The following
Google Trends chart
shows the five frameworks side by side. While noting that this chart does show
disambiguated topic trends as detected by Google (as opposed to ambiguous
search term trends),
nevertheless it is clearly not an exact science.
Google Trends interest over time for Electron, NW.js, Apache Cordova, Flutter, and React Native.
[Source]
StackOverflow statistics
on tag usage also support this. The underlying assumption of people actually
using a technology correlating with people asking questions about that
technology on StackOverflow is not beyond the realms of possibility.
Shouldn't everybody be building for the Web, then? π
Given the examples of Photoshop, VS Code, and Twitter, that show that it is
indeed possible to build amazing applications on the Web, and given the Web's
super powers of linkability and universality, two research questions come up:
Web applications still lack certain functionalities that platform-specific apps
have. In the following paragraph, I list representative examples of such
functionalities on different platforms.
First, it is impossible, even with an installed PWA, to obey the macOS user
interface paradigm of having the
app menu at the top of the screen.
It can easily be achieved with frameworks such as Electron.js via the
Menu class. (On
the Web, the next best thing is
Window Controls Overlay; getting
support for app menus is tracked as crbug/1295253.)
Another example is in-app purchases on macOS that can be handled via Electron's
inAppPurchase()
method. (On the Web, the next best thing is the
Digital Goods API,
currently limited to Android and ChromeOS.) Installers are a common way users
have learned to install applications on Windows. With Electron.js, it is
possible to create
installers
and make installed applications
update automatically.
(On the Web, Web Bundles are the next best
alternative in Chrome.) This list is not exhaustive, and Electron.js is
mentioned as a representative apps framework out of several.
How big a challenge is this?
There are undeniably a number of capabilities that are missing from the Web. In
many cases, they are "nice-to-have", but not necessarily required for a still
great experience. Carefully assess if a capability can be seen as a progressive
enhancement. For an example of this approach, check out the article
Progressively enhance your Progressive Web App.
Collectively, we have educated users to look for apps in app stores. Some stores
such as the
Windows Store and
the
Android Play Store
have started to embrace (wrapped!) PWAs (optionally
limited to ChromeOS),
and offer graphical user interface tools like
PWABuilder (internally based on the command line
tool bubblewrap) for
submitting applications. Meanwhile, on other stores such as Apple's App Store,
the situation is different and less welcoming, and apps
may or may not
make it into the App Store, depending on the outcome of the app review.
Recently, Oculus, a division of Meta Platforms that produces virtual reality
headsets, has announced that PWAs would be accepted into the
Oculus Store.
How big a challenge is this?
If your users are on one of the platforms whose stores accept PWAs, you can
publish your app to the stores in question. Remember linkability as one of the
Web's super powers. Your app is discoverable, advertisable, and linkable from
the Web, too. Investing in a memorable domain name can sometimes actually be
better for discoverability. Even for app stores, people still rely most on
recommendations from friends and family members to discover new apps according
to
research done by Google.
Apart from making apps themselves available for a fee, apps can also be
monetized by selling items as in-app purchases (for example, items in a game
app), or by selling subscriptions (for example, regular courses in a fitness
app). If the developer integrates with payment providers, all of this is
available to Web apps as well, but the smooth integration of stores and their
related payment systems make this a lot more attractive for platform-specific
apps, albeit at a 15β30% commission. For apps built using
Trusted Web Activities
and delivered through the Google Play Store, developers can now use the
Payment Request API
and the new
Digital Goods API
to integrate with Google Play Billing.
How big a challenge is this?
When you profit from the convenience of app store billing or in-app purchases,
at the same time you also leave a part of your benefits on the table as a
commission. As a matter of fact, some apps that are published to app
stores even ask their users to make the purchase off-store. One well-known
example is
Netflix with their external subscriptions.
From personal experience through talking to many of Google's partners, a lot of
companies struggle with hiring great Web developers.
The talent shortage is real, and recruiting costs are high, which is why
startups commonly hire in-house recruiters who often approach recruiting with a
breadth-first approach that has not helped the reputation of recruiters with IT
professionals. Also, companies often already employ teams of Android and/or iOS
developers that they cannot just retrain to become Web developers. Creating a
PWA requires a high level of specialization that not all Web developers can
offer.
How big a challenge is this?
In the current economic situation, hiring any kind of developer is
difficult. Hiring someone with Web development skills is, in comparison to other
platform-specific coding skills, still easier
according to StackOverflow surveys,
which (in part) also explains the popularity of app frameworks such as React
Native, Ionic, Flutter, and others that are based on Web technologies.
Existing apps legacy (and migrating the user base) π
It is not unusual for companies to have made massive investments in
platform-specific apps, and giving up these investments, as well as a user base
acquired over time (not to speak of the vanity install statistics), is not easy.
Apparently, starting from scratch, even when a company has an existing website,
appears very unattractive in comparison, but sometimes it does
happen.
How big a challenge is this?
Vanity is vanity, but once you have set up new, potentially more meaningful,
tracking metrics than number of app installs such as
increase of indicators of
purchase intent, you can start tracking those instead.
Web compatibility is still the
main issue
mentioned in developer surveys like Mozilla's, but also in internal surveys that
Google has run. Having to support specific browsers, avoiding or removing a
feature that doesn't work across browsers, or making a design look or work the
same across browsers are frequently brought up as challenges. Projects such as
webcompat.com collect user-submitted browser bugs and
invite interested developers to fix them. Mozilla operates a
repository with
interventions and patches to enable individual sites to run successfully in
Firefox. WebKit maintains a
quirks list
and
hires WebKit Web Compatibility Analysts.
How big a challenge is this?
Compatibility is the top priority for Web developers and browser vendors alike.
With feature testing and progressive enhancement, impressive apps which behave
well on all browsers can be built. For an example of this approach, check out
the article
Progressively enhance your Progressive Web App.
As well as browser compatibility, Mozilla's
2020 developer survey
likewise showed that developers struggle with tools and frameworks. Supporting
multiple frameworks in the same code base, understanding and implementing
security measures, plus outdated or inaccurate documentation for frameworks and
libraries, and keeping up with the large number of new and existing tools or
frameworks were all cited.
How big a challenge is this?
The tooling and framework situation in the Web development world is infamous for
being confusing and hard to keep up with. In practice, though, companies would
use one technology and tooling stack and stay true to it for many years. The
world of tech Twitter is one thing, the reality in businesses, where the
decades-old jQuery is still (and by a large amount) the
most
popular framework, is the other.
Security (or rather, the theater of security with certificate pinning) π
In platform-specific app development, certificate pinning restricts which
certificates are considered valid for a particular app. Instead of allowing any
trusted certificate to be used, developers pin the certificate authority issuer,
public keys, or even end-entity certificates of their choice. Clients connecting
to that server will treat all other certificates as invalid and refuse to make
an HTTPS connection. The hope is that this renders "person-in-the-middle"
attacks impossible, so platform-specific apps are more "secure" than Web apps,
where traffic can easily be sniffed with browser DevTools. There are ways to
circumvent pinned certificates
on all platforms, so it is mostly the theater of security at this point.
How big a challenge is this?
As outlined
earlier,
certificate pinning mostly just increases the effort an attacker has to put into
sniffing your traffic and reverse-engineering the functioning of your app; but
it doesn't make it impossible.
Web applications have seen impressive performance improvements thanks to
advanced technologies such as WebAssembly (including
SIMD),
WebGPU, and general JavaScript engine
progress in recent years. Nonetheless, a carefully developed, platform-specific
app will typically outperform a Web-based application (albeit the situations
where this actually matters may be limited). With even high-performance
audio-editing tools like Soundtrap (thanks to the
Web Audio API and
AudioWorklet),
interactive development environments like
Jupyter Notebook, and graphics-editing tools like
Figma (thanks to WebAssembly), and of course
graphics-intensive games like Quake (thanks to
WebGL and
WebGPU in the future), the boundaries are
being pushed at a rapid rate.
How big a challenge is this?
There are two types of performance problems: those where truly every frame
counts, as in gaming or WebXR experiences, and those where apps feel "janky", or
unreliable. For the latter, new APIs such as the
View Transitions API
can help. For the former, WebGPU is probably the most promising API on the
horizon. Very rarely, but admittedly sometimes, a device may just be too slow to
render a given experience, which clearly happens with native apps, too, where
developers can specify
minimum required device capabilities.
For research question β‘, one possible explanation is
that it is a
Google-backed
toolkit for "building beautiful, natively compiled applications for mobile,
Web, desktop, and embedded devices from a single codebase". If even Google, as
the maker of Android, trusts Flutter enough to build some of its strategic apps
with it, such as
Stadia
(RIP) and Google Ads for both Android and iOS,
and
Assistant apps on
smart display embedded devices, that is quite a signal to send. Also note how
Web and desktop are included in Flutter's output options, which means Flutter is
no longer limited to just mobile (with submission into app stores as the
carrot), and the promise is that it reduces the development cost of apps by the
number of targeted platforms. (Prominent target platform omissions so far are
Apple CarPlay, WearOS, WatchOS, and tvOS.)
An argument that is frequently brought up for Flutter is
hot reloading. On the
backend, Flutter also
plays well with Firebase,
so apps are easy to scale. Important for Web, and as Flutter was initially
criticized for rendering everything inaccessibly onto a <canvas>, the
framework now has
two different Web renderers
it can automatically choose from:
HTML renderer: This renderer uses a combination of HTML elements, CSS,
canvas elements, and SVG elements, and has a smaller download size.
CanvasKit renderer: This renderer is fully consistent with Flutter mobile
and desktop, has faster performance with higher widget density, but adds about
2Β MB in download size.
By default, Flutter selects the HTML renderer when the app is running in a
mobile browser, and the CanvasKit renderer when the app is running in a desktop
browser.
Flutter relies on
a library of pre-made widgets
called Cupertino (for the iOS-native look) and Material (for the Android-native
look) that allow developers to quickly develop a good-looking application with a
shared code base. It is worth noting that Flutter-built user interfaces are
platform-agnostic because Flutterβs Skia rendering engine
does not require any platform-specific UI components. (A downside of this
approach of wrapping everything the app needs instead of reusing platform
primitives directly is app size.)
Apps in Flutter are developed in Dart, an object-oriented programming language
that supports both just-in-time (JIT) and ahead-of-time (AOT) compilation.
Flutter compiles directly to native ARM or Intel x64 code, which has a lot of
performance advantages. Dart is also easy to pick up for developers coming from
any other object-oriented programming language.
Flutterβs documentation is generally recognized as
best in class and its cookbook application
makes getting started with a baseline scaffolding a simple copy and paste job.
The Flutter community is thriving and it's easy to find help if you are stuck.
Dash, the mascot for the Dart language and the Flutter framework.
It is undeniable that amazing apps can be built on the Web. Photoshop, VS Code,
and Twitter are the stand-out examples in this article, but there are many
others. One of the Web's super powers is its linkability, which is hard to beat
on platforms other than the Web. There seems to be a certain tendency for
cross-platform app frameworks to become less attractive to developers, with the
notable exception of Flutter, which allows for Web as one of its target
platforms. Reasons for not building for the Web are easy to find, but it is
also not hard to find counter-arguments to take these reasons apart. Some of
them rely on outdated or weak assumptions, for example, PWAs not being welcome
on app stores, or platform-specific apps being more secure than PWAs. Others are
things that are in process, like closing the app gap by adding missing Web
platform APIs. Some reasons apply equally to both worlds, for example, for
hiring to be a challenge. I could go on, but in the end it all boils down to the
concrete circumstances your use case needs to be built for. In this article, I
have given a number of really strong arguments for building for the Web, while
also not hiding the fact that the Web is a platform that is still not perfect,
and pointing out that other alternatives exist. And as the three stand-out
examples have shown, the decision is also not mutually exclusive. You can build
a powerful Web app, and have a great, platform-specific application at the same
time. It is up to you to decide if you want to. And as I said in the title:
"Not everyone's currently building for the Web, but probably more people
should". In my humble opinion.
If you want to build an app, you have several ways of doing it. You can build a
platform-specific app for the platforms you care about, for example, Windows,
Android, and iOS. In which case you would build three apps. You can also build a
(progressive) Web app, possibly in addition to platform-specific apps.
Alternatively, you can choose a cross-platform framework such as
Electron.js or
Ionic that promises to let you write once and run
anywhere. Let me begin by walking you through three extraordinary examples of
apps whose makers chose to also build for the Web, apart from building
platform-specific apps.
Beacon cases that demonstrate the Web's abilities π
I always saw Photoshop as one of the last bastions of high quality apps that
supposedly would never make it to the Web platform. Forget thatβthis last
bastion has finally fallen. With Photoshop,
Adobe, together with Chromium engineering, has managed to get a beta version of
Photoshop running in the browser that can serve as the new beacon showcase of
what is possible on the Web. In it, you can try out the commenting workflow and
test some early Photoshop editing features Adobe is piloting on the Web. You and
your collaborators can now open and view Photoshop cloud documents in the
browser, provide feedback, and make basic edits. All in one place without having
to download or launch the app.
Similarly, Microsoft has launched
Visual Studio Code on the Web,
a fully fledged, installable Web experience of its integrated development
environment (IDE) that makes developing completely in the browser possible,
including the option to open and edit files on the local file system.
Lastly Twitterβwhose progressive Web app (PWA) is
largely seen
as probably the best mainstream Progressive Web Appβhas
used
its responsive Web codebase for all platforms, mobile and desktop, via Web
browsers. On Windows, the PWA is the experience the company is confident enough
to make the Twitter experience that you get when you
install
the app from the Microsoft Store.
Twitter in the Microsoft Store
Linkability and universality: the Web's super powers π
All three companies, Adobe, Microsoft, and Twitter, in parallel with their Web
apps, have well-established, platform-specific Windows, macOS, Android, iOS, and
Linux versions of their apps Photoshop, Visual Studio Code, and Twitter
respectively. So why did they build for the Web on top? The answer lies in its
linkability and universality.
As Google's Thomas Nattestad
put it:
"The simple power of a URL is that anyone can click it and instantly access it.
All you need is a browser. There is no need to install an application or worry
about what operating system you are running on".
According to
Microsoft's Chris Dias, with Visual Studio Code
for the Web, when working with GitHub "you can make quick edits, review PRs,
and continue on to a local clone". The sole fact that you can share a link to
your work unlocks collaboration patterns that users have embraced and loved
since the birth of apps such as Google Docs. Twitter, of course, lives and dies
by its links. News sites regularly
link to newsworthy tweets,
which means "keeping it quick"is core
to ensuring people can get from an article straight into the app, where they can
read or engage with the linked tweet.
Web applications are inherently universal. They run on whatever operating system
is capable of running a Web browser and they do not need to be compiled for each
operating system separately. The same code base powers the application on all
platforms. This does not mean that there are no compatibility issuesβthere are
plenty actuallyβbut there is a
solid, shared, increasing baseline that all
applications can build upon.
While more ubiquitous on mobile, linking into a platform-specific app from the
Web on desktop is comparatively rare. On mobile (and macOS), this works via a
technology called
Universal Links on iOS (and
on macOS), and App Links on
Android. Platform-specific apps alternatively can rely on
registered protocol schemes
such as itms-apps: for when you want to deep-link into the App Store app on
macOS or iOS, or register your own custom schemes for your own apps. So while
technically possible, linking into platform-specific apps is a lot less flexible
and requires more plumbing work than simply linking into a Web app.
The slow decline of interest in cross-platform app frameworks and the rise of Flutter π
The Web isn't the only platform that promises "write once, run anywhere".
Cross-platform frameworks Γ la Electron.js do, too. With the Web becoming
powerful enough to drive apps such as Photoshop that were thought to be
impossible, we can, however, observe a slow decline of interest in
cross-platform desktop app frameworks such as
Electron.js and NW.js, and
mobile app frameworks such as Cordova or
React Native; while at the same time there is an
undeniable increase of interest in Flutter.
The following
Google Trends chart
shows the five frameworks side by side. While noting that this chart does show
disambiguated topic trends as detected by Google (as opposed to ambiguous
search term trends),
nevertheless it is clearly not an exact science.
Google Trends interest over time for Electron, NW.js, Apache Cordova, Flutter, and React Native.
[Source]
StackOverflow statistics
on tag usage also support this. The underlying assumption of people actually
using a technology correlating with people asking questions about that
technology on StackOverflow is not beyond the realms of possibility.
Shouldn't everybody be building for the Web, then? π
Given the examples of Photoshop, VS Code, and Twitter, that show that it is
indeed possible to build amazing applications on the Web, and given the Web's
super powers of linkability and universality, two research questions come up:
Web applications still lack certain functionalities that platform-specific apps
have. In the following paragraph, I list representative examples of such
functionalities on different platforms.
First, it is impossible, even with an installed PWA, to obey the macOS user
interface paradigm of having the
app menu at the top of the screen.
It can easily be achieved with frameworks such as Electron.js via the
Menu class. (On
the Web, the next best thing is
Window Controls Overlay; getting
support for app menus is tracked as crbug/1295253.)
Another example is in-app purchases on macOS that can be handled via Electron's
inAppPurchase()
method. (On the Web, the next best thing is the
Digital Goods API,
currently limited to Android and ChromeOS.) Installers are a common way users
have learned to install applications on Windows. With Electron.js, it is
possible to create
installers
and make installed applications
update automatically.
(On the Web, Web Bundles are the next best
alternative in Chrome.) This list is not exhaustive, and Electron.js is
mentioned as a representative apps framework out of several.
How big a challenge is this?
There are undeniably a number of capabilities that are missing from the Web. In
many cases, they are "nice-to-have", but not necessarily required for a still
great experience. Carefully assess if a capability can be seen as a progressive
enhancement. For an example of this approach, check out the article
Progressively enhance your Progressive Web App.
Collectively, we have educated users to look for apps in app stores. Some stores
such as the
Windows Store and
the
Android Play Store
have started to embrace (wrapped!) PWAs (optionally
limited to ChromeOS),
and offer graphical user interface tools like
PWABuilder (internally based on the command line
tool bubblewrap) for
submitting applications. Meanwhile, on other stores such as Apple's App Store,
the situation is different and less welcoming, and apps
may or may not
make it into the App Store, depending on the outcome of the app review.
Recently, Oculus, a division of Meta Platforms that produces virtual reality
headsets, has announced that PWAs would be accepted into the
Oculus Store.
How big a challenge is this?
If your users are on one of the platforms whose stores accept PWAs, you can
publish your app to the stores in question. Remember linkability as one of the
Web's super powers. Your app is discoverable, advertisable, and linkable from
the Web, too. Investing in a memorable domain name can sometimes actually be
better for discoverability. Even for app stores, people still rely most on
recommendations from friends and family members to discover new apps according
to
research done by Google.
Apart from making apps themselves available for a fee, apps can also be
monetized by selling items as in-app purchases (for example, items in a game
app), or by selling subscriptions (for example, regular courses in a fitness
app). If the developer integrates with payment providers, all of this is
available to Web apps as well, but the smooth integration of stores and their
related payment systems make this a lot more attractive for platform-specific
apps, albeit at a 15β30% commission. For apps built using
Trusted Web Activities
and delivered through the Google Play Store, developers can now use the
Payment Request API
and the new
Digital Goods API
to integrate with Google Play Billing.
How big a challenge is this?
When you profit from the convenience of app store billing or in-app purchases,
at the same time you also leave a part of your benefits on the table as a
commission. As a matter of fact, some apps that are published to app
stores even ask their users to make the purchase off-store. One well-known
example is
Netflix with their external subscriptions.
From personal experience through talking to many of Google's partners, a lot of
companies struggle with hiring great Web developers.
The talent shortage is real, and recruiting costs are high, which is why
startups commonly hire in-house recruiters who often approach recruiting with a
breadth-first approach that has not helped the reputation of recruiters with IT
professionals. Also, companies often already employ teams of Android and/or iOS
developers that they cannot just retrain to become Web developers. Creating a
PWA requires a high level of specialization that not all Web developers can
offer.
How big a challenge is this?
In the current economic situation, hiring any kind of developer is
difficult. Hiring someone with Web development skills is, in comparison to other
platform-specific coding skills, still easier
according to StackOverflow surveys,
which (in part) also explains the popularity of app frameworks such as React
Native, Ionic, Flutter, and others that are based on Web technologies.
Existing apps legacy (and migrating the user base) π
It is not unusual for companies to have made massive investments in
platform-specific apps, and giving up these investments, as well as a user base
acquired over time (not to speak of the vanity install statistics), is not easy.
Apparently, starting from scratch, even when a company has an existing website,
appears very unattractive in comparison, but sometimes it does
happen.
How big a challenge is this?
Vanity is vanity, but once you have set up new, potentially more meaningful,
tracking metrics than number of app installs such as
increase of indicators of
purchase intent, you can start tracking those instead.
Web compatibility is still the
main issue
mentioned in developer surveys like Mozilla's, but also in internal surveys that
Google has run. Having to support specific browsers, avoiding or removing a
feature that doesn't work across browsers, or making a design look or work the
same across browsers are frequently brought up as challenges. Projects such as
webcompat.com collect user-submitted browser bugs and
invite interested developers to fix them. Mozilla operates a
repository with
interventions and patches to enable individual sites to run successfully in
Firefox. WebKit maintains a
quirks list
and
hires WebKit Web Compatibility Analysts.
How big a challenge is this?
Compatibility is the top priority for Web developers and browser vendors alike.
With feature testing and progressive enhancement, impressive apps which behave
well on all browsers can be built. For an example of this approach, check out
the article
Progressively enhance your Progressive Web App.
As well as browser compatibility, Mozilla's
2020 developer survey
likewise showed that developers struggle with tools and frameworks. Supporting
multiple frameworks in the same code base, understanding and implementing
security measures, plus outdated or inaccurate documentation for frameworks and
libraries, and keeping up with the large number of new and existing tools or
frameworks were all cited.
How big a challenge is this?
The tooling and framework situation in the Web development world is infamous for
being confusing and hard to keep up with. In practice, though, companies would
use one technology and tooling stack and stay true to it for many years. The
world of tech Twitter is one thing, the reality in businesses, where the
decades-old jQuery is still (and by a large amount) the
most
popular framework, is the other.
Security (or rather, the theater of security with certificate pinning) π
In platform-specific app development, certificate pinning restricts which
certificates are considered valid for a particular app. Instead of allowing any
trusted certificate to be used, developers pin the certificate authority issuer,
public keys, or even end-entity certificates of their choice. Clients connecting
to that server will treat all other certificates as invalid and refuse to make
an HTTPS connection. The hope is that this renders "person-in-the-middle"
attacks impossible, so platform-specific apps are more "secure" than Web apps,
where traffic can easily be sniffed with browser DevTools. There are ways to
circumvent pinned certificates
on all platforms, so it is mostly the theater of security at this point.
How big a challenge is this?
As outlined
earlier,
certificate pinning mostly just increases the effort an attacker has to put into
sniffing your traffic and reverse-engineering the functioning of your app; but
it doesn't make it impossible.
Web applications have seen impressive performance improvements thanks to
advanced technologies such as WebAssembly (including
SIMD),
WebGPU, and general JavaScript engine
progress in recent years. Nonetheless, a carefully developed, platform-specific
app will typically outperform a Web-based application (albeit the situations
where this actually matters may be limited). With even high-performance
audio-editing tools like Soundtrap (thanks to the
Web Audio API and
AudioWorklet),
interactive development environments like
Jupyter Notebook, and graphics-editing tools like
Figma (thanks to WebAssembly), and of course
graphics-intensive games like Quake (thanks to
WebGL and
WebGPU in the future), the boundaries are
being pushed at a rapid rate.
How big a challenge is this?
There are two types of performance problems: those where truly every frame
counts, as in gaming or WebXR experiences, and those where apps feel "janky", or
unreliable. For the latter, new APIs such as the
View Transitions API
can help. For the former, WebGPU is probably the most promising API on the
horizon. Very rarely, but admittedly sometimes, a device may just be too slow to
render a given experience, which clearly happens with native apps, too, where
developers can specify
minimum required device capabilities.
For research question β‘, one possible explanation is
that it is a
Google-backed
toolkit for "building beautiful, natively compiled applications for mobile,
Web, desktop, and embedded devices from a single codebase". If even Google, as
the maker of Android, trusts Flutter enough to build some of its strategic apps
with it, such as
Stadia
(RIP) and Google Ads for both Android and iOS,
and
Assistant apps on
smart display embedded devices, that is quite a signal to send. Also note how
Web and desktop are included in Flutter's output options, which means Flutter is
no longer limited to just mobile (with submission into app stores as the
carrot), and the promise is that it reduces the development cost of apps by the
number of targeted platforms. (Prominent target platform omissions so far are
Apple CarPlay, WearOS, WatchOS, and tvOS.)
An argument that is frequently brought up for Flutter is
hot reloading. On the
backend, Flutter also
plays well with Firebase,
so apps are easy to scale. Important for Web, and as Flutter was initially
criticized for rendering everything inaccessibly onto a <canvas>, the
framework now has
two different Web renderers
it can automatically choose from:
HTML renderer: This renderer uses a combination of HTML elements, CSS,
canvas elements, and SVG elements, and has a smaller download size.
CanvasKit renderer: This renderer is fully consistent with Flutter mobile
and desktop, has faster performance with higher widget density, but adds about
2Β MB in download size.
By default, Flutter selects the HTML renderer when the app is running in a
mobile browser, and the CanvasKit renderer when the app is running in a desktop
browser.
Flutter relies on
a library of pre-made widgets
called Cupertino (for the iOS-native look) and Material (for the Android-native
look) that allow developers to quickly develop a good-looking application with a
shared code base. It is worth noting that Flutter-built user interfaces are
platform-agnostic because Flutterβs Skia rendering engine
does not require any platform-specific UI components. (A downside of this
approach of wrapping everything the app needs instead of reusing platform
primitives directly is app size.)
Apps in Flutter are developed in Dart, an object-oriented programming language
that supports both just-in-time (JIT) and ahead-of-time (AOT) compilation.
Flutter compiles directly to native ARM or Intel x64 code, which has a lot of
performance advantages. Dart is also easy to pick up for developers coming from
any other object-oriented programming language.
Flutterβs documentation is generally recognized as
best in class and its cookbook application
makes getting started with a baseline scaffolding a simple copy and paste job.
The Flutter community is thriving and it's easy to find help if you are stuck.
Dash, the mascot for the Dart language and the Flutter framework.
It is undeniable that amazing apps can be built on the Web. Photoshop, VS Code,
and Twitter are the stand-out examples in this article, but there are many
others. One of the Web's super powers is its linkability, which is hard to beat
on platforms other than the Web. There seems to be a certain tendency for
cross-platform app frameworks to become less attractive to developers, with the
notable exception of Flutter, which allows for Web as one of its target
platforms. Reasons for not building for the Web are easy to find, but it is
also not hard to find counter-arguments to take these reasons apart. Some of
them rely on outdated or weak assumptions, for example, PWAs not being welcome
on app stores, or platform-specific apps being more secure than PWAs. Others are
things that are in process, like closing the app gap by adding missing Web
platform APIs. Some reasons apply equally to both worlds, for example, for
hiring to be a challenge. I could go on, but in the end it all boils down to the
concrete circumstances your use case needs to be built for. In this article, I
have given a number of really strong arguments for building for the Web, while
also not hiding the fact that the Web is a platform that is still not perfect,
and pointing out that other alternatives exist. And as the three stand-out
examples have shown, the decision is also not mutually exclusive. You can build
a powerful Web app, and have a great, platform-specific application at the same
time. It is up to you to decide if you want to. And as I said in the title:
"Not everyone's currently building for the Web, but probably more people
should". In my humble opinion.