<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Toni Engelhardt</title>
    <description>The latest articles on DEV Community by Toni Engelhardt (@toniengelhardt).</description>
    <link>https://dev.to/toniengelhardt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F612891%2Fbdd9245d-a0a5-44c0-8cbb-b645e5d72c24.jpeg</url>
      <title>DEV Community: Toni Engelhardt</title>
      <link>https://dev.to/toniengelhardt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/toniengelhardt"/>
    <language>en</language>
    <item>
      <title>Which WebAPIs are supported on this device in this browser?</title>
      <dc:creator>Toni Engelhardt</dc:creator>
      <pubDate>Thu, 27 Oct 2022 16:05:15 +0000</pubDate>
      <link>https://dev.to/toniengelhardt/which-webapis-are-supported-on-this-device-in-this-browser-4ol7</link>
      <guid>https://dev.to/toniengelhardt/which-webapis-are-supported-on-this-device-in-this-browser-4ol7</guid>
      <description>&lt;p&gt;I had trouble finding this out while working on two side project, both PWAs, &lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt; and &lt;a href="https://repo-tracker.com"&gt;RepoTracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I ended up adding developer-only pages to each app, checking and displaying the status of the WebAPIs that I wanted to use and testing it in different browsers, I realized that is stupid. Better to have a tool that can do that independently of my apps without the hassle.&lt;/p&gt;

&lt;p&gt;A few hours later &lt;a href="https://webapicheck.com"&gt;webapicheck.com&lt;/a&gt; was up and running. Atm there are only a couple dozen APIs that get checked but I'm adding more as we speak. &lt;/p&gt;

&lt;p&gt;It's ridiculously easy to use. Just open &lt;a href="https://webapicheck.com"&gt;the page&lt;/a&gt; on the device and with the browser you want to check and you get an instant visual overview of the APIs that are supported/not supported and whether or not they are in experimental stage. Selected APIs even have a quick test with which you can try the APIs and play around at the click of a button.&lt;/p&gt;

&lt;p&gt;If you're building modern web apps, try it out, would love to get some feedback.&lt;/p&gt;

&lt;p&gt;🙏🏽 ✌🏽 &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webapi</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Let’s build a Native(-like) Web App (NWA)</title>
      <dc:creator>Toni Engelhardt</dc:creator>
      <pubDate>Tue, 27 Sep 2022 21:14:50 +0000</pubDate>
      <link>https://dev.to/toniengelhardt/lets-build-a-native-like-web-app-nwa-597n</link>
      <guid>https://dev.to/toniengelhardt/lets-build-a-native-like-web-app-nwa-597n</guid>
      <description>&lt;p&gt;…and with that, I mean a web app that works and feels exactly like a native app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why, what’s wrong with native apps?
&lt;/h2&gt;

&lt;p&gt;Let’s say you come up with a great concept for an app or service, e.g. in my case, a &lt;a href="https://journalisticapp.com/"&gt;minimalistic micro journaling app&lt;/a&gt;. You naturally want it to be available to as many users as possible, no matter where they live and which device(s) they choose to have on their desk, wrist, and/or in their pocket.&lt;/p&gt;

&lt;p&gt;For a decent-size corporation that is no big deal, just let your product team come up with a design and hire a bunch of Android-, iOS-, and web devs to implement a version for each platform (3 in total). But for a small organization or an &lt;a href="https://rameerez.com/what-is-indie-hacking/"&gt;indie hacker&lt;/a&gt; that is not an option, you just don’t have the resources to build and maintain three apps.&lt;/p&gt;

&lt;p&gt;Well, there are cross-platform solutions out there. The usual suspects are React Native, Ionic, and Flutter. They are all great and give you access to native device APIs. React Native and Ionic even allow you to use the web stack (HTML, JS/JSX, CSS) and frameworks like React or Vue to build your app fast.&lt;/p&gt;

