Blogccasion
A look inside the think tank
2024-02-28T10:30:53Z
https://blog.tomayac.com/
Thomas Steiner
steiner.thomas@gmail.com
So, what exactly did Apple break in the EU?
2024-02-28T10:30:53Z
https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/
<h2 id="disclaimer-just-in-case" tabindex="-1">Disclaimer, just in caseβ¦ <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#disclaimer-just-in-case" aria-hidden="true">π</a></h2>
<p>I work for Google on the Chrome Developer Relations team. But for this post, I
want to make it super duper clear that I'm speaking <em>not</em> on behalf of my
employer and that all views and opinions expressed in this blog post are purely
<em>my own</em>: Thomas Steiner's, the guy commonly known for his avatar with a green
hat, but today in my pajamas having my second morning coffee. Oh, thanks for
asking, the two cats are Lluna (yes, with double 'l', it means moon in Catalan)
Norris, looking at the camera, and Skinny Norris, looking out of the window.</p>
<p><img src="https://blog.tomayac.com/images/thomas-cats.jpg" alt="Thomas Steiner with two cats sat on a coffee machine in the background." /></p>
<h2 id="how-i-noticed" tabindex="-1">How I noticed <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#how-i-noticed" aria-hidden="true">π</a></h2>
<p>With this out of the way, it's time to dive in and answer the question of what
exactly did Apple break in the EU? I'm physically located in the European Union
and my iPhone has a German SIM card. On January 30, 2024, I sent the following
<a href="https://toot.cafe/@tomayac/111845185332124491">toot</a> with attached screenshot
(cropped here):</p>
<blockquote>
<p>Hope this is a bug in the beta, but opening previously installed Home Screen
Web apps on iOS 17.4 (21E5184i) results in a prompt:</p>
<p>Open "Example app" in Safari. "Example app" will open in your default browser
from now on.</p>
<p>Newly installed apps always open in the browser. There doesn't appear to be a
standalone mode anymore.</p>
<p>Reported as FB13567834.</p>
</blockquote>
<p><img src="https://blog.tomayac.com/images/open-in-default-browser.jpg" alt="Prompt with the text Open "Example app" in Safari. "Example app" will open in your default browser from now on." /></p>
<p>The toot that all the news outlets cited was the
<a href="https://mastodon.social/@mysk/111857830238574891">one from Mysk</a> from February
1, 2024, that said:</p>
<blockquote>
<p>π¬ Finally, iOS treats all browsers equally when it comes to PWAs. Previously,
only Safari was able to install and run PWA apps. With iOS 17.4 beta in the
EU, no browser can install PWA apps, even Safari. It seems PWAs have been
disabled entirely.</p>
<p>Oh yes, when you set a third-party browser as the default browser and then you
delete it, iOS sets Safari as the default browser. Watch this:</p>
<p>#iOS #Apple #DMA #EU #maliciouscompliance</p>
<p><a href="https://youtu.be/AST12aDGf0Q">youtu.be/AST12aDGf0Q</a></p>
</blockquote>
<p>Then, on February 2, 2024, <a href="https://tixie.name/">Tixie</a> opened a
<a href="https://bugs.webkit.org/show_bug.cgi?id=268643">WebKit bug</a> titled <em>"Bug
268643 - [iOS 17.4 Beta (21E5184k)] REGRESSION: PWA added to Home Screen are
forced to open in Safari."</em></p>
<p><strong>π Update:</strong> The message in the release candidate of iOS 17.4 (21E217) is now:
<em>"Open 'Example app' in 'Default browser'? In your region, web apps now open in
your default browser".</em></p>
<h2 id="what-does-apple-say" tabindex="-1">What does Apple say? <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#what-does-apple-say" aria-hidden="true">π</a></h2>
<p>By now, you have probably heard that
<a href="https://developer.apple.com/support/dma-and-apps-in-the-eu#8">users in the EU don't have access to Home Screen web apps</a>
anymore. Here is Apple's statement in its full glorious detail:</p>
<blockquote>
<p>To comply with the Digital Markets Act, Apple has done an enormous amount of
engineering work to add new functionality and capabilities for developers and
users in the European Union β including more than 600 new APIs and a wide
range of developer tools.</p>
<p>The iOS system has traditionally provided support for Home Screen web apps by
building directly on WebKit and its security architecture. That integration
means Home Screen web apps are managed to align with the security and privacy
model for native apps on iOS, including isolation of storage and enforcement
of system prompts to access privacy impacting capabilities on a per-site
basis.</p>
<p>Without this type of isolation and enforcement, malicious web apps could read
data from other web apps and recapture their permissions to gain access to a
user's camera, microphone or location without a user's consent. Browsers also
could install web apps on the system without a user's awareness and consent.
Addressing the complex security and privacy concerns associated with web apps
using alternative browser engines would require building an entirely new
integration architecture that does not currently exist in iOS and was not
practical to undertake given the other demands of the DMA and the very low
user adoption of Home Screen web apps. And so, to comply with the DMA's
requirements, we had to remove the Home Screen web apps feature in the EU.</p>
<p>EU users will be able to continue accessing websites directly from their Home
Screen through a bookmark with minimal impact to their functionality. We
expect this change to affect a small number of users. Still, we regret any
impact this change β that was made as part of the work to comply with the DMA
β may have on developers of Home Screen web apps and our users.</p>
</blockquote>
<h2 id="these-changes-are-ios-only" tabindex="-1">These changes are iOS only! <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#these-changes-are-ios-only" aria-hidden="true">π</a></h2>
<p>The first important thing to note here is that this statement exclusively
applies to iOS, but not iPadOS and not macOS. This works because Apple managed
to convince the EU Commission that iPadOS and macOS are distinct core platform
services. The
<a href="https://ec.europa.eu/competition/digital_markets_act/cases/202344/DMA_100013_215.pdf#page=21">relevant section of the DMA</a>
says:</p>
<blockquote>
<p>Moreover, the Commission considers, in line with Apple's view, that iOS,
iPadOS, macOS, watchOS, and tvOS constitute distinct CPSs [core platform > >
services] within the meaning of Article 2, point (2), sub (f), of Regulation
(EU) 2022/1925.</p>
</blockquote>
<p>This means on iPadOS and macOS, everything will stay the same. You can still add
Web apps to the Home Screen on iPadOS or the Dock on macOS, and they will open
in standalone mode as they always did.</p>
<p><strong>π‘ Note:</strong> This article exclusively talks about Home Screen Web Apps, not
bookmarks. According to
<a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/#:~:text=Web%20developers%20have,any%20other%20browser.">Apple's documentation</a>,
<em>"Web developers have the option to create a
<a href="https://developer.mozilla.org/en-US/docs/Web/Manifest">manifest file</a> (with its
<a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/display"><code>display</code></a>
member set to <code>standalone</code> or <code>fullscreen</code>) and serve it along with their
website. If they do, that site becomes a Home Screen web app. Then, when you tap
on its icon, the web app opens like any other app on iOS or iPadOS instead of
opening in a browser. You can see its app preview in the
<a href="https://support.apple.com/en-us/HT202070">App Switcher</a>, separate from Safari
or any other browser."</em></p>
<h2 id="what-happens-on-ios" tabindex="-1">What happens on iOS? <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#what-happens-on-ios" aria-hidden="true">π</a></h2>
<p>Looking now at iOS. Ifβ¦</p>
<ol>
<li>you have an iPhone that runs (betas of) iOS 17.4 or later, and iff (if and
only if)β¦</li>
<li>you are detected as being in the European Union (EU), you can still add apps
to the Home Screen, but they will open in a regular new browser tab in your
<a href="https://support.apple.com/en-us/104975">default browser</a>.</li>
</ol>
<p>How exactly Apple detects if you're in the EU isn't clear yet. It seems not to
be based on the SIM operator, as some users claim they are affected even on
SIM-less iPhones. Possibly IP geolocation as it doesn't require location access?
Or maybe GPS for improved accuracy based on a system-level access grant? What
about travelers in the EU from non-EU countries? I hope we will find out
eventually. People
<a href="https://www.reddit.com/r/iOSBeta/comments/19fgmcs/ios_174_db1_region_identifier_in_about_page/">started noticing</a>
an <code>IDENTIFIABLE_REGION</code> string in iOS 17.4 beta 1 (21E5184i) as early as
January 25, 2024, but it was removed in the next beta.</p>
<p><strong>π‘ Note:</strong> Since iOS 16.4, apart from Safari, alternative browsers, too, have
the ability to add apps to the Home Screen. Based on
<a href="https://developer.apple.com/documentation/webkit/wkwebview#4143030">Apple's instructions</a>,
<em>"if your app has the
<a href="https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_web-browser"><code>com.apple.developer.web-browser</code></a>
entitlement, the iOS share sheet can offer Add to Home Screen for an <code>http</code> or
<code>https</code> webpage, creating a convenient link to a web app or bookmark. To allow
someone to add the current webpage to the Home Screen, include the <code>WKWebView</code>
instance in the <code>activityItems</code> array when you call
<a href="https://developer.apple.com/documentation/uikit/uiactivityviewcontroller/1622019-init"><code>init(activityItems:applicationActivities:)</code></a>
to create the <code>UIActivityViewController</code>."</em></p>
<p>There are different scenarios listed in the following.</p>
<h3 id="you-previously-added-an-app-to-the-home-screen-with-safari" tabindex="-1">You previously added an app to the Home Screen with Safari <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#you-previously-added-an-app-to-the-home-screen-with-safari" aria-hidden="true">π</a></h3>
<p>In this case, the app will open in a regular new browser tab in your current
default browser. It doesn't matter if Safari was your default browser when you
added the app to the Home Screen, it will still open in your current default
browser.</p>
<h3 id="you-previously-added-an-app-to-the-home-screen-with-an-alternative-browser-that-has-the-com-apple-developer-web-browser-entitlement" tabindex="-1">You previously added an app to the Home Screen with an alternative browser that has the <code>com.apple.developer.web-browser</code> entitlement <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#you-previously-added-an-app-to-the-home-screen-with-an-alternative-browser-that-has-the-com-apple-developer-web-browser-entitlement" aria-hidden="true">π</a></h3>
<p>In this case, the app will open in a regular new browser tab in your current
default browser. It doesn't matter if the alternative browser was your default
browser when you added the app to the Home Screen, it will still open in your
current default browser.</p>
<h3 id="you-newly-add-an-app-to-the-home-screen-with-safari" tabindex="-1">You newly add an app to the Home Screen with Safari <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#you-newly-add-an-app-to-the-home-screen-with-safari" aria-hidden="true">π</a></h3>
<p>In this case, the app will open in a regular new browser tab in your current
default browser. It doesn't matter if Safari was your default browser when you
added the app to the Home Screen, it will still open in your current default
browser.</p>
<h3 id="you-newly-add-an-app-to-the-home-screen-with-an-alternative-browser-that-has-the-com-apple-developer-web-browser-entitlement" tabindex="-1">You newly add an app to the Home Screen with an alternative browser that has the <code>com.apple.developer.web-browser</code> entitlement <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#you-newly-add-an-app-to-the-home-screen-with-an-alternative-browser-that-has-the-com-apple-developer-web-browser-entitlement" aria-hidden="true">π</a></h3>
<p>In this case, the app will open in a regular new browser tab in your current
default browser. It doesn't matter if the alternative browser was your default
browser when you added the app to the Home Screen, it will still open in your
current default browser.</p>
<h2 id="what-breaks" tabindex="-1">What breaks? <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#what-breaks" aria-hidden="true">π</a></h2>
<p>As you see, all the cases mentioned above lead to the same result, a new tab in
your current default browser. While simple to understand, there are a number of
things that now break.</p>
<h3 id="push-api" tabindex="-1">Push API <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#push-api" aria-hidden="true">π</a></h3>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API">Push API</a> was
described in the article
<a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/">Web Push for Web Apps on iOS and iPadOS</a>
published on February 16, 2023. It's important to note the caveat: <em>"A web app
that has been added to the Home Screen can request permission to receive push
notifications as long as that request is in response to direct user interaction
β such as tapping on a 'subscribe' button provided by the web app."</em> Since Home
Screen web apps are no longer available in the EU, the Push API is effectively
broken for EU users.</p>
<h3 id="badging-api" tabindex="-1">Badging API <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#badging-api" aria-hidden="true">π</a></h3>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/Badging_API">Badging API</a>
was described in the article
<a href="https://webkit.org/blog/14112/badging-for-home-screen-web-apps/">Badging for Home Screen Web Apps</a>
published on April 25, 2023. The important caveat here is: <em>"The user must grant
the app permission to display notifications before the badge will appear."</em>
Since the Push API is no longer exposed, the Badging API breaks as collateral
damage.</p>
<h3 id="standalone-mode" tabindex="-1">Standalone mode <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#standalone-mode" aria-hidden="true">π</a></h3>
<p>Running in standalone mode allows Web apps to look and feel like native apps
without any browser UI. This was particularly useful for game streaming services
like <a href="https://www.nvidia.com/en-us/geforce-now/">NVIDIA GeForce Now</a> or
<a href="https://www.xbox.com/en-us/play">XBox Cloud Gaming</a>, but also just any other
app that wants to make best use of the limited screen real estate. Even manually
entering fullscreen mode isn't possible anymore, as Safari 17.4
<a href="https://developer.apple.com/documentation/safari-release-notes/safari-17_4-release-notes#:~:text=Fixed%20multiple%20issues%20by%20disabling%20support%20for%20the%20Fullscreen%20API%20on%20iOS."><em>"[f]ixed multiple issues by disabling support for the Fullscreen API on iOS."</em></a></p>
<h3 id="stored-data" tabindex="-1">Stored data <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#stored-data" aria-hidden="true">π</a></h3>
<p>Home Screen Web apps ran in a different isolated context than regular in-tab Web
apps. This means that if you were logged in to a Web app from the Home Screen,
you need to log in again in the browser tab, and all previously stored data is
gone. This includes any data stored in:</p>
<ul>
<li>IndexedDB</li>
<li>LocalStorage</li>
<li>Media keys</li>
<li>SessionStorage</li>
<li>Service Worker registrations and cache</li>
<li>Origin private file system</li>
</ul>
<h3 id="exclusion-from-storage-eviction" tabindex="-1">Exclusion from storage eviction <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#exclusion-from-storage-eviction" aria-hidden="true">π</a></h3>
<p>Home Screen Web apps were exempt from Safari's
<a href="https://webkit.org/tracking-prevention/#:~:text=to%2024%20hours.-,7%2DDay%20Cap%20on%20All%20Script%2DWriteable%20Storage,-Trackers%20executing%20script">7-Day Cap on All Script-Writeable Storage</a>,
but now they aren't anymore. Unless you use a Web app regularly enough, its data
will be evicted from storage. This also
<a href="https://webkit.org/blog/10882/app-bound-domains/#:~:text=Intelligent%20Tracking%20Prevention%20in%20WKWebView">applies to <code>WKWebView</code>-based browsers</a>
that have the <code>com.apple.developer.web-browser</code> entitlement:</p>
<blockquote>
<p>Additionally in iOS 14.0 and macOS Big Sur, Intelligent Tracking Prevention
(ITP), is enabled by default in all <code>WKWebView</code> applications.</p>
<p>[β¦]</p>
<p>Note that applications taking the new Default Web Browser entitlement always
have a user control in Settings to disable ITP[.]</p>
</blockquote>
<h3 id="multiple-installs-of-the-same-web-app" tabindex="-1">Multiple installs of the same Web app <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#multiple-installs-of-the-same-web-app" aria-hidden="true">π</a></h3>
<p>iOS has supported multiple installs of the same Web app since the very
beginning. Apple
<a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/#:~:text=When%20adding%20a,others%20as%20well.">highlighted</a>
the ability for people to install any Web app more than once on their device,
which can indeed be useful:</p>
<blockquote>
<p>When adding a web app to the Home Screen, users are given the opportunity to
change the app's name. iOS and iPadOS 16.4 combine this name with the Manifest
ID to uniquely identify the web app. That way, a user can install multiple
copies of the web app on one device and give them different identities. For
example, notifications from "Shiny (personal)" can be silenced by Focus while
notifications from "Shiny (work)" can be allowed. If the user gives their
favorite website the same name on multiple devices, Focus settings on one
device will sync and apply to the others as well.</p>
</blockquote>
<p>Technically, this still works and people can add apps more than once, but
because the apps now open in the same browser context, the multiple installs
people used, for example, to sign in to different accounts, are now effectively
useless.</p>
<h2 id="what-now" tabindex="-1">What now? <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#what-now" aria-hidden="true">π</a></h2>
<p>The DMA opened the door for browser vendors to ship their own engines on iOS.
This would mean that push notifications, app icon badges, storage management,
storage eviction, and fullscreen/standalone mode could be decoupled from the
previous model of creating a browser shell that until now needed to embed a
<code>WKWebView</code> and at best could inject JavaScript to expose APIs that <code>WKWebView</code>
didn't support natively to Web apps. The process of
<a href="https://developer.apple.com/support/alternative-browser-engines/">Using alternative browser engines in the European Union</a>
is going to be maximally painful, as
<a href="https://infrequently.org/2024/02/home-screen-advantage/">Alex Russell points out</a>
and as
<a href="https://www.theverge.com/2024/1/26/24052067/mozilla-apple-ios-browser-rules-firefox">Mozilla has gone on the record</a>
to say.</p>
<p>According to the
<a href="https://www.ft.com/content/d2f7328c-5851-4f16-8f8d-93f0098b6adc">Financial Times</a>
and
<a href="https://www.theverge.com/2024/2/26/24083511/apple-eu-investigation-web-app-support">The Verge</a>,
the European Commission is on the case. This is what spokesperson
<a href="https://commission.europa.eu/persons/lea-zuber_en">Lea Zuber</a> shared with both
publications:</p>
<blockquote>
<p>We are indeed looking at the compliance packages of all gatekeepers, including
Apple.</p>
<p>In that context, we're in particular looking into the issue of progressive web
apps, and can confirm sending the requests for information to Apple and to app
developers, who can provide useful information for our assessment.</p>
</blockquote>
<h2 id="an-open-letter-to-tim-cook" tabindex="-1">An open letter to Tim Cook <a class="direct-link" href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/#an-open-letter-to-tim-cook" aria-hidden="true">π</a></h2>
<p>The good folks from <a href="https://open-web-advocacy.org/">Open Web Advocacy</a> have
written an open letter addressed at Tim Cook in which they outline why
<a href="https://letter.open-web-advocacy.org/">Sabotaging Web Apps Is Indefensible</a>. As
an immediate action, I would very much encourage you to go
<a href="https://letter.open-web-advocacy.org/#:~:text=Sign%20the%20Open%20Letter">ποΈ sign it</a>.
I did. And now back to my third morning coffee and my cats.</p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2024%2F02%2F28%2Fso-what-exactly-did-apple-break-in-the-eu%2F&dp=%2F2024%2F02%2F28%2Fso-what-exactly-did-apple-break-in-the-eu%2F&dt=So%2C%20what%20exactly%20did%20Apple%20break%20in%20the%20EU%3F" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/">https://blog.tomayac.com/2024/02/28/so-what-exactly-did-apple-break-in-the-eu/</a>.
</p>
Lenovo ThinkVision P27h-20 screen randomly turns off when connected to MacBook Pro
2024-02-21T09:13:56Z
https://blog.tomayac.com/2024/02/lenovo-p27h-20-randomly-turns-off/
<p>The
<a href="https://www.lenovo.com/us/en/p/accessories-and-software/monitors/professional/61e9gar6us?orgRef=https%253A%252F%252Fwww.google.com%252F">Lenovo ThinkVision P27h-20</a>
screen I get from work is a decent 27 inch screen. Coming from the Retina screen
of my laptop that
<a href="https://blog.tomayac.com/2020/03/23/my-working-from-home-setup-during-covid-19/">I worked on for a long time</a>,
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β¦</p>
<p>My biggest gripe with the screen was that it just <strong>randomly turned off</strong> when
connected to my MacBook Pro in clamshell mode. I finally found the culprit after
combing through the
<a href="https://support.apple.com/guide/console/welcome/mac">Console</a> system logs for
<em>any</em> trace for the longest time. I found out that the MacBook Pro thought the
power was changing from grid to battery and <em>vice versa</em> (all while being
constantly on-power), and whenever it did that, the screen would turn off.</p>
<p>The solution was to disable the "Smart Power" option in the screen's settings.
According to the
<a href="https://psref.lenovo.com/syspool/Sys/PDF/datasheet/ThinkVision%20P27h-20_datasheet_EN.PDF">manual</a>,
the "Smart Power" option does the following:</p>
<blockquote>
<p>Smart Power intelligently distributes power to connected USB and USB Type-C
devices, maximizing power supply efficiency while also reducing overall
consumption.</p>
</blockquote>
<p>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.</p>
<p><img src="https://blog.tomayac.com/images/lenovo-p27h-20.jpg" alt="Lenovo ThinkVision P27h-20 settings with the Smart Power option circled." /></p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2024%2F02%2Flenovo-p27h-20-randomly-turns-off%2F&dp=%2F2024%2F02%2Flenovo-p27h-20-randomly-turns-off%2F&dt=Lenovo%20ThinkVision%20P27h-20%20screen%20randomly%20turns%20off%20when%20connected%20to%20MacBook%20Pro" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2024/02/lenovo-p27h-20-randomly-turns-off/">https://blog.tomayac.com/2024/02/lenovo-p27h-20-randomly-turns-off/</a>.
</p>
Wasm meetup Munich: A Wasm New Year! trip report
2024-01-17T11:04:26Z
https://blog.tomayac.com/2024/01/17/a-wasm-new-year/
<h2 id="background" tabindex="-1">Background <a class="direct-link" href="https://blog.tomayac.com/2024/01/17/a-wasm-new-year/#background" aria-hidden="true">π</a></h2>
<p>The WebAssembly meetup in Munich has a history that
<a href="https://www.meetup.com/en-US/webassembly/events/?type=past">reaches back to 2018</a>.
After a long Covid-related hiatus and a lack of organizers to pick up the ball
again, <em>A Wasm New Year!</em> 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.</p>
<p><img src="https://blog.tomayac.com/images/a-wasm-new-year.png" alt="image" /></p>
<h2 id="talks" tabindex="-1">Talks <a class="direct-link" href="https://blog.tomayac.com/2024/01/17/a-wasm-new-year/#talks" aria-hidden="true">π</a></h2>
<h3 id="compiling-to-and-optimizing-wasm-with-binaryen" tabindex="-1">Compiling to and Optimizing Wasm with Binaryen <a class="direct-link" href="https://blog.tomayac.com/2024/01/17/a-wasm-new-year/#compiling-to-and-optimizing-wasm-with-binaryen" aria-hidden="true">π</a></h3>
<p><strong>Speaker:</strong> Thomas Steiner</p>
<p>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
<code>wasm-opt</code> and <code>wasm-merge</code>.</p>
<p><strong>Resources:</strong></p>
<ul>
<li><a href="https://docs.google.com/presentation/d/1W7CQK8E8iV0fkTBeJWOTysd-KzOLLGKaTVJWy4dZH6g/edit?usp=drivesdk">Compiling to and optimizing Wasm with Binaryen</a></li>
</ul>
<h3 id="llm-inference-with-webassembly" tabindex="-1">LLM inference with WebAssembly <a class="direct-link" href="https://blog.tomayac.com/2024/01/17/a-wasm-new-year/#llm-inference-with-webassembly" aria-hidden="true">π</a></h3>
<p><strong>Speaker:</strong> <a href="https://www.linkedin.com/in/sven-pfennig/">Sven Pfennig</a></p>
<p>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
<a href="https://webllm.mlc.ai/">WebLLM</a> running variants of
<a href="https://ai.meta.com/llama/">Llama 2</a> and
<a href="https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.2">Mistral-7B</a> 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
<a href="https://en.wikipedia.org/wiki/PAW_Patrol#PAW_Patrol">PAW Patrol members</a>, where
the model would plain hallucinate a member that never existed. Second, Sven
showed how to use the
<a href="https://www.secondstate.io/articles/run-llm-sh/"><code>run-llm.sh</code> script</a> to get an
LLM running on-device with <a href="https://wasmedge.org/">WasmEdge</a>. He noted the
usefulness of this approach to mock an OpenAI API response due to the
compatibility of the responses. Finally, he showed
<a href="https://www.fermyon.com/spin">Fermyon's Spin</a> solution to
<a href="https://developer.fermyon.com/spin/index">create serverless WebAssembly apps</a>,
run them locally, and finally deploy them to the
<a href="https://developer.fermyon.com/cloud/index">Fermyon cloud</a>.</p>
<p><strong>Resources:</strong></p>
<ul>
<li><a href="https://webllm.mlc.ai/">WebLLM</a></li>
<li><a href="https://www.secondstate.io/articles/run-llm-sh/"><code>run-llm.sh</code> script</a></li>
<li><a href="https://www.fermyon.com/spin">Fermyon Spin</a></li>
</ul>
<h1 id="observations" tabindex="-1">Observations <a class="direct-link" href="https://blog.tomayac.com/2024/01/17/a-wasm-new-year/#observations" aria-hidden="true">π</a></h1>
<p>There was huge interest for Wasm on the server. People were particularly curious
about
<a href="https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-intro.md">WASI</a>,
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 <a href="https://github.com/WebAssembly/wasi-nn">wasi-nn</a>, a WASI API for
performing ML inference modeled closely after
<a href="https://webmachinelearning.github.io/webnn-intro/">WebNN</a>.)</p>
<p>The company that hosted the meetup,
<a href="https://www.reply.com/liquid-reply/en/">Liquid Reply</a>, is pitching WebAssembly
as a solution for creating production-grade Wasm apps on Kubernetes and hosting
a workshop titled
<a href="https://2024.wasmio.tech/sessions/create-production-grade-wasm-applications-on-kubernetes-workshop/">Create Production-Grade Wasm Applications on Kubernetes</a>
at the upcoming <a href="https://2024.wasmio.tech/">Wasm I/O conference</a> in March 2024
(where Thomas Nattestad and I are going to present on
<a href="https://2024.wasmio.tech/sessions/webassembly-at-google/">WebAssembly at Google</a>,
alongside with Kevin Moore, who's going to present
<a href="https://2024.wasmio.tech/sessions/flutter-dart-and-wasm-shipping-a-new-model-for-web-applications/">Flutter, Dart, and WASM: Shipping a new model for Web applications</a>).</p>
<p>I also got a fair amount of questions on
<a href="https://github.com/WebAssembly/gc">WasmGC</a> and what it means for compiling new
programming languages to Wasm. The strategy of writing a higher-level article
(<a href="https://developer.chrome.com/blog/wasmgc">WebAssembly Garbage Collection (WasmGC) now enabled by default in Chrome</a>)
and a lower-level article
(<a href="https://v8.dev/blog/wasm-gc-porting">A new way to bring garbage collected programming languages efficiently to WebAssembly</a>)
really paid off and I could point developers at either of the two, dependent on
how deep they wanted to go.</p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2024%2F01%2F17%2Fa-wasm-new-year%2F&dp=%2F2024%2F01%2F17%2Fa-wasm-new-year%2F&dt=Wasm%20meetup%20Munich%3A%20A%20Wasm%20New%20Year!%20trip%20report" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2024/01/17/a-wasm-new-year/">https://blog.tomayac.com/2024/01/17/a-wasm-new-year/</a>.
</p>
W3C TPAC 2023 Trip Report
2023-09-25T16:19:45Z
https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/
<h2 id="background" tabindex="-1">Background <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#background" aria-hidden="true">π</a></h2>
<p>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
<a href="https://www.melia.com/en/hotels/spain/seville/melia-sevilla">MeliΓ£ hotel in Seville</a>,
Spain. The hotel is located right next to the
<a href="https://en.wikipedia.org/wiki/Plaza_de_Espa%C3%B1a,_Seville">Plaza de EspaΓ±a</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.</p>
<p><img src="https://blog.tomayac.com/images/w3ctpac2023tri--q5fbcovgd9r.jpg" alt="Panorama of Plaza de EspaΓ±a." /></p>
<p><img src="https://blog.tomayac.com/images/w3ctpac2023tri--u0djnvaere.jpg" alt="View of the hotel pool with the Glorieta De La Ronda De Capitania in the background." /></p>
<h2 id="monday-tuesday" tabindex="-1">Monday, Tuesday <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#monday-tuesday" aria-hidden="true">π</a></h2>
<h3 id="web-applications-working-group" tabindex="-1">Web Applications Working Group <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#web-applications-working-group" aria-hidden="true">π</a></h3>
<p>I attended the
<a href="https://www.w3.org/2008/webapps/">Web Applications Working Group</a> meetings on
Monday and Tuesday. After a quick rundown of all the APIs in scope for the
working group, the first topic was the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation">Screen Orientation API</a>,
which was mostly driven by questions and improvement proposals the WebKit folks
had after implementing it.</p>
<p>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.</p>
<p>An interesting corner case was debated in the context of the joint meeting with
the <a href="https://www.w3.org/groups/wg/das/">Devices and Sensors Working Group</a>.
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
<a href="https://w3c.github.io/webappswg/charter/draft-charter-2023.html#working-mode">shared deliverables</a>,
where the APIs that there <em>is</em> agreement on get cross-delivered by a working
group Apple is part of.</p>
<p>Following this, we talked about whether the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API">Screen Wake Lock API</a>
should use
<a href="https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation">transient</a>
or
<a href="https://developer.mozilla.org/en-US/docs/Glossary/Sticky_activation">sticky activation</a>.</p>
<p>The group made no progress on François Beaufort's suggestion for a
<a href="https://github.com/w3c/screen-wake-lock/blob/gh-pages/brightness-mode-explainer.md">Screen Brightness API</a>.</p>
<p>On the topic of
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Device_orientation_events/Detecting_device_orientation">DeviceOrientation API</a>
vs. <a href="https://www.w3.org/TR/generic-sensor/">Generic Sensor API</a>, 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.</p>
<p>For the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API">Geolocation API</a>,
most discussion circulated around limiting its precision by encouraging more
coarse data. On the opposite side, there's also still the open question of
<code>floorLevel</code> data, which Safari exposes, but which isn't standardized. The group
briefly discussed a <code>toJSON()</code> method for geolocation results, but it probably
would be a breaking change due to <code>instanceof</code> checks. The
<a href="https://github.com/w3c/geolocation-api/issues/74">background geolocation</a>
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.
<a href="https://www.w3.org/TR/geolocation-sensor/">Geolocation Sensor</a> had promises but
we're not sure it's worth bringing this over, since the callback can easily be
wrapped.</p>
<p>There was a joint meeting with the
<a href="https://www.w3.org/International/core/">Internationalization Working Group</a> to
discuss long-standing
<a href="https://github.com/w3c/manifest/issues/1045">open questions regarding translations of the Web App Manifest</a>
were investigated, which resulted in a
<a href="https://github.com/w3c/manifest/issues/1045#issuecomment-1713866460">potential solution</a>.
I foresee challenges when looking at the <code>"shortcuts"</code> member.</p>
<h4 id="notes-and-resources" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://docs.google.com/document/d/1RIaeXT_-j8n4iGPI3odZyJTqtHCKqe3oWZTO-j21z9U/edit#heading=h.n0pc0966xlbs">WebApps WG TPAC 2023 Meeting (Day 1)</a></li>
<li><a href="https://docs.google.com/document/d/1QDqllh8inOcIkTrblERm4HRKYh8Ce9Lu5S7WhOygs_0/edit#heading=h.n0pc0966xlbs">WebApps WG TPAC 2023 Meeting (Day 2)</a></li>
</ul>
<h3 id="web-platform-incubator-community-group" tabindex="-1">Web Platform Incubator Community Group <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#web-platform-incubator-community-group" aria-hidden="true">π</a></h3>
<p>On Monday afternoon, I switched over to the Web Platform Incubator Community
Group (<a href="https://www.w3.org/community/wicg/">WICG</a>) meeting. The topics I was
interested in were Low Level Device APIs and First Party Sets (now Related
Website Sets).</p>
<p>In the first part, Vincent Scheib presented on low level device APIs. Firefox
has rolled out
<a href="https://www.midi.org/forum/1332-web-midi-api-for-firefox">Web MIDI access based on an ad-hoc extension</a>,
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.</p>
<p>For First Party Sets, there are currently only a few entries in the
<a href="https://github.com/GoogleChrome/first-party-sets/blob/main/first_party_sets.JSON">First Party Sets list</a>,
following the
<a href="https://github.com/GoogleChrome/first-party-sets/blob/main/FPS-Submission_Guidelines.md">Submission Guidelines</a>.
It's rolling out to Chrome slowly. Other browser vendors do not implement First
Party Sets at the moment.</p>
<p>On Tuesday, the big topic was installable web apps where Dan Murphy presented
our existing solutions around
<a href="https://developer.chrome.com/docs/web-platform/launch-handler/">Launch Handling</a>.
Marcos from Apple and Olli from Mozilla questioned the queue model vs. an event
model and suggested to replace <code>LaunchParams</code> with <code>DataTransferItem</code>. Apple
noted that a launch handling feature is something that they would probably need.</p>
<blockquote>
<p>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?</p>
</blockquote>
<p>Sangwhan Moon provided the Technical Architecture Group
(<a href="https://tag.w3.org/">TAG</a>) 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.</p>
<p>Diego from Microsoft then presented the
<a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/WebInstall/explainer.md">Install API proposal</a>.
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.</p>
<p>The group further discussed the standardization of
[iOS' proprietary <code>navigator.standalone](https://github.com/w3c/manifest/issues/1092)</code>.</p>
<p>After that, we looked at the
<a href="https://www.w3.org/2022/09/13-webapps-minutes.html#t03">update algorithm</a>
discussed at the last TPAC and confirmed an update token would be the way to go.</p>
<p>The group briefly touched upon isolation of installed apps from the running
browser context and the challenges it introduces with OAuth etc.</p>
<p>Next was
<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers">protocol handling</a>
which Apple mostly opposed,
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Window_Controls_Overlay_API">window controls overlay</a>
and <a href="https://web.dev/tabbed-application-mode/">tabbed application mode</a> which
Apple was neutral-ish to, and my <a href="https://crbug.com/1295253">app menu proposal</a>
which Apple committed to coming up with a proposal for. Mozilla notably was in
the room, but had no opinion on almost all topics close to PWA.</p>
<p>Apple then dropped a
<a href="https://github.com/WebKit/explainers/blob/main/DeclarativeWebPush/README.md">proposal for declarative push notifications</a>.
I filed a
<a href="https://github.com/WebKit/explainers/blob/main/DeclarativeWebPush/README.md">number of questions</a>
to the proposal.</p>
<h4 id="notes-and-resources-1" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-1" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://docs.google.com/document/d/1zZp6fY0JV7nt4IHZczCSQw2SqYsGednpU2kAO95rJbU/edit#heading=h.b1lo9cy1ham">Web Apps and Handling Data for TPAC (public)</a></li>
<li><a href="https://docs.google.com/document/d/1PVkuF0g0pUj5NTQzUcpglSsOfwoOa_AZM-S7EJ5ZAbU/edit">WICG TPAC 2023 Low Level Device APIs</a>
(<a href="https://docs.google.com/presentation/d/1Nf64QLI-lkyqJ7UoDUPefrLJU7zcTUJKvTYV8L7ZAaY/edit?resourcekey=0-Bf69ilULrcA4qBZb7ZHdkA#slide=id.p">2022 TPAC Device APIs</a>)</li>
<li><a href="https://docs.google.com/document/d/1edq0k9yGtTgcR4NViu0sibUkCcRHHTCBQXGCK759jLY/edit#heading=h.703ew5rbvdo3">TPAC 2023 - Web Platform Incubator CG (WICG) - Isolated Web Apps - Notes</a></li>
<li><a href="https://github.com/WICG/first-party-sets/blob/main/meetings/09-11-2023-TPAC-minutes.md">First Party Sets</a>
(<a href="https://docs.google.com/presentation/d/1K6surspD72-sdkVdRy6KxOA3uipj6XXB9lF_ynOaeX4/edit?usp=sharing">[Public] TPAC 2023: Related Website Sets (fka First-Party Sets)</a>)</li>
<li><a href="https://onedrive.live.com/edit.aspx?resid=8D8B723D008546BD!949334&ithint=file%2cdocx&wdo=2&authkey=!APpYdHqZA56dkBU">Web Install API TPAC 23 discussion</a></li>
</ul>
<h2 id="wednesday" tabindex="-1">Wednesday <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#wednesday" aria-hidden="true">π</a></h2>
<p>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.</p>
<h3 id="accelerating-the-web-performance-by-compiling-javascript-code-to-wasm" tabindex="-1">Accelerating the Web performance by compiling Javascript code to WASM <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#accelerating-the-web-performance-by-compiling-javascript-code-to-wasm" aria-hidden="true">π</a></h3>
<p>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 <em>certain</em>
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.</p>
<h4 id="notes-and-resources-2" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-2" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://www.w3.org/2023/09/13-js2wasm-minutes.html">Minutes</a></li>
<li><a href="https://lists.w3.org/Archives/Public/www-archive/2023Sep/att-0021/TPCA_2023_-_Web_for_Apps_v1.pdf">Slides web for apps</a></li>
<li><a href="https://lists.w3.org/Archives/Public/www-archive/2023Sep/att-0021/W3C-TPAC-JWST-Beihang-ShiXiaohua-final.pdf">Slides for JWST</a></li>
</ul>
<h3 id="page-embedded-permission-control-permission-element" tabindex="-1">Page Embedded Permission Control (Permission Element) <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#page-embedded-permission-control-permission-element" aria-hidden="true">π</a></h3>
<p>In this session, the Chrome team introduced our current thinking of a
<code>permission</code> 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.</p>
<h4 id="notes-and-resources-3" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-3" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://docs.google.com/presentation/d/1fzMEeyWbdpBS7HN9WumIOSbqB3pl-MG2DTo_5-lvgus/edit#slide=id.g27df7eff9c5_0_226">TPAC Permission Control (public)</a></li>
<li><a href="https://docs.google.com/document/d/1pJFCADgasiqojESz2VePkVwaDdlfDqpN5JSqo4T4mMs/edit#heading=h.ocs3ne1w3v4g">(public) Page Embedded Permission Control (Permission Element) - TPAC 2023 Breakout</a></li>
</ul>
<h3 id="the-future-of-powerful-apis-on-the-web-platform" tabindex="-1">The Future of Powerful APIs on the Web Platform <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#the-future-of-powerful-apis-on-the-web-platform" aria-hidden="true">π</a></h3>
<p>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.</p>
<h4 id="notes-and-resources-4" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-4" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://docs.google.com/presentation/d/1-1Q-2206wTjWadU0NtXozEWyGZbnaz1ABHCWL_MCNaM/edit#slide=id.p">The Future of Powerful APIs on the Web Platform</a></li>
<li><a href="https://docs.google.com/document/d/1vRO6xher_AiHDOkQIClgz4wCI8tEAJdHifLU-M2epOI/edit#heading=h.xxa48zxk3cpj">Powerful APIs TPAC 2023 Breakout minutes</a></li>
</ul>
<h3 id="privacy-principles" tabindex="-1">Privacy Principles <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#privacy-principles" aria-hidden="true">π</a></h3>
<p>This session introduced the
<a href="https://www.w3.org/TR/privacy-principles/">privacy principles</a> jointly
developed by TAG and Privacy Interest Group
(<a href="https://www.w3.org/Privacy/IG/">PING</a>) 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 <code>requestStorageAccess()</code> to which the
answer was to abstract as much as possible in the permission prompt.</p>
<h4 id="notes-and-resources-5" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-5" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://raw.githack.com/w3ctag/privacy-principles/main/meetings/2023-09-tpac/breakout/slides.html">Slides</a></li>
<li><a href="https://www.w3.org/2023/09/13-privacy-principles-minutes.html">Minutes</a></li>
</ul>
<h3 id="the-cross-browser-future-of-installable-web-apps" tabindex="-1">The cross-browser future of Installable Web Apps <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#the-cross-browser-future-of-installable-web-apps" aria-hidden="true">π</a></h3>
<p>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
<a href="https://adaptivecards.io/">Adaptive Card</a> 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.</p>
<h4 id="notes-and-resources-6" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-6" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://docs.google.com/presentation/d/1t_0WsgKFy2VmFY9lzpdLy00FgXK3Z9d0XJybOtCl-Tk/edit#slide=id.p">The cross-browser future of Installable Web Apps</a></li>
<li><a href="https://docs.google.com/document/d/1QzHTKGDxHol7KybdqY-rll1VGd1FIirvW-mtAFxPjC4/edit#heading=h.5wzb241vwwm2">The cross-browser future of Installable Web Apps</a></li>
</ul>
<h3 id="installing-web-apps" tabindex="-1">Installing Web Apps <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#installing-web-apps" aria-hidden="true">π</a></h3>
<p>This was again a deep-dive in Microsoft's
<a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/WebInstall/explainer.md">Web Install API</a>
proposal. Many points or arguments were already made in the
<a href="https://onedrive.live.com/edit?id=8D8B723D008546BD!949334&resid=8D8B723D008546BD!949334">WICG session on Tuesday</a>
(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 <code>getInstalledRelatedApps()</code> 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.</p>
<h4 id="notes-and-resources-7" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-7" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://onedrive.live.com/edit?id=8D8B723D008546BD!949334&resid=8D8B723D008546BD!949334">Minutes</a></li>
</ul>
<h2 id="thursday" tabindex="-1">Thursday <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#thursday" aria-hidden="true">π</a></h2>
<h2 id="devices-and-sensors" tabindex="-1">Devices and Sensors <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#devices-and-sensors" aria-hidden="true">π</a></h2>
<p>I spent Thursday in the Devices and Sensors Working Group meeting. The first
part of the day was occupied by a charter discussion between Philippe Le HΓ©garet
from the W3C. The core question that was discussed was cross-deliverables
between the Web Apps WG and the Devices and Sensors WG, since Apple can't commit
to joining the Device and Sensors WG but is interested in some of the things the
group is working on.</p>
<p>Next, we looked at the privacy principles and how they are applied by some of
the specs. Marian Harbach briefly presented the <code>permission</code> element.</p>
<p>In suite, Intel talked about testability improvements they made around
WebDriver.</p>
<p>Regarding Generic Sensors, we made a resolution to ensure Generic Sensor-based
specs have mitigations normatively defined for factory calibration device
fingerprinting, matching
<a href="https://w3c.github.io/deviceorientation/#security-and-privacy:~:text=The%20calibration%20of%20accelerometers%2C%20gyroscopes%20and%20magnetometers%20may%20reveal%20persistent%20details%20about%20the%20particular%20sensor%20hardware">existing normative mitigations in the DeviceOrientation Events spec</a>.</p>
<p>After that, we went through all the APIs in scope of the working group and
looked at their status:</p>
<ul>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t09">Accelerometer</a>,
<a href="https://www.w3.org/2023/09/14-dap-minutes.html#t10">Gyroscope</a>, and
<a href="https://www.w3.org/2023/09/14-dap-minutes.html#t11">Magnetometer</a>, all with
no issues.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t12">Orientation Sensor</a> and
<a href="https://www.w3.org/2023/09/14-dap-minutes.html#t13">DeviceOrientation Events</a>
in the context of spatial audio, referring to WebXR as the better home for the
use case.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t14">Ambient Light Sensor</a>
with going through existing use cases.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t15">Proximity Sensor</a> with no
issues.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t16">Geolocation Sensor</a> where
we went through the existing use cases for background geolocation and
geofencing again.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t17">Screen Brightness API</a>
with no updates since Apple's negative feedback on an imperative API and after
François Beaufort's
<a href="https://github.com/WICG/screen-brightness/issues/1">proposal</a> for an element
attribute for increasing the screen brightness.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t18">Screen Wake Lock API</a>
with some address-worthy implementer feedback from Apple.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t19">System Wake Lock API</a>
with a discussion of use cases.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t20">Contact Picker API</a> with
no updates.</li>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html#t21">Battery Status API</a> which
might be turned into a user preference media feature.</li>
</ul>
<p>Next, Intel gave a device market overview followed by an implementation overview
including compelling use case demonstrations for the
<a href="https://www.w3.org/2023/09/14-dap-minutes.html#t22">Device Posture API</a>.
Fine-grained angle information was removed from the spec due to privacy
concerns.</p>
<p>In the following, Intel continued on presenting on the
<a href="https://www.w3.org/2023/09/14-dap-minutes.html#t23">Compute Pressure API</a>, 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.</p>
<p>The day ended with a look at the
<a href="https://www.w3.org/2023/09/14-dap-minutes.html#t26">Geolocation API</a>, which is
mostly stable but could add improvements around encouraging more coarse location
access.</p>
<p>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.</p>
<h4 id="notes-and-resources-8" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-8" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://www.w3.org/2023/09/14-dap-minutes.html">Minutes</a></li>
</ul>
<h2 id="friday" tabindex="-1">Friday <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#friday" aria-hidden="true">π</a></h2>
<h3 id="what-working-group" tabindex="-1">WHAT Working Group <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#what-working-group" aria-hidden="true">π</a></h3>
<p>On Friday, I saw an interesting
<a href="https://github.com/whatwg/html/issues/5033">proposal for a <code>headinglevelstart</code></a>
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
embed<code>README.md</code> files into repository homepages and who wish to adjust heading
levels accordingly.</p>
<p>Next, a
<a href="https://github.com/whatwg/html/issues/5326">focus navigation start point proposal</a>
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.</p>
<p>Noteworthy was also a
<a href="https://github.com/WICG/observable">proposal for an Observable API</a> presented
by Dominic Farolino , which would allow for more convenient event handling
scenarios and that was greeted with great interest.</p>
<h4 id="notes-and-resources-9" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-9" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://docs.google.com/document/d/1V6_s_VsaWcI9J-ZATbIKKijn59JbVmRMsHXYyH29sho/edit#heading=h.9gswhzv85q2">Minutes: WHATWG session</a></li>
<li><a href="https://docs.google.com/presentation/d/1lPLUcm_yqR5couGwouETTkblhqgHfpgUBkm2mnmxegU/edit#slide=id.p">Observable API Presentation TPAC 2023</a></li>
</ul>
<h3 id="web-platform-incubator-community-group-1" tabindex="-1">Web Platform Incubator Community Group <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#web-platform-incubator-community-group-1" aria-hidden="true">π</a></h3>
<p>In the afternoon, I attended Web Incubator Community Group
(<a href="https://wicg.io/">WICG</a>) sessions focused on the Accessibility Object Model
(AOM), the Shape Detection API, and the File System.</p>
<p>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
<a href="https://github.com/WICG/aom/blob/gh-pages/explainer.md">AOM explainer</a> contains
many abandoned sections and the <a href="https://wicg.github.io/aom/spec/">AOM spec</a> is
just a barebones skeleton, plus the
<a href="https://wicg.github.io/aom/demos/tictactoe.html">demo</a> doesn't work (anymore).</p>
<p>For the
<a href="https://developer.chrome.com/articles/shape-detection/">Shape Detection API</a>,
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 <a href="https://mediastreamtrack.glitch.me/">demo</a>
that solves this with
<a href="https://alvestrand.github.io/mediacapture-transform/chrome-96.html">MediaStreamTrack Insertable Media Processing using Streams</a>.
Apple was also worried about the Chrome-specificity of the test suite and the
future venue of the proposal, hinting it could be the
<a href="https://www.w3.org/groups/wg/webmachinelearning">WebML WG</a>. 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.</p>
<p>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
<a href="https://christianliebel.com/">Christian Liebel</a>).</p>
<h4 id="notes-and-resources-10" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-10" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://www.w3.org/2023/09/15-wicg-minutes.html">Minutes</a></li>
<li><a href="https://docs.google.com/presentation/u/1/d/1ouEXjfvkxM9WJmTg22Fb_qwMjXeOrZG1Aa3p97Fj3j0/edit">[TPAC 2023] WICG File System</a></li>
</ul>
<h3 id="web-app-security-working-group" tabindex="-1">Web App Security Working Group <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#web-app-security-working-group" aria-hidden="true">π</a></h3>
<p>On the end of the day, I crashed the Web App Security WG meeting and saw Mike
West's proposal for
<a href="https://github.com/mikewest/purposeful-permissions">purposeful permissions</a>. I
made the point for aligning with other efforts in this area in an
<a href="https://github.com/mikewest/purposeful-permissions/issues/1">issue</a>, namely the
W3C MiniApp Manifest and Isolated Web Apps permissions.</p>
<h4 id="notes-and-resources-11" tabindex="-1">Notes and resources <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#notes-and-resources-11" aria-hidden="true">π</a></h4>
<ul>
<li><a href="https://cryptpad.w3ctag.org/code/#/2/code/edit/Pq1xOhFZ9oxeI5vrXwx--B3a/">Minutes</a></li>
</ul>
<h2 id="meta-observations" tabindex="-1">Meta observations <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#meta-observations" aria-hidden="true">π</a></h2>
<h3 id="covid-measures" tabindex="-1">Covid measures <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#covid-measures" aria-hidden="true">π</a></h3>
<p>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.</p>
<h3 id="in-person-event" tabindex="-1">In-person event <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#in-person-event" aria-hidden="true">π</a></h3>
<p>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.</p>
<h3 id="food" tabindex="-1">Food <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#food" aria-hidden="true">π</a></h3>
<p>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.</p>
<p>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.</p>
<h3 id="google-attendance" tabindex="-1">Google attendance <a class="direct-link" href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/#google-attendance" aria-hidden="true">π</a></h3>
<p>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".</p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2023%2F09%2F25%2Fw3c-tpac-2023-trip-report%2F&dp=%2F2023%2F09%2F25%2Fw3c-tpac-2023-trip-report%2F&dt=W3C%20TPAC%202023%20Trip%20Report" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/">https://blog.tomayac.com/2023/09/25/w3c-tpac-2023-trip-report/</a>.
</p>
Web Apps on macOS Sonoma 14 Beta
2023-06-07T13:39:59Z
https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/
<h2 id="executive-summary" tabindex="-1">Executive summary <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#executive-summary" aria-hidden="true">π</a></h2>
<p>With macOS Sonoma, <strong>Apple goes all-in on the concept of installable web apps</strong>.
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.</p>
<h2 id="testing-environment" tabindex="-1">Testing environment <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#testing-environment" aria-hidden="true">π</a></h2>
<p>Tested on macOS Sonoma 14.0 Beta (<code>23A5257q</code>) with Safari version 17.0
(<code>19616.1.14.11.11</code>). It probably doesn't matter, but the testing device was a
13-inch, M1, 2020 MacBook Pro.</p>
<h2 id="install-experience" tabindex="-1">Install experience <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#install-experience" aria-hidden="true">π</a></h2>
<p>On macOS Sonoma, you can add a websiteβany website, not just apps with a
manifestβto your Dock. Go to the <strong>Share</strong> icon and click <strong>Add to Dock</strong>, or
use the menu item <strong>File > Add to Dock</strong>.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--u0q7vo9587s.png" alt="Adding an app via the Share icon." /></p>
<p><em>Adding an app via the <strong>Share</strong> icon.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--9zgyksdtzr.png" alt="Adding an app via the File menu." /></p>
<p><em>Adding an app via the <strong>File</strong> menu.</em></p>
<p>You can adjust the name and icon if desired. The URL is the URL you're on for
pages without a manifest, or the <code>start_url</code> 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.</p>
<p><strong>π Observation:</strong> Unlike on iOS/iPadOS, you can't add the same app twice,
unless you rename it.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--jbz4jqyyylc.png" alt="App name and icon are adjustable, the URL is not." /></p>
<p><em>App name and icon are adjustable, the URL is not.</em></p>
<p>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.</p>
<p><strong>π Observation:</strong> 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.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--1iikfvhhzcr.png" alt="Web app added to the Dock." /></p>
<p><em>Web app added to the Dock.</em></p>
<p>When right-clicking the Dock icon, you can uncheck <strong>Keep in Dock</strong> and still
launch the app via Launchpad, Spotlight Search, or even just by double-clicking
the app icon in <code>~/Applications/</code>.</p>
<h2 id="launch-experience" tabindex="-1">Launch experience <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#launch-experience" aria-hidden="true">π</a></h2>
<p>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.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--hysefdcnykc.png" alt="Web app running without any Safari UI." /></p>
<p><em>Web app running without any Safari UI.</em></p>
<p><strong>π Observation:</strong> 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. <em>"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".</em></p>
<p><strong>π Observation:</strong> Web Inspector (DevTools) works a little differently than,
for example, in Chrome: even with the <strong>Show features for web developers</strong>
checkbox in Safari checked, there's no <strong>Develop</strong> menu item nor can you
right-click and <strong>Inspect Element</strong> in a web app. Instead, you debug apps via
Safari's <strong>Develop > $machineName > $appName</strong> menu item (thanks,
<a href="https://mastodon.social/@samedwards/110504651650657859">@samedwards@mastodon.social</a>).
If all app windows are closed but the app isn't quit, a potential service worker
will be inspectable until it gets terminated after a couple of seconds.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--hysefdcnykd.png" alt="Debugging a web app via Safari." /></p>
<p><em>Debugging a web app via Safari.</em></p>
<p><strong>π Observation:</strong> Extensions don't run and likewise aren't displayed. Also
probably a conscious decision.</p>
<p><strong>π Observation:</strong> Same-origin (or
in-<a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/scope">scope</a> if a
manifest exists) links are handled in-app, cross-origin (or
out-of-<a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/scope">scope</a> if a
manifest exists) links open in the default browser. A notable exception are
OAuth flow links, which are handled in-app based on a heuristic. Links opened
via <code>window.open()</code> will always open in the web app.</p>
<p>If a user navigates to an already installed app in Safari, a prompt is displayed
that invites the user to <strong>Open in web app</strong>.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--k85cr23x5v.png" alt="Prompt inviting the user to Open in web app." /></p>
<p><em>Prompt inviting the user to <strong>Open in web app</strong>.</em></p>
<h2 id="macos-integration-experience" tabindex="-1">macOS integration experience <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#macos-integration-experience" aria-hidden="true">π</a></h2>
<p>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.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--6e18tk2ywgl.png" alt="Multitasking experience." /></p>
<p><em>Multitasking experience.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--gyygf94lo0l.png" alt="Spotlight search experience." /></p>
<p><em>Spotlight search experience.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--cwy5ftpy4qi.png" alt="Launchpad experience." /></p>
<p><em>Launchpad experience.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--wg589k8r7mh.png" alt="Stage Manager experience." /></p>
<p><em>Stage Manager experience.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--n1elzn6cq9n.png" alt="All web apps have an About dialog." /></p>
<p><em>All web apps have an <strong>About</strong> dialog.</em></p>
<h2 id="settings-and-permissions" tabindex="-1">Settings and permissions <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#settings-and-permissions" aria-hidden="true">π</a></h2>
<p>Web apps work with AutoFill credentials from iCloud Keychain and from
third-party apps that have adopted the
<a href="https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_authentication-services_autofill-credential-provider">Credential Provider Extension API</a>.
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.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--2rirguybc3w.png" alt="System settings with Camera permissions." /></p>
<p><em>System settings with Camera permissions.</em></p>
<p>Web apps on Mac support
<a href="https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_web_apps_safari_and_other_browsers?language=objc">web push</a>,
<a href="https://webkit.org/blog/14112/badging-for-home-screen-web-apps/">badging</a>, and
all the usual web standards implemented by WebKit, just like web apps
<a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/">on iOS and iPadOS</a>.</p>
<p><strong>π Observation:</strong> There seems to be a
<a href="https://bugs.webkit.org/show_bug.cgi?id=257807">bug</a> where the hosting Web App
appears as the app requesting the Notifications permission. Notifications then
work as expected, though, including using the correct icon.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--f4adwfi8t1.png" alt="Notifications permission prompt with the wrong app name and icon." /></p>
<p><em>Notifications permission prompt with the wrong app name and icon.</em></p>
<p>Web apps have their own <strong>Settings</strong> dialog. In <strong>General</strong>, the app name and
icon can be changed and navigation controls can be toggled on or off. The
<a href="https://developer.apple.com/documentation/safari-release-notes/safari-15-release-notes#:~:text=Added%20support%20for%20the%20theme%2Dcolor%20meta%20tag%20to%20change%20the%20tab%20bar%20background%20and%20over%2Dscroll%20area%20in%20macOS%20and%20iPadOS%2C%20and%20the%20status%20bar%20in%20iOS.">theming behavior of the title bar</a>
can be changed, too.</p>
<p><strong>π Observation:</strong> Navigation controls are toggled off when there's a manifest
with <code>"display": "standalone"</code>. In all other cases, even if a manifest exists
but with a different <code>"display"</code> mode, navigation controls are toggled on.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--kgsu98ksrqf.png" alt="Web app Settings dialog on the General tab." />
<em>Web app <strong>Settings</strong> dialog on the <strong>General</strong> tab.</em></p>
<p><strong>π Observation:</strong> There's currently a
<a href="https://bugs.webkit.org/show_bug.cgi?id=257806">bug</a> where web apps don't
correctly report <code>matchMedia('(display-mode: standalone)')</code>. Added to the Dock
web apps think they run in a tab.</p>
<p>With navigation controls enabled, there's an <strong>Open in Safari</strong> icon in the
upper right corner. Despite its label, it actually respects the user's default
browser.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--c95fwgkg6e9.png" alt="Open in Safari icon." /></p>
<p><em><strong>Open in Safari</strong> icon.</em></p>
<p>Web pages get navigation affordances in the form of a back and forward button.
There's no reload button.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--f5jaczcwma.png" alt="Back and forward buttons." /></p>
<p><em>Back and forward buttons.</em></p>
<p><strong>π Observation:</strong> 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 <code><title></code> is shown.</p>
<p><strong>π Observation:</strong> When you right-click, there's a context menu with <strong>Reload</strong>
or <strong>Back</strong> and <strong>Reload</strong>. This works independent from whether navigation
controls are toggled on or off.</p>
<p>The <strong>Privacy</strong> tab allows the user to clear website data and links into the
<strong>Privacy & Security Settings</strong> of the System Settings app.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--f37x3wpvl5.png" alt="Web app Settings dialog on the Privacy tab." /></p>
<p><em>Web app <strong>Settings</strong> dialog on the <strong>Privacy</strong> tab.</em></p>
<h2 id="technical-analysis" tabindex="-1">Technical analysis <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#technical-analysis" aria-hidden="true">π</a></h2>
<p>(See
<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1451667#c7">comment #7 of Chromium bug 1451667</a>
for the full details.)</p>
<p>All apps are stored in <code>~/Applications/</code>. The package contents of each apps are:</p>
<ul>
<li>a <code>_CodeSignature</code> folder with code signature metadata</li>
<li>a <code>Resources</code> folder with just the app icons as a single
<code>ApplicationIcon.icns</code> file</li>
<li>an <code>Info.plist</code> file.</li>
</ul>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--oekactyqlf.png" alt="The package contents of an app." /></p>
<p><em>The package contents of an app.</em></p>
<p>The <code>Info.plist</code> file interestingly contains an XML version of key parts of the
manifest and metadata about the app.</p>
<pre class="language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">plist</span> <span class="token name">PUBLIC</span> <span class="token string">"-//Apple//DTD PLIST 1.0//EN"</span> <span class="token string">"http://www.apple.com/DTDs/PropertyList-1.0.dtd"</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plist</span> <span class="token attr-name">version</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleIconFile<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>ApplicationIcon<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleIdentifier<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span>
<span class="token punctuation">></span></span>com.apple.Safari.WebApp.svgco.de.53298B34-AF7F-4074-9CA9-1EE46B7E3E83<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span>
<span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleInfoDictionaryVersion<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>6.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleName<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>SVGcode<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundlePackageType<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>AAPL<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleShortVersionString<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>1.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleSupportedPlatforms<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>MacOSX<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleURLTypes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleURLSchemes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>x-webkit-app-launch<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>LSHandlerRank<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>None<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleVersion<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>LSMinimumSystemVersion<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>14.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>LSTemplateApplication<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>true</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>LSTemplateApplicationParameters<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>CFBundleIdentifier<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>com.apple.Safari.WebApp<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>TemplateAppUUID<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>53298B34-AF7F-4074-9CA9-1EE46B7E3E83<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>defaultarguments<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>true</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>teamIdentifier<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>Manifest<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>description<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span>
<span class="token punctuation">></span></span>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.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span>
<span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>display<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>standalone<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>icons<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>purpose<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>maskable<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>sizes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>1024x1024<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>src<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>https://svgco.de/favicon.png<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>type<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>image/png<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>purpose<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>any<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>sizes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>150x150<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>src<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>https://svgco.de/favicon.svg<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>type<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>image/svg+xml<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>purpose<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>monochrome<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>sizes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>150x150<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>src<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>https://svgco.de/favicon-bw.svg<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>type<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>image/svg+xml<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>array</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>name<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>SVGcode<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>scope<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>https://svgco.de<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>short_name<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>SVGcode<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>start_url<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>https://svgco.de/<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>theme_color<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>#ffffff<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>WKPushBundleMetadata<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>key</span><span class="token punctuation">></span></span>manifestId<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>key</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>string</span><span class="token punctuation">></span></span>https://svgco.de/<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>string</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dict</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plist</span><span class="token punctuation">></span></span></code></pre>
<p>Similar to iOS/iPadOS, web apps run in the context of a separate process called
<code>Web App.app</code>, which resides in
<code>/System/Volumes/Preboot/Cryptexes/App/System/Library/CoreServices/Web App.app</code>.</p>
<p><strong>π Observation:</strong> 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.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--3cd4wjo74qu.png" alt="The Web App.app app in Finder." /></p>
<p><em>The <code>Web App.app</code> app in Finder.</em></p>
<p>Each web app runs as its own process of kind <code>Web</code>, accompanied by a number of
helper processes of kind <code>Apple</code>. They can all be seen in Activity Monitor.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--cln1h5jyf1.png" alt="Activity Monitor showing all processes associated with a web app." /></p>
<p><em>Activity Monitor showing all processes associated with a web app.</em></p>
<h2 id="wish-list-for-apple" tabindex="-1">Wish list for Apple <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#wish-list-for-apple" aria-hidden="true">π</a></h2>
<p>(Also see
<a href="https://docs.google.com/document/d/1chkEulpKBNQQfGIgTfQSbJhjw5mtZhvE47PF4tyTEXc/edit#">Most wanted PWA features on iOS/iPadOS/macOS Safari</a>.)</p>
<ul>
<li>Add support for the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API">File System Access API</a>,
so users can install apps and edit files directly, rather than opening them
and then downloading a copy.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=231706">π§Β 231706</a>]</li>
<li>Add support for
<a href="https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsFileSystemHandle"><code>DataTransferItem.getAsFileSystemHandle()</code></a>,
so users can drag and drop files into web apps and edit the file.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=257792">π§ 257792</a>]</li>
<li>Add support for the
<a href="https://developer.chrome.com/articles/web-share-target/">Web Share Target API</a>,
so you can share data to installed web apps.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=194593">π§Β 194593</a>]</li>
<li>Let web apps programmatically trigger the <strong>Add to Dock</strong> flow, since the
<strong>Share</strong> icon and the <strong>File</strong> menu install ways are hard to discover.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=255716">π§Β 255716</a>]</li>
<li>Add support for the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Window_Controls_Overlay_API">Window Controls Overlay API</a>,
so the gorgeous current experience can be made even more gorgeous.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=257782">π§Β 257782</a>]</li>
</ul>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--4dq3oazo75q.png" alt="Spotify native app title bar experience." /></p>
<p><em>Spotify native app title bar experience.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--9bwtu16pbtv.png" alt="Spotify web app title bar experience." /></p>
<p><em>Spotify web app title bar experience.</em></p>
<ul>
<li>Add support for the
<a href="https://github.com/WICG/file-handling/blob/main/explainer.md">File Handling API</a>,
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 <strong>Open with</strong> if the web app can handle a file type, but isn't
the default file handler.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=257783">π§Β 257783</a>]</li>
<li>Add support for the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Launch_Handler_API">Launch Handler API</a>,
so web apps can decide how they want to handle launch events.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=257785">π§ 257785</a>]</li>
<li>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.
[<a href="https://bugs.webkit.org/show_bug.cgi?id=257786">π§ 257786</a>]</li>
<li>Allow users to turn off the <strong>Open in web app</strong> prompt.</li>
</ul>
<h2 id="recommendations-for-chrome" tabindex="-1">Recommendations for Chrome <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#recommendations-for-chrome" aria-hidden="true">π</a></h2>
<ul>
<li>Better respect macOS' design paradigms. Currently web app icon handling looks
not integrated and icon shapes are all over the place. This is tracked as
<a href="https://crbug.com/1230792">crbug/1230792</a>. The examples below are all web
apps installed via Chrome.</li>
</ul>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--pp6i6yqgm9l.png" alt="Web app icon shapes installed from Chrome don't respect the squircle." /></p>
<p><em>Web app icon shapes installed from Chrome don't respect the squircle.</em></p>
<ul>
<li>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.</li>
</ul>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--gqdtdnumc98.png" alt="Window Controls Overlay chevron and extension puzzle piece clutter the UI of
Chrome-installed apps." /></p>
<p><em>Window Controls Overlay chevron and extension puzzle piece clutter the UI of
Chrome-installed apps.</em></p>
<h2 id="new-fugu-api-needs" tabindex="-1">New Fugu API needs <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#new-fugu-api-needs" aria-hidden="true">π</a></h2>
<p>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
<a href="https://crbug.com/1295253">crbug/1295253</a>. The screenshots below show all menu
items as per the current default.</p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--svgcode.png" alt="Web app default app name menu." /></p>
<p><em>Web app <strong>default app name</strong> menu.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--file.png" alt="Web app File menu." /></p>
<p><em>Web app <strong>File</strong> menu.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--edit.png" alt="Web app Edit menu." /></p>
<p><em>Web app <strong>Edit</strong> menu.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--view.png" alt="Web app View menu." /></p>
<p><em>Web app <strong>View</strong> menu.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--go.png" alt="Web app Go menu." /></p>
<p><em>Web app <strong>Go</strong> menu.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--window.png" alt="Web app Window menu." /></p>
<p><em>Web app <strong>Window</strong> menu.</em></p>
<p><img src="https://blog.tomayac.com/images/webappsonmacos--help.png" alt="Web app Help menu." /></p>
<p><em>Web app <strong>Help</strong> menu.</em></p>
<h2 id="conclusion" tabindex="-1">Conclusion <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#conclusion" aria-hidden="true">π</a></h2>
<p>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.</p>
<h2 id="related-links" tabindex="-1">Related links <a class="direct-link" href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/#related-links" aria-hidden="true">π</a></h2>
<ul>
<li><a href="https://webkit.org/blog/14205/news-from-wwdc23-webkit-features-in-safari-17-beta/#web-apps">News from WWDC23: WebKit Features in Safari 17 beta</a></li>
<li><a href="https://developer.apple.com/videos/play/wwdc2023/10120/">What's new in web apps</a></li>
</ul>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2023%2F06%2F07%2Fweb-apps-on-macos-sonoma-14-beta%2F&dp=%2F2023%2F06%2F07%2Fweb-apps-on-macos-sonoma-14-beta%2F&dt=Web%20Apps%20on%20macOS%20Sonoma%2014%20Beta" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/">https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/</a>.
</p>
Getting my domain tomayac.de back
2023-04-18T08:26:04Z
https://blog.tomayac.com/2023/04/18/getting-my-domain-tomayac-de-back/
<p>There's this old mantra that
<a href="https://www.w3.org/Provider/Style/URI">Cool URIs don't change</a> that Tim Berners
Lee has been championing since 1998. And in the subtitle of the linked document
it says:</p>
<blockquote>
<p>What makes a cool URI?<br /> A cool URI is one which does not change.<br /> What
sorts of URI change?<br /> > <strong>URIs don't change: people change them.</strong></p>
</blockquote>
<p>And that's exactly what happened in my case: I changed them. Tim goes on later
in the document:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>That latter part (<em>"or can no longer afford to keep the server running"</em>) was
meβa person, not a companyβin my late, money-saving student days. At the time, I
owned <code>tomayac.de</code>, and after making the switch to <code>tomayac.com</code>, I let go the
<code>.de</code> domain after a while because I didn't want to pay for it anymore.</p>
<p>While I did make sure to redirect everything properly (that is, using a
<a href="https://developers.google.com/search/docs/crawling-indexing/301-redirects#permanent-server-side-redirects">permanent 301 redirect</a>),
the problem really was that I had referenced the <code>.de</code> domain in my printed
<a href="https://www.cs.upc.edu/~tsteiner/papers/2007/automatic-multi-language-program-library-generation-for-rest-apis-masters-thesis-2007.pdf">Master's thesis</a>
that I couldn't change and in which I wrote about a tool I built called
<a href="https://tomayac.com/rest-describe/latest/RestDescribe.html">REST Describe & Compile</a>.
And of course over the years I had accrued the occasional external link that I
likewise couldn't control.</p>
<p>I think the <code>.de</code> domain was parked for a while gathering dust, until it was
taken over by <a href="https://www.linkedin.com/in/anowak2/">AndrΓ© Nowak</a> who redirected
it to a page on his site called
<a href="https://www.linux-abos.de/vermischtes/rest-describe-compile-tool/">Tomayac.de β REST Describe & Compile Tool</a>.
Many years passedβ¦</p>
<p>For some nostalgic reason a couple of days ago, I decided to see if I could get
my domain back. So I emailed AndrΓ© out of the blue based on the
<a href="https://www.linux-abos.de/impressum/">imprint of <code>linux-abos.de</code></a> and asked him
how much it would cost to transfer <code>tomayac.de</code> back to me, and what happened
next is just the nicest story.</p>
<p>AndrΓ© kindly offered to sell it back to me for the price he originally payed for
the domain, that is 12β¬, plus 1β¬ for his tax advisor, since, turns out, domains
are fixed assets. Before I even had a chance to pay him, he sent me the auth
code. I ended up sending him 25β¬ as a <strong>thank you</strong> after successfully moving
the domain to <a href="https://domains.google/">Google Domains</a>.</p>
<p><img src="https://blog.tomayac.com/images/google-domains.png" alt="Google Domains admin panel showing the DNS section of the domain tomayac.de being edited." /></p>
<p>Now all that remains is setting up DNS properly, get a certificate, set up an
<code>.htaccess</code>, 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!</p>
<p>So for the back link, if you ever need to update the operating system on your
smart phone, consider the page
<a href="https://www.linux-abos.de/spiele/linux-handy-smartphone/">Linux auf dem Handy Β» Das Smartphone mit Linux updaten!</a>
and for the historical REST Describe and Compile content AndrΓ© created, read
<a href="https://www.linux-abos.de/vermischtes/rest-describe-compile-tool/">Tomayac.de β REST Describe & Compile Tool</a>.
Thanks again, AndrΓ© π, for being the kindest person on the Internet last
Wednesday.</p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2023%2F04%2F18%2Fgetting-my-domain-tomayac-de-back%2F&dp=%2F2023%2F04%2F18%2Fgetting-my-domain-tomayac-de-back%2F&dt=Getting%20my%20domain%20tomayac.de%20back" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2023/04/18/getting-my-domain-tomayac-de-back/">https://blog.tomayac.com/2023/04/18/getting-my-domain-tomayac-de-back/</a>.
</p>
Cross platform software frameworks
2023-02-23T19:19:38Z
https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/
<h1 id="cross-platform-software-frameworks" tabindex="-1">Cross Platform Software Frameworks <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#cross-platform-software-frameworks" aria-hidden="true">π</a></h1>
<p>The other day, I came across
<a href="https://github.com/elk-zone/elk-native">Elk Native</a>, a native version of the
rather excellent, if early-stage, Mastodon Web client <a href="https://elk.zone/">Elk</a>.
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
<a href="https://github.com/elk-zone/elk-native/releases/download/elk-native-v0.4.0/Elk_0.4.0_macos_x86_64.dmg"><code>Elk_0.4.0_macos_x86_64.dmg</code></a>
and immediately ran into
<a href="https://github.com/elk-zone/elk-native/issues/74">Issue #74</a>, that is, a blank
screen.</p>
<p>To better understand the motivation behind the Elk Native developers, I tried
the same for one of my apps, with different frameworks. This
<a href="https://github.com/tomayac/cross-platform-software-frameworks">repository</a>
contains the same PWA, <a href="https://svgco.de/">SVGcode</a>, wrapped five times with
different cross platform software frameworks.</p>
<h2 id="running-the-apps" tabindex="-1">Running the apps <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#running-the-apps" aria-hidden="true">π</a></h2>
<p>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.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> run build-svgcode
<span class="token function">npm</span> start</code></pre>
<h2 id="included-frameworks" tabindex="-1">Included frameworks <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#included-frameworks" aria-hidden="true">π</a></h2>
<ul>
<li><a href="https://electronjs.org/">Electron.js</a>
(<a href="https://www.electronjs.org/docs/latest/tutorial/quick-start">"Getting started" guide</a>)</li>
<li><a href="https://nwjs.io/">NW.js</a>
(<a href="https://nwjs.readthedocs.io/en/latest/For%20Users/Getting%20Started/">"Getting started" guide</a>)</li>
<li><a href="https://tauri.app/">Tauri</a>
(<a href="https://tauri.app/v1/guides/getting-started/setup/html-css-js/">"Getting started" guide</a>)</li>
<li><a href="https://neutralino.js.org/">Neutralinojs</a>
(<a href="https://neutralino.js.org/docs/getting-started/your-first-neutralinojs-app/">"Getting started" guide</a>)</li>
<li><a href="https://gluonjs.org/">Gluon</a>
(<a href="https://gluonjs.org/docs/guide/quick-start/">"Getting started" guide</a>)</li>
</ul>
<h2 id="screenshots" tabindex="-1">Screenshots <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#screenshots" aria-hidden="true">π</a></h2>
<ul>
<li>Electron.js
<img src="https://github.com/tomayac/cross-platform-software-frameworks/raw/main/screenshots/svgcode-electron.png" alt="" /></li>
<li>NW.js
<img src="https://github.com/tomayac/cross-platform-software-frameworks/raw/main/screenshots/svgcode-nw_js.png" alt="" /></li>
<li>Tauri
<img src="https://github.com/tomayac/cross-platform-software-frameworks/raw/main/screenshots/svgcode-tauri.png" alt="" /></li>
<li>Neutralinojs
<img src="https://github.com/tomayac/cross-platform-software-frameworks/raw/main/screenshots/svgcode-neutralinojs.png" alt="" /></li>
<li>Gluon
<img src="https://github.com/tomayac/cross-platform-software-frameworks/raw/main/screenshots/svgcode-gluon.png" alt="" /></li>
</ul>
<h2 id="issues" tabindex="-1">Issues <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#issues" aria-hidden="true">π</a></h2>
<blockquote>
<p>β οΈ 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.</p>
</blockquote>
<p>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.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// If `navigator.userAgentData` is available, use it.</span>
<span class="token function">copy</span><span class="token punctuation">(</span>
<span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>
<span class="token keyword">await</span> navigator<span class="token punctuation">.</span>userAgentData<span class="token punctuation">.</span><span class="token function">getHighEntropyValues</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
<span class="token string">'architecture'</span><span class="token punctuation">,</span>
<span class="token string">'bitness'</span><span class="token punctuation">,</span>
<span class="token string">'model'</span><span class="token punctuation">,</span>
<span class="token string">'platformVersion'</span><span class="token punctuation">,</span>
<span class="token string">'uaFullVersion'</span><span class="token punctuation">,</span>
<span class="token string">'fullVersionList'</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token keyword">null</span><span class="token punctuation">,</span>
<span class="token number">2</span>
<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Else use the user agent.</span>
<span class="token function">copy</span><span class="token punctuation">(</span>navigator<span class="token punctuation">.</span>userAgent<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="electron-js" tabindex="-1">Electron.js <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#electron-js" aria-hidden="true">π</a></h3>
<p>Clicking the <strong>Copy SVG</strong> button causes an
<code>Uncaught (in promise) ReferenceError: Cannot access 'P' before initialization.</code>
error.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
<span class="token property">"architecture"</span><span class="token operator">:</span> <span class="token string">"arm"</span><span class="token punctuation">,</span>
<span class="token property">"bitness"</span><span class="token operator">:</span> <span class="token string">"64"</span><span class="token punctuation">,</span>
<span class="token property">"brands"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Not A(Brand"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"24"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Chromium"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"fullVersionList"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Not A(Brand"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"24.0.0.0"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Chromium"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.100"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"mobile"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"model"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
<span class="token property">"platform"</span><span class="token operator">:</span> <span class="token string">"macOS"</span><span class="token punctuation">,</span>
<span class="token property">"platformVersion"</span><span class="token operator">:</span> <span class="token string">"13.3.0"</span><span class="token punctuation">,</span>
<span class="token property">"uaFullVersion"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.100"</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="nw-js" tabindex="-1">NW.js <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#nw-js" aria-hidden="true">π</a></h3>
<p>Clicking the <strong>Copy SVG</strong> button causes an
<code>Uncaught (in promise) ReferenceError: Cannot access 'P' before initialization.</code>
error.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
<span class="token property">"architecture"</span><span class="token operator">:</span> <span class="token string">"arm"</span><span class="token punctuation">,</span>
<span class="token property">"bitness"</span><span class="token operator">:</span> <span class="token string">"64"</span><span class="token punctuation">,</span>
<span class="token property">"brands"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Not A(Brand"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"24"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Chromium"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"fullVersionList"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Not A(Brand"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"24.0.0.0"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Chromium"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.97"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"mobile"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"model"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
<span class="token property">"platform"</span><span class="token operator">:</span> <span class="token string">"macOS"</span><span class="token punctuation">,</span>
<span class="token property">"platformVersion"</span><span class="token operator">:</span> <span class="token string">"13.3.0"</span><span class="token punctuation">,</span>
<span class="token property">"uaFullVersion"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.97"</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="tauri" tabindex="-1">Tauri <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#tauri" aria-hidden="true">π</a></h3>
<p>Clicking the <strong>Save SVG</strong> button does nothing.</p>
<pre class="language-bash"><code class="language-bash">Mozilla/5.0 <span class="token punctuation">(</span>Macintosh<span class="token punctuation">;</span> Intel Mac OS X 10_15_7<span class="token punctuation">)</span> AppleWebKit/605.1.15 <span class="token punctuation">(</span>KHTML, like Gecko<span class="token punctuation">)</span></code></pre>
<h3 id="neutralinojs" tabindex="-1">Neutralinojs <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#neutralinojs" aria-hidden="true">π</a></h3>
<p>Clicking the <strong>Open Image</strong> button does nothing. Clicking the <strong>Save SVG</strong>
button does nothing.</p>
<pre class="language-bash"><code class="language-bash">Mozilla/5.0 <span class="token punctuation">(</span>Macintosh<span class="token punctuation">;</span> Intel Mac OS X 10_15_7<span class="token punctuation">)</span> AppleWebKit/605.1.15 <span class="token punctuation">(</span>KHTML, like Gecko<span class="token punctuation">)</span></code></pre>
<h3 id="gluon" tabindex="-1">Gluon <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#gluon" aria-hidden="true">π</a></h3>
<p>Fails with a
<code>RangeError Failed to execute 'createImageBitmap' on 'Window': The crop rect width is 0.</code>.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
<span class="token property">"architecture"</span><span class="token operator">:</span> <span class="token string">"arm"</span><span class="token punctuation">,</span>
<span class="token property">"bitness"</span><span class="token operator">:</span> <span class="token string">"64"</span><span class="token punctuation">,</span>
<span class="token property">"brands"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Chromium"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Not A(Brand"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"24"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Google Chrome"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"fullVersionList"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Chromium"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.177"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Not A(Brand"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"24.0.0.0"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"brand"</span><span class="token operator">:</span> <span class="token string">"Google Chrome"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.177"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"mobile"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"model"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
<span class="token property">"platform"</span><span class="token operator">:</span> <span class="token string">"macOS"</span><span class="token punctuation">,</span>
<span class="token property">"platformVersion"</span><span class="token operator">:</span> <span class="token string">"13.3.0"</span><span class="token punctuation">,</span>
<span class="token property">"uaFullVersion"</span><span class="token operator">:</span> <span class="token string">"110.0.5481.177"</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="building-the-apps-incomplete" tabindex="-1">Building the apps (incomplete) <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#building-the-apps-incomplete" aria-hidden="true">π</a></h2>
<p>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
<code>electron-forge make</code>, I ended up with a 332,1Β MB executable called
<code>svgcode-electron.app</code> that only showed a white screen, despite the
<code>electron-forge start</code> development app working mostly fine.</p>
<p><img src="https://github.com/tomayac/cross-platform-software-frameworks/raw/main/screenshots/svgcode-electron-app.png" alt="" /></p>
<p>To build the apps, run the following command in each subfolder. (So far I have
only worked on Electron.js.)</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> run build</code></pre>
<p>I didn't even look into the signing part, which is required for proper
distribution.</p>
<h2 id="conclusions" tabindex="-1">Conclusions <a class="direct-link" href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/#conclusions" aria-hidden="true">π</a></h2>
<p>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 <a href="https://svgco.de/">svgco.de</a>,
clicking <strong>Install</strong>, 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
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Window_Controls_Overlay_API">Window Controls Overlay</a>
or <a href="https://developer.chrome.com/en/articles/file-handling/">File Handling</a> 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.</p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2023%2F02%2F23%2Fcross-platform-software-frameworks%2F&dp=%2F2023%2F02%2F23%2Fcross-platform-software-frameworks%2F&dt=Cross%20platform%20software%20frameworks" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/">https://blog.tomayac.com/2023/02/23/cross-platform-software-frameworks/</a>.
</p>
iOS Continuity Camera not working in Chrome
2023-02-16T11:28:03Z
https://blog.tomayac.com/2023/02/16/ios-continuity-camera-not-working-in-chrome/
<p>I'm a big fan of the macOS
<a href="https://support.apple.com/en-us/HT213244">Continuity Camera</a> 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.</p>
<p>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
<a href="https://www.reddit.com/user/bonnerup/">bonnerup</a> filed feedback (<code>FB11639588</code>)
about the problem with Apple, and got the following response (<em>sic</em>):</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>Since this is not documented anywhere apart from a
<a href="https://www.reddit.com/r/MacOSBeta/comments/y4h6ww/continuity_camera_in_browsers_response_from_apple/">Reddit post</a>,
I thought I'd share it here as well. Once I put my phone in the "magic pose", it
worked just fine.</p>
<p>My iPhone model doesn't support all video effects yet, but
<a href="https://support.apple.com/en-us/HT213244#centerstage">Center Stage</a> works and
is pretty cool. It makes it look like if the camera would move and follow me. I
also use
<a href="https://support.apple.com/en-us/HT213244#:~:text=or%20Close%20Window.-,Mic%20modes,-Click%20Control%20Center">Voice Isolation</a>,
which helps in noisy environments.</p>
<p><img src="https://blog.tomayac.com/images/continuity-camera.png" alt="iOS Continuity Camera with applied Center Stage video effect and Voice Isolation mic mode." /></p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2023%2F02%2F16%2Fios-continuity-camera-not-working-in-chrome%2F&dp=%2F2023%2F02%2F16%2Fios-continuity-camera-not-working-in-chrome%2F&dt=iOS%20Continuity%20Camera%20not%20working%20in%20Chrome" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2023/02/16/ios-continuity-camera-not-working-in-chrome/">https://blog.tomayac.com/2023/02/16/ios-continuity-camera-not-working-in-chrome/</a>.
</p>
Not everyone's currently building for the Web, but probably more people should
2023-01-16T09:27:32Z
https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/
<p>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 <em>in addition to</em> platform-specific apps.
Alternatively, you can choose a cross-platform framework such as
<a href="https://www.electronjs.org/">Electron.js</a> or
<a href="https://ionicframework.com/">Ionic</a> 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 <em>also</em> build for the Web, apart from building
platform-specific apps.</p>
<h2 id="beacon-cases-that-demonstrate-the-web-s-abilities" tabindex="-1">Beacon cases that demonstrate the Web's abilities <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#beacon-cases-that-demonstrate-the-web-s-abilities" aria-hidden="true">π</a></h2>
<h3 id="photoshop" tabindex="-1">Photoshop <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#photoshop" aria-hidden="true">π</a></h3>
<p>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 <a href="https://web.dev/ps-on-the-web/">Photoshop</a>,
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.</p>
<figure>
<img src="https://blog.tomayac.com/images/photoshop.avif" ,="" alt="Adobe Photoshop running in the browser." width="800" height="500" />
<figcaption>
Photoshop on the Web
</figcaption>
</figure>
<h3 id="visual-studio-code" tabindex="-1">Visual Studio Code <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#visual-studio-code" aria-hidden="true">π</a></h3>
<p>Similarly, Microsoft has launched
<a href="https://code.visualstudio.com/blogs/2021/10/20/vscode-dev">Visual Studio Code on the Web</a>,
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.</p>
<figure>
<img src="https://blog.tomayac.com/images/vscode.avif" ,="" alt="Microsoft VS Code running in the browser." width="800" height="483" />
<figcaption>
VS Code on the Web
</figcaption>
</figure>
<h3 id="twitter" tabindex="-1">Twitter <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#twitter" aria-hidden="true">π</a></h3>
<p>Lastly Twitterβwhose progressive Web app (PWA) is
<a href="https://www.thurrott.com/cloud/social/150171/twitter-lite-now-adapts-larger-screens#:~:text=probably%20the%20best%20mainstream%20progressive%20web%20app">largely seen</a>
as <em>probably the best mainstream Progressive Web App</em>βhas
<a href="https://blog.twitter.com/engineering/en_us/topics/insights/2019/twitter-for-mac-is-coming-back#:~:text=This%20led%20to%20our%20Responsive%20Web%20codebase%20being%20the%20spearhead%20for%20all%20platforms%20via%20web%20browsers">used</a>
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 <em>the</em> Twitter experience that you get when you
<a href="https://blog.twitter.com/en_us/topics/product/2018/a-new-twitter-experience-on-windows">install</a>
the app from the Microsoft Store.</p>
<figure>
<img src="https://blog.tomayac.com/images/twitter.avif" ,="" alt="Microsoft Store showing the Twitter app." width="800" height="568" />
<figcaption>
Twitter in the Microsoft Store
</figcaption>
</figure>
<h2 id="linkability-and-universality-the-web-s-super-powers" tabindex="-1">Linkability and universality: the Web's super powers <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#linkability-and-universality-the-web-s-super-powers" aria-hidden="true">π</a></h2>
<p>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.</p>
<p>As Google's Thomas Nattestad
<a href="https://web.dev/ps-on-the-web/#:~:text=the%20simple%20power%20of%20a%20url%20is%20that%20anyone%20can%20click%20it%20and%20instantly%20access%20it.%20all%20you%20need%20is%20a%20browser.%20there%20is%20no%20need%20to%20install%20an%20application%20or%20worry%20about%20what%20operating%20system%20you%20are%20running%20on.">put it</a>:
<em>"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"</em>.
<a href="https://code.visualstudio.com/blogs/2021/10/20/vscode-dev#:~:text=You%20can%20make%20quick%20edits%2C%20review%20PRs%2C%20and%20Continue%20on%20to%20a%20local%20clone">According to</a>
Microsoft's <a href="https://twitter.com/chrisdias">Chris Dias</a>, with Visual Studio Code
for the Web, when working with GitHub <em>"you can make quick edits, review PRs,
and continue on to a local clone"</em>. 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
<a href="https://edition.cnn.com/2021/11/09/politics/gosar-anime-video-violence-ocasio-cortez-biden/index.html#:~:text=Ocasio-Cortez%20tweeted%20in%20response%20Monday%20saying%20a%20%22creepy%20member%22%20of%20the%20House%20had%20%22shared%20a%20fantasy%20video%20of%20him%20killing%20me.%22">link to newsworthy tweets</a>,
which <em>means "keeping it quick"</em>
<a href="https://blog.twitter.com/engineering/en_us/topics/infrastructure/2019/progressively-enhancing-desktop-devices#:~:text=%C2%A0-,Keeping%20it%20quick,-With%20all%20the">is core</a>
to ensuring people can get from an article straight into the app, where they can
read or engage with the linked tweet.</p>
<p>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
<a href="https://web.dev/interop-2022/">solid, shared, increasing baseline</a> that all
applications can build upon.</p>
<h3 id="linkability-of-platform-specific-apps" tabindex="-1">Linkability of platform-specific apps <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#linkability-of-platform-specific-apps" aria-hidden="true">π</a></h3>
<p>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
<a href="https://developer.apple.com/ios/universal-links/">Universal Links</a> on iOS (and
on macOS), and <a href="https://developer.android.com/training/app-links/">App Links</a> on
Android. Platform-specific apps alternatively can rely on
<a href="https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app">registered protocol schemes</a>
such as <code>itms-apps:</code> 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.</p>
<h2 id="the-slow-decline-of-interest-in-cross-platform-app-frameworks-and-the-rise-of-flutter" tabindex="-1">The slow decline of interest in cross-platform app frameworks and the rise of Flutter <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#the-slow-decline-of-interest-in-cross-platform-app-frameworks-and-the-rise-of-flutter" aria-hidden="true">π</a></h2>
<p>The Web isn't the only platform that promises <em>"write once, run anywhere"</em>.
Cross-platform frameworks <em>Γ la</em> 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
<a href="https://www.electronjs.org/">Electron.js</a> and <a href="https://nwjs.io/">NW.js</a>, and
mobile app frameworks such as <a href="https://cordova.apache.org/">Cordova</a> or
<a href="https://reactnative.dev/">React Native</a>; while at the same time there is an
undeniable increase of interest in <a href="https://flutter.dev/">Flutter</a>.</p>
<h3 id="google-trends-stats" tabindex="-1">Google Trends stats <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#google-trends-stats" aria-hidden="true">π</a></h3>
<p>The following
<a href="https://trends.google.com/trends/explore/TIMESERIES/1636457400?hl=en-US&tz=-60&cat=5&date=today+5-y&q=%2Fg%2F11bw_559wr,%2Fg%2F11f11js9bh,%2Fm%2F06znsr5,%2Fg%2F11f03_rzbg,%2Fg%2F11h03gfxy9&sni=3">Google Trends chart</a>
shows the five frameworks side by side. While noting that this chart <em>does</em> show
disambiguated topic trends as detected by Google (as opposed to ambiguous
<a href="https://blog.tomayac.com/2021/11/08/things-mode-and-strings-mode-in-google-trends/">search term trends</a>),
nevertheless it is clearly <em>not</em> an exact science.</p>
<figure>
<div style="height: 425px; width: 100%;">
<iframe src="https://trends.google.com/trends/embed/explore/TIMESERIES?req=%7B%22comparisonItem%22%3A%5B%7B%22keyword%22%3A%22%2Fg%2F11bw_559wr%22%2C%22geo%22%3A%22%22%2C%22time%22%3A%22today%205-y%22%7D%2C%7B%22keyword%22%3A%22%2Fg%2F11f11js9bh%22%2C%22geo%22%3A%22%22%2C%22time%22%3A%22today%205-y%22%7D%2C%7B%22keyword%22%3A%22%2Fm%2F06znsr5%22%2C%22geo%22%3A%22%22%2C%22time%22%3A%22today%205-y%22%7D%2C%7B%22keyword%22%3A%22%2Fg%2F11f03_rzbg%22%2C%22geo%22%3A%22%22%2C%22time%22%3A%22today%205-y%22%7D%2C%7B%22keyword%22%3A%22%2Fg%2F11h03gfxy9%22%2C%22geo%22%3A%22%22%2C%22time%22%3A%22today%205-y%22%7D%5D%2C%22category%22%3A5%2C%22property%22%3A%22%22%7D&tz=-60&forceMobileMode=false&isPreviewMode=true&eq=q%3D%252Fg%252F11bw_559wr%2C%252Fg%252F11f11js9bh%2C%252Fm%252F06znsr5%2C%252Fg%252F11f03_rzbg%2C%252Fg%252F11h03gfxy9%26date%3Dtoday%25205-y%26cat%3D5%23TIMESERIES&hl=enUS" title="Google Trends interest over time for Electron, NW.js, Apache Cordova, Flutter, and React Native." style="height: 100%; width: 100%; border: 0;">
>
</iframe>
</div>
<figcaption>
Google Trends interest over time for Electron, NW.js, Apache Cordova, Flutter, and React Native.
[<a href="https://www.google.com/url?q=https://trends.google.com/trends/embed/explore/TIMESERIES?req%3D%257B%2522comparisonItem%2522%253A%255B%257B%2522keyword%2522%253A%2522%252Fg%252F11bw_559wr%2522%252C%2522geo%2522%253A%2522%2522%252C%2522time%2522%253A%2522today%25205-y%2522%257D%252C%257B%2522keyword%2522%253A%2522%252Fg%252F11f11js9bh%2522%252C%2522geo%2522%253A%2522%2522%252C%2522time%2522%253A%2522today%25205-y%2522%257D%252C%257B%2522keyword%2522%253A%2522%252Fm%252F06znsr5%2522%252C%2522geo%2522%253A%2522%2522%252C%2522time%2522%253A%2522today%25205-y%2522%257D%252C%257B%2522keyword%2522%253A%2522%252Fg%252F11f03_rzbg%2522%252C%2522geo%2522%253A%2522%2522%252C%2522time%2522%253A%2522today%25205-y%2522%257D%252C%257B%2522keyword%2522%253A%2522%252Fg%252F11h03gfxy9%2522%252C%2522geo%2522%253A%2522%2522%252C%2522time%2522%253A%2522today%25205-y%2522%257D%255D%252C%2522category%2522%253A5%252C%2522property%2522%253A%2522%2522%257D%26tz%3D-60%26forceMobileMode%3Dfalse%26isPreviewMode%3Dtrue%26eq%3Dq%253D%25252Fg%25252F11bw_559wr%252C%25252Fg%25252F11f11js9bh%252C%25252Fm%25252F06znsr5%252C%25252Fg%25252F11f03_rzbg%252C%25252Fg%25252F11h03gfxy9%2526date%253Dtoday%2525205-y%2526cat%253D5%2523TIMESERIES%26hl%3DenUS&sa=D&source=docs&ust=1656333876287238&usg=AOvVaw1QYdCACMEsvrJP2BsAbyBT">Source</a>]
</figcaption>
</figure>
<h3 id="statista-stats" tabindex="-1">Statista stats <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#statista-stats" aria-hidden="true">π</a></h3>
<p>This trend is backed by
<a href="https://www.statista.com/statistics/869224/worldwide-software-developer-working-hours/">Statista stats</a>,
according to which Flutter has passed React Native as the most popular
framework.</p>
<figure>
<img src="https://blog.tomayac.com/images/statista.avif" ,="" alt="Flutter is the most popular cross-platform mobile framework used by global developers, according to a 2021 developer survey. Based on the survey, 42 percent of software developers used Flutter. On the whole, roughly one third of mobile developers use cross-platform technologies or frameworks; the rest of mobile developers use native tools." width="800" height="594" />
<figcaption>
Cross-platform mobile frameworks used by software developers worldwide from 2019 to 2021.
[<a href="https://www.statista.com/statistics/869224/worldwide-software-developer-working-hours/">Source</a>]
</figcaption>
</figure>
<h3 id="stackoverflow-stats" tabindex="-1">StackOverflow stats <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#stackoverflow-stats" aria-hidden="true">π</a></h3>
<p><a href="https://insights.stackoverflow.com/trends?tags=flutter%2Creact-native%2Celectron%2Cionic-framework">StackOverflow statistics</a>
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.</p>
<figure>
<img style="font-face: system-ui, sans-serif; background-color: #fff;" src="https://blog.tomayac.com/images/stackoverflow.svg" ,="" alt="How technologies have trended over time based on use of their tags since 2008, when Stack Overflow was founded. Comparing the tags flutter, react-native, electron, and ionic-framework. Flutter's curve increases the steepest, with React Native being the flattening second and Ionic and Electron the flattening 'also ran'." width="800" height="492" />
<figcaption>
StackOverflow statistics on tag usage.
[<a href="https://insights.stackoverflow.com/trends?tags=flutter%2Creact-native%2Celectron%2Cionic-framework">Source</a>]
</figcaption>
</figure>
<h2 id="shouldn-t-everybody-be-building-for-the-web-then" tabindex="-1">Shouldn't everybody be building for the Web, then? <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#shouldn-t-everybody-be-building-for-the-web-then" aria-hidden="true">π</a></h2>
<p>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:</p>
<ul>
<li><span id="research-question-1">Research question β :</span>
<a href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#why-do-people-not-fully-bet-on-pwa">Why do people not fully bet on PWA?</a></li>
<li><span id="research-question-2">Research question β‘:</span>
<a href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#why-is-flutter-so-popular">Why is Flutter so popular?</a></li>
</ul>
<h3 id="why-do-people-not-fully-bet-on-pwa" tabindex="-1">Why do people not fully bet on PWA? <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#why-do-people-not-fully-bet-on-pwa" aria-hidden="true">π</a></h3>
<p>For <a href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#research-question-1">research question β </a>, the answer is complex and
manifold. I want to break it down into different sub-categories.</p>
<h4 id="missing-capabilities-aka-the-app-gap" tabindex="-1">Missing capabilities: aka the app gap <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#missing-capabilities-aka-the-app-gap" aria-hidden="true">π</a></h4>
<p>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.</p>
<p>First, it is impossible, even with an installed PWA, to obey the macOS user
interface paradigm of having the
<a href="https://developer.apple.com/design/human-interface-guidelines/macos/menus/menu-bar-menus/">app menu at the top of the screen</a>.
It can easily be achieved with frameworks such as Electron.js via the
<code><a href="https://www.electronjs.org/docs/latest/api/menu">Menu</a></code> class. (On
the Web, the next best thing is
<a href="https://web.dev/window-controls-overlay/">Window Controls Overlay</a>; getting
support for app menus is tracked as <a href="https://crbug.com/1295253">crbug/1295253</a>.)
Another example is in-app purchases on macOS that can be handled via Electron's
<code><a href="https://www.electronjs.org/docs/latest/tutorial/in-app-purchases">inAppPurchase()</a></code>
method. (On the Web, the next best thing is the
<a href="https://developer.chrome.com/docs/android/trusted-web-activity/receive-payments-play-billing/">Digital Goods API</a>,
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
<a href="https://www.electronjs.org/docs/latest/api/auto-updater#windows">installers</a>
and make installed applications
<a href="https://www.electronjs.org/docs/latest/api/auto-updater">update automatically</a>.
(On the Web, <a href="https://web.dev/web-bundles/">Web Bundles</a> 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.</p>
<h5>How big a challenge is this?</h5>
<p>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
<a href="https://web.dev/progressively-enhance-your-pwa/">Progressively enhance your Progressive Web App</a>.</p>
<h4 id="discoverability-in-stores" tabindex="-1">Discoverability in stores <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#discoverability-in-stores" aria-hidden="true">π</a></h4>
<p>Collectively, we have educated users to look for apps in app stores. Some stores
such as the
<a href="https://developer.microsoft.com/en-us/microsoft-store/pwa/">Windows Store</a> and
the
<a href="https://developer.chrome.com/docs/android/trusted-web-activity/quick-start/">Android Play Store</a>
have started to embrace (wrapped!) PWAs (optionally
<a href="https://chromeos.dev/en/publish/pwa-in-play#chrome-os-only">limited to ChromeOS</a>),
and offer graphical user interface tools like
<a href="https://www.pwabuilder.com/">PWABuilder</a> (internally based on the command line
tool <a href="https://github.com/GoogleChromeLabs/bubblewrap">bubblewrap</a>) for
submitting applications. Meanwhile, on other stores such as Apple's App Store,
the situation is different and less welcoming, and apps
<a href="https://blog.pwabuilder.com/posts/publish-your-pwa-to-the-ios-app-store/">may or may not</a>
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
<a href="https://developer.oculus.com/pwa/">Oculus Store</a>.</p>
<h5>How big a challenge is this?</h5>
<p>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
<a href="https://www.thinkwithgoogle.com/_qs/documents/331/how-users-discover-use-apps-google-research.pdf">research done by Google</a>.</p>
<h4 id="monetization-of-apps-and-in-app-content" tabindex="-1">Monetization of apps and in-app content <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#monetization-of-apps-and-in-app-content" aria-hidden="true">π</a></h4>
<p>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
<a href="https://developer.chrome.com/docs/android/trusted-web-activity/">Trusted Web Activities</a>
and delivered through the Google Play Store, developers can now use the
<a href="https://developer.mozilla.org/docs/Web/API/Payment_Request_API">Payment Request API</a>
and the new
<a href="https://developer.chrome.com/docs/android/trusted-web-activity/receive-payments-play-billing/">Digital Goods API</a>
to integrate with Google Play Billing.</p>
<h5>How big a challenge is this?</h5>
<p>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 <em>are</em> published to app
stores even ask their users to make the purchase off-store. One well-known
example is
<a href="https://9to5mac.com/2022/07/22/netflix-external-subscription-ios/">Netflix with their external subscriptions</a>.</p>
<h4 id="hiring-or-retraining-developers" tabindex="-1">Hiring or retraining developers <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#hiring-or-retraining-developers" aria-hidden="true">π</a></h4>
<p>From personal experience through talking to many of Google's partners, a lot of
<a href="https://medium.com/javascript-scene/why-hiring-is-so-hard-in-tech-c462c3230017">companies struggle with hiring great Web developers</a>.
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.</p>
<h5>How big a challenge is this?</h5>
<p>In the current economic situation, hiring <em>any</em> kind of developer is
difficult. Hiring someone with Web development skills is, in comparison to other
platform-specific coding skills, still easier
<a href="https://insights.stackoverflow.com/survey/2021#most-popular-technologies-language-prof">according to StackOverflow surveys</a>,
which (in part) also explains the popularity of app frameworks such as React
Native, Ionic, Flutter, and others that are based on Web technologies.</p>
<h4 id="existing-apps-legacy-and-migrating-the-user-base" tabindex="-1">Existing apps legacy (and migrating the user base) <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#existing-apps-legacy-and-migrating-the-user-base" aria-hidden="true">π</a></h4>
<p>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
<a href="https://www.glossy.co/ecommerce/gone-fishin-patagonia-bids-farewell-to-mobile-app/">happen</a>.</p>
<h5>How big a challenge is this?</h5>
<p>Vanity is vanity, but once you have set up new, potentially more meaningful,
tracking metrics than number of app installs such as
<a href="https://web.dev/betty-crocker/#results">increase of indicators of
purchase intent</a>, you can start tracking those instead.</p>
<h4 id="compatibility-with-relevant-browsers" tabindex="-1">Compatibility with relevant browsers <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#compatibility-with-relevant-browsers" aria-hidden="true">π</a></h4>
<p>Web compatibility is still the
<a href="https://insights.developer.mozilla.org/reports/mdn-web-developer-needs-assessment-2020.html#needs-assessment-top-ten-needs">main issue</a>
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
<a href="https://webcompat.com/">webcompat.com</a> collect user-submitted browser bugs and
invite interested developers to fix them. Mozilla operates a
<a href="https://github.com/mozilla-extensions/webcompat-addon">repository</a> with
interventions and patches to enable individual sites to run successfully in
Firefox. WebKit maintains a
<a href="https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/page/Quirks.cpp">quirks list</a>
and
<a href="https://jobs.apple.com/search?search=%22WebKit%20Web%20Compatibility%20Analyst%22&sort=relevance">hires WebKit Web Compatibility Analysts</a>.</p>
<h5>How big a challenge is this?</h5>
<p>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
<a href="https://web.dev/progressively-enhance-your-pwa/">Progressively enhance your Progressive Web App</a>.</p>
<h4 id="tools-and-framework-support" tabindex="-1">Tools and framework support <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#tools-and-framework-support" aria-hidden="true">π</a></h4>
<p>As well as browser compatibility, Mozilla's
<a href="https://insights.developer.mozilla.org/reports/mdn-web-developer-needs-assessment-2020.html#needs-assessment-top-ten-needs">2020 developer survey</a>
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.</p>
<h5>How big a challenge is this?</h5>
<p>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
<a href="https://almanac.httparchive.org/en/2021/javascript#libraries-and-frameworks">most
popular framework</a>, is the other.</p>
<h4 id="security-or-rather-the-theater-of-security-with-certificate-pinning" tabindex="-1">Security (or rather, the theater of security with certificate pinning) <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#security-or-rather-the-theater-of-security-with-certificate-pinning" aria-hidden="true">π</a></h4>
<p>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
<a href="https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/">circumvent pinned certificates</a>
on all platforms, so it is mostly the theater of security at this point.</p>
<h5>How big a challenge is this?</h5>
<p>As outlined
<a href="https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/">earlier</a>,
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.</p>
<h4 id="performance-limitations" tabindex="-1">Performance limitations <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#performance-limitations" aria-hidden="true">π</a></h4>
<p>Web applications have seen impressive performance improvements thanks to
advanced technologies such as <a href="https://webassembly.org/">WebAssembly</a> (including
<a href="https://v8.dev/features/simd">SIMD</a>),
<a href="https://gpuweb.github.io/gpuweb/">WebGPU</a>, 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 <em>actually</em> matters may be limited). With even high-performance
audio-editing tools like <a href="https://www.soundtrap.com/">Soundtrap</a> (thanks to the
<a href="https://developer.mozilla.org/docs/Web/API/Web_Audio_API">Web Audio API</a> and
<a href="https://developer.mozilla.org/docs/Web/API/AudioWorklet">AudioWorklet</a>),
interactive development environments like
<a href="https://jupyter.org/try">Jupyter Notebook</a>, and graphics-editing tools like
<a href="https://www.figma.com/">Figma</a> (thanks to WebAssembly), and of course
graphics-intensive games like <a href="http://www.quakejs.com/">Quake</a> (thanks to
<a href="https://developer.mozilla.org/de/docs/Web/API/WebGL_API">WebGL</a> and
<a href="https://gpuweb.github.io/gpuweb/">WebGPU</a> in the future), the boundaries are
being pushed at a rapid rate.</p>
<h5>How big a challenge is this?</h5>
<p>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
<a href="https://developer.chrome.com/docs/web-platform/view-transitions/">View Transitions API</a>
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
<a href="https://developer.apple.com/support/required-device-capabilities/">minimum required device capabilities</a>.</p>
<h3 id="why-is-flutter-so-popular" tabindex="-1">Why is Flutter so popular? <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#why-is-flutter-so-popular" aria-hidden="true">π</a></h3>
<p>For <a href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#research-question-2">research question β‘</a>, one possible explanation is
that it is a
<a href="https://flutter.dev/#:~:text=Flutter%20is%20Google%27s%20UI%20toolkit%20for%20building%20beautiful%2C%20natively%20compiled%20applications%20for%20mobile%2C%20web%2C%20desktop%2C%20and%20embedded%20devices%20from%20a%20single%20codebase.">Google-backed</a>
toolkit for <em>"building beautiful, natively compiled applications for mobile,
Web, desktop, and embedded devices from a single codebase"</em>. If even Google, as
the maker of Android, trusts Flutter enough to build some of its strategic apps
with it, such as
<a href="https://stadia.dev/blog/how-flutter-helped-us-make-stadia-controller-setup-better-for-users/">Stadia</a>
(RIP) and <a href="https://flutter.dev/showcase">Google Ads</a> for both Android and iOS,
and
<a href="https://developers.googleblog.com/2019/05/Flutter-io19.html">Assistant apps</a> 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.)</p>
<p>An argument that is frequently brought up for Flutter is
<a href="https://flutter.dev/docs/development/tools/hot-reload">hot reloading</a>. On the
backend, Flutter also
<a href="https://firebase.google.com/docs/flutter/setup?platform=ios">plays well with Firebase</a>,
so apps are easy to scale. Important for Web, and as Flutter was initially
criticized for rendering everything inaccessibly onto a <code><canvas></code>, the
framework now has
<a href="https://flutter.dev/docs/development/tools/web-renderers">two different Web renderers</a>
it can automatically choose from:</p>
<ul>
<li><strong>HTML renderer:</strong> This renderer uses a combination of HTML elements, CSS,
canvas elements, and SVG elements, and has a smaller download size.</li>
<li><strong>CanvasKit renderer:</strong> 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.</li>
</ul>
<p>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.</p>
<p>Flutter relies on
<a href="https://docs.flutter.dev/development/ui/widgets">a library of pre-made widgets</a>
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 <a href="https://skia.org/">Skia</a> 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.)</p>
<p>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.</p>
<p>Flutterβs <a href="https://flutter.dev/docs">documentation</a> is generally recognized as
best in class and its <a href="https://docs.flutter.dev/cookbook">cookbook application</a>
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.</p>
<figure>
<img src="https://blog.tomayac.com/images/flutter.avif" ,="" alt="Blue cartoon bird." width="800" height="450" />
<figcaption>Dash, the mascot for the Dart language and the Flutter framework.</figcaption>
</figure>
<h2 id="conclusions" tabindex="-1">Conclusions <a class="direct-link" href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/#conclusions" aria-hidden="true">π</a></h2>
<p>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 <em>not</em> 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:
<em>"Not everyone's currently building for the Web, but probably more people
should"</em>. In my humble opinion.</p>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2023%2F01%2F16%2Fwhy-not-everyones-building-for-the-web-yet-but-why-potentially-they-should%2F&dp=%2F2023%2F01%2F16%2Fwhy-not-everyones-building-for-the-web-yet-but-why-potentially-they-should%2F&dt=Not%20everyone's%20currently%20building%20for%20the%20Web%2C%20but%20probably%20more%20people%20should" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/">https://blog.tomayac.com/2023/01/16/why-not-everyones-building-for-the-web-yet-but-why-potentially-they-should/</a>.
</p>
Project Fugu π‘ on the JS party podcast
2022-12-05T14:23:34Z
https://blog.tomayac.com/2022/12/05/project-fugu-on-the-js-party-podcast/
<p>I had the honor of being interviewed on the
<a href="https://changelog.com/jsparty">JS Party podcast</a> and chat about Project Fugu
π‘. Thanks to the hosts, <a href="https://twitter.com/nomadtechie">Amal Hussein</a> and
<a href="https://t.co/DZ4ioWAWMX">Nick Nisi</a>, for the interesting questions. Here's the
episode for your listening pleasure.</p>
<iframe src="https://changelog.com/jsparty/254/embed" scrolling="no" frameborder="no" height="220" width="100%"></iframe>
<p>
<img alt="Thomas Steiner" width="32" height="32" src="https://blog.tomayac.com/feed.php?dl=https%3A%2F%2Fblog.tomayac.com%2F2022%2F12%2F05%2Fproject-fugu-on-the-js-party-podcast%2F&dp=%2F2022%2F12%2F05%2Fproject-fugu-on-the-js-party-podcast%2F&dt=Project%20Fugu%20%F0%9F%90%A1%20on%20the%20JS%20party%20podcast" alt="">
<br/>This post appeared first on <a href="https://blog.tomayac.com/2022/12/05/project-fugu-on-the-js-party-podcast/">https://blog.tomayac.com/2022/12/05/project-fugu-on-the-js-party-podcast/</a>.
</p>