&lt;p&gt;(Thanks to &lt;a href="https://twitter.com/danielcroe"&gt;Daniel Roe&lt;/a&gt;, using Nuxt will soon also be an option with &lt;a href="https://ionic.roe.dev/"&gt;nuxt/ionic&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rTYJrQTH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8x6gvzk11zc7ycaas4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rTYJrQTH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8x6gvzk11zc7ycaas4s.png" alt="React Native vs Ionic vs Flutter" width="768" height="300"&gt;&lt;/a&gt; &lt;em&gt;Image from &lt;a href="https://enappd.com/blog/react-native-vs-ionic-vs-flutter/91/"&gt;enappd&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nice, but they all share one problem: the app still needs to be packaged (several times), deployed to the web, and submitted to the respective stores of Apple, Google, and Microsoft.&lt;/p&gt;

&lt;p&gt;This is annoying because updates to your app will be delayed by the review processes of each store as well as by users just deciding to not update their apps for ages. Your backend/API, therefore, has to be able, in theory, to work with every version of your app that ever existed. Meee…&lt;/p&gt;

&lt;p&gt;Additionally, you are forced to implement multiple payment solutions (including accounting!) according to store policies (3 in this case, plus 1 for the web). And what if you want to accept &lt;a href="https://lightning.network/"&gt;Lightning&lt;/a&gt; payments for example?&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Progressive Web Apps (PWAs)?
&lt;/h2&gt;

&lt;p&gt;Progressive Web Apps (PWAs) are great and you can even publish them — with limitations — to most of the app stores out there via tools like &lt;a href="https://github.com/GoogleChromeLabs/bubblewrap"&gt;bubblewrap&lt;/a&gt; or &lt;a href="https://www.pwabuilder.com/"&gt;PWA Builder&lt;/a&gt;. See also Trusted Web Activities (TWAs) and my previous post &lt;a href="https://dev.to/toniengelhardt/publishing-a-progressive-web-app-pwa-on-the-playstore-what-works-and-what-doesn-t-in-2021-38o5"&gt;Publishing a Progressive Web App (PWA) on the PlayStore — What works and what doesn’t (in 2021)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7PUVWpCF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6d2rcripi7ib4ke43ozm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7PUVWpCF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6d2rcripi7ib4ke43ozm.png" alt="PWA feature image" width="800" height="409"&gt;&lt;/a&gt; &lt;em&gt;Image from &lt;a href="https://web.dev/progressive-web-apps/"&gt;web.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But progressive loading and caching are not really what we want when we’re talking about a “native-like” app.&lt;/p&gt;

&lt;p&gt;A native app, once downloaded, works offline. That’s also the premise of a PWA, but a Progressive Web App (as the “P” in the name suggests) will only cache pages and update them when visited. So, the app is not really fully offline capable, but rather online with a fallback.&lt;/p&gt;

&lt;p&gt;This behavior is useful to enhance the experience of web services and there are &lt;a href="https://www.pwastats.com/"&gt;stats to prove it&lt;/a&gt;, but for a lot of use cases, i.a. my journaling app, this will just not work.&lt;/p&gt;

&lt;p&gt;So let’s tweak it a bit…&lt;/p&gt;

&lt;h2&gt;
  
  
  Native Web Apps (NWAs)
&lt;/h2&gt;

&lt;p&gt;What we really want is a PWA with impromtu caching and immediate full-offline support.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WREQDoJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcdedy5ine4q4eluxppf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WREQDoJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcdedy5ine4q4eluxppf.png" alt="NWA logo" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What would it look like?
&lt;/h3&gt;

&lt;p&gt;Let’s look at an idealized concept that would resolve (almost) all of the problems we currently face with native apps as well as PWAs.&lt;/p&gt;

&lt;p&gt;Instead of consulting an app store, you open the homepage of the app that you want to acquire, e.g. &lt;a href="http://www.journalisticapp.com"&gt;www.journalisticapp.com&lt;/a&gt;. There are two options here, either you are prompted with an install banner à la PWA or there is an install button triggering the installation manually. Ideally, the choice between the two options should be left to the developer.&lt;/p&gt;

&lt;p&gt;Once the install is triggered the app will be downloaded (aka. fully cached) to the user’s device and therefore be available for offline use immediately.&lt;/p&gt;

&lt;p&gt;There are currently no technical hurdles that stop us from implementing such an app, even though there is no out-of-the-box solution and we will have to tinker with workbox and/or service worker scripts.&lt;/p&gt;

&lt;p&gt;However, it will be limited.&lt;/p&gt;

&lt;p&gt;I mean, it is clear that we will have to take a performance hit when relying on a JS codebase that executes on a single thread in the browser as opposed to native Java or Swift code optimized for the chip architecture. But not all apps are performance critical. Those that are will not get around a native implementation any time soon I guess.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what’s missing?
&lt;/h3&gt;

&lt;p&gt;While progress is being made to enable access to more and more device APIs via &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API"&gt;Web APIs&lt;/a&gt;, there are still a lot of critical ones that are missing, e.g. control over the navigation bar color, access to a device’s security chip, or biometric authentication.&lt;/p&gt;

&lt;p&gt;It would also be important for an NWA to have dedicated storage that is not shared with the browser and that can be encrypted and/or blocked, e.g. when the user is not authenticated or has locked the app. As of this writing, the only feasible storage option for the web that ships with the browser is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API"&gt;IndexedDB&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;It would be amazing to have web apps that are indistinguishable from native apps that combine the best of both worlds and that can be downloaded directly from the web. The latter is especially important when contemplating the decentralized future of applications and &lt;a href="https://en.wikipedia.org/wiki/Web3"&gt;web3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In all likelihood, I’ll keep going down the NWA rabbit hole with &lt;a href="https://journalisticapp.com/"&gt;Journalistic&lt;/a&gt; and keep reporting back on how far I’ll get in the quest to build a web app that is indistinguishable from its native counterparts.&lt;/p&gt;

&lt;p&gt;Thanks for reading and have a wonderful day ✌🏽&lt;/p&gt;

</description>
      <category>pwa</category>
      <category>webdev</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Talking Privacy of Journaling Apps</title>
      <dc:creator>Toni Engelhardt</dc:creator>
      <pubDate>Tue, 12 Jul 2022 08:36:05 +0000</pubDate>
      <link>https://dev.to/toniengelhardt/talking-privacy-of-journaling-apps-45dm</link>
      <guid>https://dev.to/toniengelhardt/talking-privacy-of-journaling-apps-45dm</guid>
      <description>&lt;p&gt;&lt;strong&gt;Privacy always comes at a cost. Let's discuss the pros and cons, and UX tradeoffs of different privacy strategies and find out whether or not your journal entries stay private.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;”Will my journal entries stay private?”&lt;/em&gt; is one of the questions I get asked frequently by &lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt; diarists, so I want&lt;br&gt;
to address it in detail in this post.&lt;/p&gt;

&lt;p&gt;In a perfect world, the answer would be &lt;em&gt;”Yes, of course!”&lt;/em&gt;, but in reality, if we are honest, it’s not that simple. First of all, &lt;em&gt;”What do you mean with ‘private’?”&lt;/em&gt;. We will see that it is not so much a matter of technical challenges and&lt;br&gt;
monetization strategies, but more about UX tradeoffs, convenience, and legislation.&lt;/p&gt;

&lt;p&gt;Grab a coffee and get comfy, this is a long one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The White Rhino
&lt;/h2&gt;

&lt;p&gt;It’s always a good idea to lay out the ideal scenario and then try to minimize the concessions that inevitably will have to be made.&lt;/p&gt;

&lt;p&gt;The perfect, privacy-focused journaling app would IMO satisfy – among others – the following requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Only users can access their entries without exception&lt;/li&gt;
&lt;li&gt;Entries are synced instantly across all of the user's devices&lt;/li&gt;
&lt;li&gt;If a device (or all devices) are damaged, lost, or stolen, the entries can be fully recovered&lt;/li&gt;
&lt;li&gt;Recovery should also be possible if a user forgets their password or is not able to provide the required means of authentication (fingerprint, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vnx_V7P0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xoy5wrvmhmkajjlx22sz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vnx_V7P0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xoy5wrvmhmkajjlx22sz.jpg" alt="White Rhino in the wild" width="800" height="529"&gt;&lt;/a&gt; &lt;em&gt;The White Rhino is a metaphor for rare or elusive things.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ll try to make the case that achieving all of the above simultaneously is&lt;br&gt;
(virtually?) impossible and that we have to make some compromises to optimize user happiness.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As a side note... While journaling apps have extremely high privacy requirements, similar challenges apply to almost any web-based app that deals with private user data.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Privacy-enhancing strategies
&lt;/h2&gt;

&lt;p&gt;First, let’s look at some methods that are commonly used to enhance the data&lt;br&gt;
privacy of consumer apps and afterward analyze whether it makes sense to utilize them for our journaling app or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encryption
&lt;/h3&gt;

&lt;p&gt;Using &lt;a href="https://en.wikipedia.org/wiki/Cryptography"&gt;cryptography&lt;/a&gt; to keep data private is an ancient concept, dating back to the medieval ages. But advances in Mathematics and access to great amounts of processing power in every device make it now feasible to seamlessly integrate encryption mechanisms into real-time applications.&lt;/p&gt;

&lt;p&gt;When appropriate algorithms are used it is currently impossible to viably decipher encrypted data. Journal entries stored on cloud servers could therefore be reliably protected from unwanted access when encrypted.&lt;/p&gt;

&lt;p&gt;The Achilles Heel of encryption is the &lt;a href="https://en.wikipedia.org/wiki/Key_(cryptography)"&gt;encryption key&lt;/a&gt;, which has to be taken care of by the user. If the key is lost, the data is gone for good. More on that later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pseudonymity
&lt;/h3&gt;

&lt;p&gt;Pseudonymity refers to the separation of data from identity. For instance, a user could create a brand new email address, which doesn’t hint at their name, and then use it to sign up for the journaling service. If they do not tell anyone about their new virtual identity their data might be accessed, but it cannot be linked to them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9ibHgkfu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2rnsrp75rrr4w81iytq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ibHgkfu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2rnsrp75rrr4w81iytq.jpg" alt="Pseudonymous person holding up the ace of spades" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I guess this is a good opportunity to introduce the two types of private data we have to worry about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personal data&lt;/strong&gt;&lt;br&gt;
People usually do not want strangers to know what they think and what they do at any given time, unless they choose to share it. This is more or less our common &lt;a href="https://en.wikipedia.org/wiki/Privacy"&gt;definition of privacy&lt;/a&gt; and also exactly the kind of information someone would store in a journal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secret data&lt;/strong&gt;&lt;br&gt;
Secret data either holds value in itself, e.g. intellectual property, insider knowledge, etc., or can endanger the safety or property of individuals or groups if exposed. Think credit card information for example.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pseudonymity is only useful (to a certain degree) to protect personal data. Most people would probably not care if their daily logs got leaked if they could be 100% sure, that nobody would ever find out that they wrote them. In practice, this guarantee can never be given and the more personal the data is (think names aso.) the easier it becomes to link it to a person.&lt;/p&gt;

&lt;p&gt;To protect secret data, pseudonymity is useless.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A great example of pseudonymity is the &lt;a href="https://bitcoin.org/bitcoin.pdf"&gt;Bitcoin protocol&lt;/a&gt;. While the protocol leverages strong encryption to protect the network itself, wallet addresses and transactions are pseudonymous and easily accessible for everyone in the public ledger. Since the addresses are only strings of seemingly random letters and numbers, privacy is protected until a wallet is at some point linked to an identity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Local data storage and peer-to-peer sync
&lt;/h3&gt;

&lt;p&gt;The most stringent strategy to enhance privacy is to store data exclusively on devices that the user physically controls and that nobody else has access to, e.g. a mobile phone. This is usually referred to as local data storage.&lt;/p&gt;

&lt;p&gt;To synchronize locally-only stored data between devices they have to communicate directly with each other – peer to peer – without a middleman. Thanks to encryption, this is even possible through public networks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyzing the requirements
&lt;/h2&gt;

&lt;p&gt;Let’s go through the requirements one by one, clearly define why they are important, how they can be implemented, and also where the challenges are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Only users can access their entries without exception
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why is it important?
&lt;/h4&gt;

&lt;p&gt;As mentioned above, users want their entries to be &lt;em&gt;private&lt;/em&gt;, and if third parties can access a user’s journal entries, the user has to trust each of those parties to keep the data private and secure. There is no way around it.&lt;/p&gt;

&lt;p&gt;In general, the more parties have access to your data, the more likely it is that one of those parties is not acting in good faith, accidentally leaks the data, or becomes the target of a hack.&lt;/p&gt;

&lt;p&gt;Depending on the jurisdiction in which the third parties are located, it is also possible that a court can subpoena private data, or that a government agency actively spies on citizens (see for instance the&lt;br&gt;
&lt;a href="https://www.theguardian.com/world/2013/jun/06/nsa-phone-records-verizon-court-order"&gt;Snowden leaks&lt;/a&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  How can it be done?
&lt;/h4&gt;

&lt;p&gt;The two ways to make sure that no one can access a user’s private data, except for the user, are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encryption&lt;/li&gt;
&lt;li&gt;Local data storage only&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What are the problems?
&lt;/h4&gt;

&lt;p&gt;First of all, both techniques only work reliably if the software is flawless (app and encryption mechanisms/libraries). Bugs might easily lead to data leaks (e.g. the &lt;a href="https://heartbleed.com"&gt;Heartbleed&lt;/a&gt; bug&lt;sup id="fnref2"&gt;2&lt;/sup&gt;).&lt;br&gt;
The hardware can also have design flaws, see for instance the &lt;a href="https://meltdownattack.com"&gt;Meltdown&lt;/a&gt; vulnerability&lt;sup id="fnref3"&gt;3&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;But let’s assume that software, hardware, and app are immaculate. Then it comes down to the single user.&lt;br&gt;
The elephant in the room for this one is data loss. If only the user has access to their data, they also bear all the responsibility for storing and/or accessing it.&lt;/p&gt;

&lt;p&gt;In the case of &lt;strong&gt;encryption&lt;/strong&gt;, data can be backed up the same way as unencrypted data, but if the encryption key is lost, your journal entries are encrypted for good. Potentially years’ worth of reflections – gone. Bummer!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Violation of requirement #4.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here's a story where losing encryption keys went wrong big time: &lt;a href="https://www.newyorker.com/magazine/2021/12/13/half-a-billion-in-bitcoin-lost-in-the-dump"&gt;Half a Billion in Bitcoin, Lost in the Dump&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For &lt;strong&gt;local storage only&lt;/strong&gt; the problem is more on the backing-things-up side (discussed in the next section).&lt;br&gt;
A user might also only have one device – most likely a phone – which can be lost or stolen; or multiple devices, that all get destroyed simultaneously, for example in a fire.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Violation of requirement #3.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Entries are synced instantly across all of the user's devices
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why is it important?
&lt;/h4&gt;

&lt;p&gt;It’s simply a matter of convenience and great user experience. Depending on the situation, you might want to write entries on your MacBook, where typing is more convenient; or access them on the go, on your phone, when you do not have your laptop at hand. Being always with you is one of the great advantages of an app over a paper journal. In the case of local storage-only, instant sync is also essential for backups.&lt;/p&gt;

&lt;h4&gt;
  
  
  How can it be done?
&lt;/h4&gt;

&lt;p&gt;Data syncing has its own challenges, especially if devices do not have a stable internet connection or are disconnected from the web entirely for long periods. But that’s a topic for another day.&lt;/p&gt;

&lt;p&gt;Data can be synced either peer-to-peer (see above), or traditionally via a central web server. Almost all web services you know (Gmail, Dropbox, Evernote, you name it...), use the latter.&lt;/p&gt;

&lt;h4&gt;
  
  
  What are the problems?
&lt;/h4&gt;

&lt;p&gt;If devices need to communicate directly to exchange data in the peer-to-peer case, continuous synchronization is difficult, e.g. all devices would need to be &lt;em&gt;ON&lt;/em&gt; all the time and connected to the network to be able to provide their latest updates when another device performs a sync.&lt;/p&gt;

&lt;p&gt;Since there is no single device in a &lt;a href="https://en.wikipedia.org/wiki/Peer-to-peer"&gt;peer-to-peer network&lt;/a&gt; that serves as a master node, inconsistencies can occur when different devices resolve conflicts and do not immediately broadcast the changes to &lt;em&gt;all&lt;/em&gt; other devices.&lt;/p&gt;

&lt;p&gt;Using a central server circumvents these problems by being always available and serving as the single source of truth by always keeping the most up-to-date state.&lt;/p&gt;

&lt;p&gt;The downside is that the service provider and/or a third party have physical access to the hardware on which the data is stored.&lt;/p&gt;

&lt;h3&gt;
  
  
  If a device (or all devices) is damaged, lost, or stolen, the entries can be fully recovered
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why is it important?
&lt;/h4&gt;

&lt;p&gt;In almost all cases complete data loss is probably the worst-case scenario.&lt;/p&gt;

&lt;h4&gt;
  
  
  How can it be done?
&lt;/h4&gt;

&lt;p&gt;Data should be backed up multiple times (at least 3x, ideally more) in as many different physical locations as possible. Physical distance is important in cases of black swan events where all devices in a location can be lost or destroyed, e.g. burglary, flooding, etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  What are the problems?
&lt;/h4&gt;

&lt;p&gt;With a local storage-only system, it might be inconvenient or even impossible for a user to establish 3+ backups on different devices and separate them spatially at all times.&lt;/p&gt;

&lt;p&gt;In the conventional case, this responsibility is shifted to the cloud service provider. Their advantage is that they are professionals and safely storing data is their business.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recovery should also be possible if a user forgets their password or is not able to provide the required means of authentication
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why is it important?
&lt;/h4&gt;

&lt;p&gt;Again, complete data loss might be the worst-case scenario.&lt;/p&gt;

&lt;h4&gt;
  
  
  How can it be done?
&lt;/h4&gt;

&lt;p&gt;The only way to achieve this is to entrust the service provider or a third party with a master key to your data. This applies both to &lt;strong&gt;encryption&lt;/strong&gt; and authentication.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Violation of requirement #1.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What are the problems?
&lt;/h4&gt;

&lt;p&gt;Being able to recover your entries after losing your password or encryption key can only be achieved by giving up a certain degree of privacy, at least if you define it most stringently. Password reset always requires trust.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep in mind that if a web service claims your data is encrypted, but you can reset your password, they at least have a key as well, otherwise they would not be able to help you out. And then, what’s the point? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Concessions, trust, and risks
&lt;/h2&gt;

&lt;p&gt;As we’ve seen, it is not possible to fulfill all four requirements we set simultaneously, so we have to prioritize and balance the cost versus benefit of each of the privacy strategies and accommodate for their incompatibilities.  This is also where we’ll leave the realm of objectivity and enter the world of the opinionated design principles and ideologies behind &lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt; specifically (see &lt;a href="https://journalisticapp.com/about"&gt;About&lt;/a&gt; page).&lt;/p&gt;

&lt;p&gt;I’ll try to explain the reasoning behind all privacy-related design decisions and will attempt to answer the question that led us here:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;”Will my journal entries stay private?”&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoiding data loss at all cost
&lt;/h3&gt;

&lt;p&gt;I already mentioned that IMO complete data loss is the worst-case scenario. How many times have you reset a password in the past? And what if you couldn't do that?&lt;/p&gt;

&lt;p&gt;Therefore, unfortunately, we have to compromise on both &lt;strong&gt;encryption&lt;/strong&gt; and &lt;strong&gt;local storage-only&lt;/strong&gt;. At least in the default case. It might be possible to opt-in to either of those in the future if you prioritize privacy over data recovery. Have a look at the &lt;a href="https://journalisticapp.com/voynich"&gt;Voynich Project&lt;/a&gt; if you want to know more.&lt;/p&gt;

&lt;p&gt;Does that mean my data is &lt;em&gt;not&lt;/em&gt; private?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It means that you have to trust us and our meticulously selected third-party service providers to keep your data safe and private.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B1uu7-uM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzcnja8jbpy6qh6r4684.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B1uu7-uM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzcnja8jbpy6qh6r4684.jpg" alt="Blindfolded person in the forest" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Who you need to trust
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Journalistic
&lt;/h4&gt;

&lt;p&gt;You have to trust us. Obviously.&lt;/p&gt;

&lt;p&gt;In any case, unless you are an expert in software and security, you will always have to trust at least the service provider (the organization behind the app/website you are using). If a service you use wanted to spy on you they could just add a &lt;a href="https://en.wikipedia.org/wiki/Backdoor_(computing)"&gt;backdoor&lt;/a&gt; to their encryption algorithm or broadcast data without your knowledge.&lt;/p&gt;

&lt;p&gt;But you also need to trust the service provider that their highest priority is user satisfaction, not profit and that they take privacy seriously.&lt;/p&gt;

&lt;p&gt;Being a tiny organization is advantageous here, versus a big corporation with stakeholders that are only in for the bucks.&lt;/p&gt;

&lt;p&gt;We strongly believe that transparency builds trust. In the end, this is why I’m sitting here writing this lengthy post.&lt;/p&gt;

&lt;h4&gt;
  
  
  Digital Ocean
&lt;/h4&gt;

&lt;p&gt;We use &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt; as our cloud service provider. DO is a US company, but the servers we rent from them are located in the European Union. European data protection rules (&lt;a href="https://gdpr.eu/"&gt;GDPR&lt;/a&gt;) therefore apply.&lt;/p&gt;

&lt;p&gt;As explained in &lt;a href="https://www.digitalocean.com/community/questions/can-digitalocean-staff-access-the-files-on-my-droplet"&gt;this thread&lt;/a&gt;, it is not in their interest to go out of their way to access data we store on one of their servers, even though they theoretically could.&lt;/p&gt;

&lt;p&gt;Relying on a professional cloud service provider is, especially for small organizations, more secure than running, protecting, and maintaining an in-house infrastructure.&lt;/p&gt;

&lt;h4&gt;
  
  
  Third-party services
&lt;/h4&gt;

&lt;p&gt;Specifically for privacy reasons, we keep reliance on third-party services at a minimum and currently only use &lt;a href="https://sentry.io/"&gt;Sentry&lt;/a&gt; for error monitoring and &lt;a href="https://plausible.io/"&gt;Plausible Analytics&lt;/a&gt; to gather usage data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encryption in transit
&lt;/h3&gt;

&lt;p&gt;While end-to-end encryption is risky, encrypting data while it moves over the wire is standard as of 2022 via &lt;a href="https://www.digicert.com/what-is-an-ssl-certificate"&gt;SSL&lt;/a&gt; (known as https). Your data will always be encrypted when it moves through infrastructure that is not controlled by you, by us, or by Digital Ocean.&lt;/p&gt;

&lt;h3&gt;
  
  
  Risks and word of caution
&lt;/h3&gt;

&lt;p&gt;While we do everything in our power to keep your data safe, there is always the risk of a hack. I therefore strongly encourage you to not add content to your journaling app that could harm you or anyone else if exposed. This warning applies to &lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt; as well as for any other journaling app, whether it is encrypted or not!&lt;/p&gt;

&lt;h3&gt;
  
  
  What about pseudonymity?
&lt;/h3&gt;

&lt;p&gt;It is completely up to you to activate “stealth mode” and add an additional safety layer to your privacy. Here is how it works. Just create a new email address that doesn’t have your name in it and exclusively use it to sign up for &lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt;. You can get free email accounts from &lt;a href="http://gmail.com/"&gt;Gmail&lt;/a&gt;, &lt;a href="https://mail.yahoo.com/"&gt;Yahoo! Mail&lt;/a&gt;, etc. In case of a data leak, your journal will be only one among thousands.&lt;/p&gt;

&lt;p&gt;We might integrate pseudonymity directly into our service in the future via a service like &lt;a href="https://evervault.com/"&gt;Evervault&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verdict, and looking ahead
&lt;/h2&gt;

&lt;p&gt;Beware of the black swan!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_swkE51m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9ijyq6sz82z6ikf9nbm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_swkE51m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9ijyq6sz82z6ikf9nbm.jpg" alt="Black swan on a lake" width="800" height="529"&gt;&lt;/a&gt; &lt;em&gt;The [...] theory of black swan events is a metaphor that describes an event that comes as a surprise, has a major effect, and is often inappropriately rationalized after the fact with the benefit of hindsight (&lt;a href="https://en.wikipedia.org/wiki/Black_swan_theory"&gt;Wikipedia&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I would claim that any web-based service that asserts that your data is 100% safe is either ignorant, rounding up, or straight out lying. And it surely is the more responsible approach to be rather cautious and transparent than overconfident. There is always the risk of a system failure or an unforeseen security vulnerability.&lt;/p&gt;

&lt;p&gt;That being said, &lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt; is designed to be secure and private, and if we assume that our software works as intended &lt;strong&gt;your journal entries will stay private&lt;/strong&gt;. We will not ever sell or intentionally give away your data to third parties without your explicit consent!&lt;/p&gt;

&lt;p&gt;To answer another often asked question: this is also why we chose to rely on a business model with a paid &lt;a href="https://docs.journalisticapp.com/pro-version.html"&gt;PRO version&lt;/a&gt; for advanced users (not yet available) to fund the development and operation of Journalistic instead of selling data for dollars.&lt;/p&gt;

&lt;p&gt;Regarding the future… We are committed to continuously refining our software design to make systemic failure as unlikely as possible. Furthermore, we’ll keep experimenting and testing opt-in features like &lt;strong&gt;encryption&lt;/strong&gt; and &lt;strong&gt;local-only data storage&lt;/strong&gt; and give you the option to use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback and suggestions
&lt;/h2&gt;

&lt;p&gt;If you have any suggestions regarding our approach towards data privacy, our &lt;a href="https://journalisticapp.com/privacy"&gt;Privacy Policy&lt;/a&gt;, or general feedback, please send it our way to &lt;a href="//mailto:feedback@journalisticapp.com"&gt;feedback@journalisticapp.com&lt;/a&gt;.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;In 2013, &lt;a href="https://en.wikipedia.org/wiki/Edward_Snowden"&gt;Edward Snowden&lt;/a&gt; exposed a secret, large-scale spying operation on private citizens, coordinated between the &lt;a href="https://en.wikipedia.org/wiki/National_Security_Agency"&gt;NSA&lt;/a&gt; and the US government: &lt;a href="https://www.theguardian.com/world/interactive/2013/nov/01/snowden-nsa-files-surveillance-revelations-decoded"&gt;NSA Files Decoded&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Heartbleed was a security bug in the OpenSSL cryptography library, which is a widely used implementation of the Transport Layer Security protocol (&lt;a href="https://en.wikipedia.org/wiki/Heartbleed"&gt;Wikipedia&lt;/a&gt;). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Meltdown is a hardware vulnerability affecting Intel x86 microprocessors, IBM POWER processors, and some ARM-based microprocessors. It allows a rogue process to read all memory, even when it is not authorized to do so. Meltdown affects a wide range of systems (&lt;a href="https://en.wikipedia.org/wiki/Meltdown_(security_vulnerability)"&gt;Wikipedia&lt;/a&gt;). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>mobile</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Augmenting GitHub repository stats and insights</title>
      <dc:creator>Toni Engelhardt</dc:creator>
      <pubDate>Sat, 02 Apr 2022 11:49:35 +0000</pubDate>
      <link>https://dev.to/toniengelhardt/augmenting-github-repository-stats-and-insights-lb2</link>
      <guid>https://dev.to/toniengelhardt/augmenting-github-repository-stats-and-insights-lb2</guid>
      <description>&lt;p&gt;While GitHub is amazing (hence, their insane market share), they unfortunately provide only very limited insights for the repositories that they host. Moreover, most of the stats in the "Insights" tab are only available for PRO users when the repo is private.&lt;/p&gt;

&lt;p&gt;Therefore, I set out to build a tool that augments those insights with loads of cool charts and cards. You can read the full story on why in &lt;a href="https://dev.to/toniengelhardt/i-made-a-github-repo-tracker-with-nuxt-3-to-track-when-nuxt-3-is-ready-47l4"&gt;this post&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vviQrJ4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/222xhkcs3yox04cwfxx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vviQrJ4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/222xhkcs3yox04cwfxx5.png" alt="RepoTracker Dashboard Preview" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;RepoTracker is designed for two user groups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open source devs and -users that want to keep up with the latest changes, issues, etc. in the pre-rc repositories that they are working/playing with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Professional software developers and dev ops peeps that need to know which of the packages their software depends on are properly maintained and which are not.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PwPoocdf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06ye7f1aanzgh2478do7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PwPoocdf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06ye7f1aanzgh2478do7.png" alt="RepoTracker Repository Details Preview" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you breathe software, try it out at &lt;a href="https://repo-tracker.com"&gt;www.repo-tracker.com&lt;/a&gt;, it's free! &lt;/p&gt;

&lt;p&gt;I'd love to hear what you think about the project and which metrics you would be interested in as a developer ✌🏽&lt;/p&gt;

&lt;p&gt;Made with &lt;a href="https://v3.nuxtjs.org/"&gt;Nuxt 3&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>devops</category>
      <category>opensource</category>
      <category>nuxt3</category>
    </item>
    <item>
      <title>I made a GitHub repo tracker with Nuxt 3 to track when Nuxt 3 is ready</title>
      <dc:creator>Toni Engelhardt</dc:creator>
      <pubDate>Fri, 11 Feb 2022 01:02:31 +0000</pubDate>
      <link>https://dev.to/toniengelhardt/i-made-a-github-repo-tracker-with-nuxt-3-to-track-when-nuxt-3-is-ready-47l4</link>
      <guid>https://dev.to/toniengelhardt/i-made-a-github-repo-tracker-with-nuxt-3-to-track-when-nuxt-3-is-ready-47l4</guid>
      <description>&lt;p&gt;Ever since Vue 3 &lt;a href="https://blog.vuejs.org/posts/vue-3-one-piece.html"&gt;One Piece&lt;/a&gt; was officially released in September 2020 by Evan You, we Nuxters have been waiting for &lt;a href="https://nuxtjs.org/"&gt;Nuxt&lt;/a&gt; to catch up so that our projects could also finally benefit from all the cool new stuff (script setup, reactive CSS properties, portals, and what not...).&lt;/p&gt;

&lt;p&gt;And the wait has been long, &lt;em&gt;painfully&lt;/em&gt; long!&lt;/p&gt;

&lt;p&gt;Composition API has been partially backported, but it's just not the real deal and it's already clear that most of the code we henceforth write for Nuxt 2 will probably have to be refactored in some way or another for Nuxt 3. That's obviously a bummer and highly demotivating.&lt;/p&gt;

&lt;p&gt;And then there are also Dom, Saito, and all the other guys starting new Nuxt projects right now, stuck in limbo, not knowing whether to start with Nuxt 2 or rather wait for v3 RC.&lt;/p&gt;

&lt;p&gt;Fortunately, &lt;a href="https://nuxtjs.org/announcements/nuxt3-beta/"&gt;Nuxt 3 public beta&lt;/a&gt; dropped in October last year and everybody was happy, right? Right?! Well, not really...&lt;/p&gt;

&lt;p&gt;I dropped &lt;a href="https://v3.nuxtjs.org/getting-started/bridge/"&gt;Nuxt Bridge&lt;/a&gt; into my pet project (&lt;a href="https://journalisticapp.com"&gt;Journalistic&lt;/a&gt;) and started migrating, testing, asking, and answering questions on Discord, opening issues and PRs on GitHub, thinking that by the year's end it'd be running at least on Bridge, if not even v3.&lt;/p&gt;

&lt;p&gt;But it quickly became clear that it would not be such a smooth transition. The problem is not even Nuxt itself (&lt;a href="https://twitter.com/danielcroe"&gt;Daniel&lt;/a&gt;, &lt;a href="https://twitter.com/_pi0_"&gt;Pooya&lt;/a&gt;, &lt;a href="https://twitter.com/antfu7"&gt;Antfu&lt;/a&gt; and others are doing an incredible job, fixing issues and helping folks out), but rather the ecosystem, aka. &lt;a href="https://modules.nuxtjs.org/"&gt;community module&lt;/a&gt; support.&lt;/p&gt;

&lt;p&gt;As of now (4 month after release), only 13 out of 191 modules officially support Bridge and 12 support v3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello RepoTracker
&lt;/h2&gt;

&lt;p&gt;So I thought, f*ck it, I'm gonna build and ship a simple app with Nuxt 3 beta, just to see how it works, what the differences are, and how far I can get. And to cut a second bird's life short with the same pitch I'll solve the problem of keeping track of all the changes and updates in all the Nuxt-related module repositories.&lt;/p&gt;

&lt;p&gt;And it was a blast, Nuxt 3 is so much fun, a massive improvement, even over the already great Nuxt 2. The DX is just another level. &lt;/p&gt;

&lt;p&gt;You can take a look at the result and play around with it at &lt;a href="https://repo-tracker.com"&gt;repo-tracker.com&lt;/a&gt; (made with Nuxt 3, &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;, &lt;a href="https://pinia.esm.dev/"&gt;Pinia&lt;/a&gt;, and &lt;a href="https://windicss.org/"&gt;windicss&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;That was last week and the response has been really great so far. While working on the project it dawned on me that a cross-platform (&lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;, &lt;a href="https://gitlab.com/"&gt;GitLab&lt;/a&gt;, &lt;a href="https://bitbucket.org/"&gt;BitBucket&lt;/a&gt;) repository tracking/analytics dashboard might have quite some potential, for open-source development, as well as in a professional software development context.&lt;/p&gt;

&lt;p&gt;I'll add some additional features, like drag-n-drop &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;requirements.txt&lt;/code&gt; file import, repo lists, insights charts, etc. and see where it goes.&lt;/p&gt;

&lt;p&gt;Thanks for reading and have a wonderful day ✌🏽&lt;/p&gt;

</description>
      <category>nuxt3</category>
      <category>productivity</category>
      <category>git</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Publishing a Progressive Web App (PWA) on the PlayStore – What works and what doesn’t (in 2022)</title>
      <dc:creator>Toni Engelhardt</dc:creator>
      <pubDate>Mon, 12 Apr 2021 19:19:14 +0000</pubDate>
      <link>https://dev.to/toniengelhardt/publishing-a-progressive-web-app-pwa-on-the-playstore-what-works-and-what-doesn-t-in-2021-38o5</link>
      <guid>https://dev.to/toniengelhardt/publishing-a-progressive-web-app-pwa-on-the-playstore-what-works-and-what-doesn-t-in-2021-38o5</guid>
      <description>&lt;p&gt;I’ve been working on a &lt;a href="https://journalisticapp.com" rel="noopener noreferrer"&gt;micro journaling app&lt;/a&gt; (PWA) over the last year, thinking that with a little notching users would just get used to installing apps directly from their browser, but errrrr…&lt;/p&gt;

&lt;p&gt;Turns out they don’t. Not yet.&lt;/p&gt;

&lt;p&gt;So I was stoked when I realized that with Google’s &lt;a href="https://developer.chrome.com/docs/android/trusted-web-activity/overview/" rel="noopener noreferrer"&gt;Trusted Web Activities (TWA)&lt;/a&gt; you can just publish a PWA on the PlayStore.&lt;/p&gt;

&lt;p&gt;The result is actually pretty great, you can check it out here: &lt;a href="https://play.google.com/store/apps/details?id=com.journalisticapp.twa" rel="noopener noreferrer"&gt;Journalistic app on Google Play&lt;/a&gt;. It quacks like a duck, mostly…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2800%2F1%2AHJfQOtSNQ6QDaGhs8eUAkg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2800%2F1%2AHJfQOtSNQ6QDaGhs8eUAkg.png" alt="Journalistic TWA screenshots: text input, lists, charts, menu"&gt;&lt;/a&gt;&lt;em&gt;Journalistic TWA screenshots: text input, lists, charts, menu&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The stack behind Journalistic is &lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;Django&lt;/a&gt; and &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;. The &lt;a href="https://pwa.nuxtjs.org/" rel="noopener noreferrer"&gt;nuxt/pwa&lt;/a&gt; module takes care of everything PWA-related on the app side: manifest, service worker, etc. Easy peasy.&lt;/p&gt;

&lt;p&gt;Generating the app bundle is also more or less straight forward if you use &lt;a href="https://github.com/GoogleChromeLabs/bubblewrap" rel="noopener noreferrer"&gt;bubblewrap&lt;/a&gt;. There are some pitfalls with the app signing shenanigans but after a few hours I managed to have a working bundle and it went straight into the PlayStore review process.&lt;/p&gt;

&lt;p&gt;Turns out that Saturday was well spent, more than 80% of new signups come through the PlayStore now, without any buck or minute spent on promoting the listing (except the 25€ one-time fee for the Google developer account).&lt;/p&gt;

&lt;p&gt;There is quite some hacking required to make the web app truly behave like a native app, especially on the CSS side, but it can be done for the better part. Since there are already a lot of posts about this topic I won’t get into details here. Let’s look at what doesn’t work well (yet).&lt;/p&gt;




&lt;h2&gt;
  
  
  Bummers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Navigation bar color
&lt;/h3&gt;

&lt;p&gt;You can customize the navigation bar color in the app manifest, but only static. For a lot of apps that might be enough, but if you have a dark mode for instance and want the user to be able to turn it on/off manually via a setting in the app you have a problem. I’ve &lt;a href="https://github.com/GoogleChromeLabs/bubblewrap/issues/429" rel="noopener noreferrer"&gt;raised the issue with bubblewrap developers&lt;/a&gt; and the problem clearly is a lack of support on the Chrome side.&lt;/p&gt;

&lt;p&gt;I’ve resolved this to some extend by detecting and using the system theme as default (you can specify a color for light- and for dark mode). This works well until the user decides to choose a theme manually. If the device is in dark mode and the selected theme is “light”, things are not so bad, you get a black bar at the bottom, not ideal, but not too bad either. But if the device is in light mode and the user chooses a dark theme they get a dark app with a white bar on the bottom and that is really not cool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Status bar color
&lt;/h3&gt;

&lt;p&gt;You can also customize the status bar color, even dynamically, until again, dark mode. When the device is in dark mode it will always use a weird dark gray as background for the status bar, which raises the question: “WHY?!!”. Same problem, the limitation is on Chrome side.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Javascript is single-threaded. You can achieve multi-threading with web workers, but for most use cases they don’t bring any benefit and for others implementation is quite tricky. As a result, a TWA will feel clunky and less responsive when compared to a native app. Especially scroll animations, chart rendering, aso. can introduce quite some lag and compromise UX.&lt;/p&gt;

&lt;h3&gt;
  
  
  Text input
&lt;/h3&gt;

&lt;p&gt;Text input is generally a big problem on mobile devices and it gets even worse if you’re in a browser. While you have some control over input elements in native apps, dealing with  is simply a nightmare. On top of that you have no control or even knowledge over what the soft touch keyboard is doing. Eventually you’ll have to adjust (and probably compromise) your design to cope with the weirdness.&lt;/p&gt;

&lt;p&gt;Ah right, if you have a nav bar at the bottom, you’re f***ed anyway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3114%2F1%2AvYi03naPkCqHhOUZSkQjBw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3114%2F1%2AvYi03naPkCqHhOUZSkQjBw.png" alt="Journalistic UX example for text input with controls"&gt;&lt;/a&gt;&lt;em&gt;Journalistic UX example for text input with controls&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Monetization
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/android/trusted-web-activity/play-billing/" rel="noopener noreferrer"&gt;Google is currently running trials in Chrome (88 and 89)&lt;/a&gt; to integrate Play Billing via the &lt;a href="https://developers.google.com/web/fundamentals/payments" rel="noopener noreferrer"&gt;Payment Request&lt;/a&gt; and &lt;a href="https://github.com/WICG/digital-goods/blob/master/explainer.md" rel="noopener noreferrer"&gt;Digital Goods&lt;/a&gt; APIs. This is definitely a big step in the right direction, but it will probably still take a bit until this is fully supported.&lt;/p&gt;

&lt;p&gt;If you want to monetize your app, this might be the dealbreaker and even if Play Billing is fully available eventually you will still have to shoulder the burden of integrating two different payment systems, the Google one and the one you use for the web app (&lt;a href="https://stripe.com/" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt; or whatever).&lt;/p&gt;

&lt;h3&gt;
  
  
  Data storage
&lt;/h3&gt;

&lt;p&gt;You can of course use local storage, just like in the browser, but if the user erases their Chrome storage it will also wipe out your app’s data, which is something most users would certainly not expect. So far I haven’t found a way around this, but tbh also haven’t been looking a lot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Annoying “Running in Chrome” banner
&lt;/h3&gt;

&lt;p&gt;When opening the app for the first time the TWA will display a banner notifying the user in which browser it is running. This is in my opinion completely unnecessary and annoying. It just confuses users and gives the impression of a “fake” app. A better alternative would be to only display the banner if the app was installed with a browser that is not the default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Device APIs
&lt;/h3&gt;

&lt;p&gt;Chrome already supports a lot of device APIs (way more than Safari for instance), but some important ones are still missing and some have really bad UX. If you want to access Bluetooth for instance via BLE, Chrome will drop an ugly browser menu in the pairing process.&lt;/p&gt;




&lt;h2&gt;
  
  
  All in all
&lt;/h2&gt;

&lt;p&gt;All in all, depending on your use case you can already get quite close to a native experience. Most of the outstanding issues are annoying but minor and could be (and hopefully will be) easily resolved on the Chrome side. Sadly progress is pretty slow here.&lt;/p&gt;

&lt;p&gt;Over the long run I see the above mentioned performance issues as the biggest limitation for PWAs compared to their native counterparts and the question is whether advances in web tech and on the framework side will be able to close the gap.&lt;/p&gt;




&lt;h2&gt;
  
  
  Daydreaming
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Chrome
&lt;/h3&gt;

&lt;p&gt;I hope that in the future Chrome will support dynamic theming for the status- as well as for the navigation bar via meta tags (text- and background color) and get rid of the weird behavior in dark mode.&lt;/p&gt;

&lt;p&gt;Removing the “Running in Chrome” banner or introducing a more user-friendly UX for it would also be amazing.&lt;/p&gt;

&lt;p&gt;I’m not sure if that would even be possible, but giving TWAs their own local storage and cookies, independent from Chrome, would be totally sick.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payments
&lt;/h3&gt;

&lt;p&gt;Can there not be a single API that you can integrate and it figures out automatically who gets their cut when someone purchases something? 💭&lt;/p&gt;

</description>
      <category>pwa</category>
      <category>twa</category>
      <category>playstore</category>
    </item>
  </channel>
</rss>
