DEV Community

Alexey
Alexey

Posted on • Updated on

A free world of app publishing

When the Epic vs Apple trial went down, I was working on Spicebreaker as a mobile app - it was maybe 95% ready as a React Native app.

I ended up putting the mobile release on hold, and re-wrote the game from scratch on the web.

I'm not going to say I'm forever done with mobile app stores. But I want to share the reasoning I went through, some problems with publishing to the web, and possible solutions.

The main punchline of this post is that payments and identity are the two major competitive advantages of the app store over the web as a publishing platform, and that crypto wallets offer a new way to publish independent applications on the web. If you wish, skip through the story and frustrations straight to my analysis.

Why I pivoted from mobile-first to web-first

Background story

Spicebreaker is a passion project. Throughout its development I've had a demanding full-time job, and very limited time outside of work to create these types of artistic indie projects.

In fact the game was developed over 2 years; I wrote the mobile prototype in React Native in a weekend, and wrote a content management system on another weekend, which my wife used to lead the content creation. It took a few months to playtest it, iterate on the core concepts. My friend Laurent Baumann helped me with the mobile design. After maybe 6 months it was ready to launch on mobile, perhaps needing a few finishing touches.

I had some in-app purchases (packs of question cards), and I had to do one platform for the integration before the other - so I chose iOS since I own an iPhone.

The friction and frustrations of mobile

Modern mobile development is expensive and fraught with issues. Spicebreaker is one of the simplest types of meaningful applications one could build - and yet getting an application like that onto an app store is no small feat.

I vent some of my frustrations below.

Incompatible platforms

At the top level, the choice is which platform(s) to target. I of course wanted my app to be as broadly available as possible; I wanted all my friends to be able to access it - which meant I could not simply do a native iOS app and call it done. I needed to support Android for sure, and perhaps even less popular platforms. Cross-platform tools like React Native leave much to be desired.

Large companies often do build native applications - they hire an entire team of iOS experts, and a separate team of Android experts - even for the simplest applications. Because the application logic itself is often not the hard part of building a native application. A project like Spicebreaker would cost millions of dollars to develop in that scenario.

How can this be? Personally, I think this is due to the terrible tooling that both platforms have.

Terrible tooling

I'm primarily going to rant about iOS development - because the experience is a bit worse than Android, and because it's what I targeted first, and have had more experience with in my career.

I've worked with many developer tools in my career: Sublime, Eclipse, Visual Studio, Vim, Jetbrains/IntelliJ, VSCode, Ruby Mine, even BorlandC++/BorlandPascal, Delphi, Notepad++... XCode is the absolute worst developer tool I have ever worked with. Sorry. Not sorry.

Hundreds of precious hours of my life have been squandered dealing with arcane XCode issues throughout my career. There's no real understanding/pattern or depth behind dealing with them, and support is non-existent/atrocious. I can write several books about my frustration.

One issue that irked me during Spicebreaker's development was how painful it was to update the SQLite database with my questions. I tried various solutions, including deleting the database before loading it - it seems to work for some people, but definitely did not work under my setup with my simulator or phone. After wasting hours, I decided it's not worth shortening my lifespan further, and settled on renaming the database file each time I update it. Absolutely disgusting.

One of the worst issues - that set my development back by almost a full year - happened when I migrated to an M1 laptop. My previous Mac laptop, which was only a few years old, was in a state of disrepair - the keyboard would double-type letters, and it would overheat every 5 mintues and grind to a halt. I had been placing icepacks under it for 6 months, waiting for the M1s to come out.

The build didn't work. I spent maybe 20 hours in the darkest depths of the internet trying to debug XCode build issues for the M1 - and simply paused development for 9 months, because I didn't want to go back to the suffering of my old laptop. I took a 2 week vacation for Christmas break, started a new react native app, and just rebuilt the app from scratch over 3 days - copying old code bit by bit and re-installing dependencies from scratch on the M1. That got the build to work. Yay?

Terrible corporate attitude towards developers

I tried to register a special email for Spicebreaker's apple developer account. Apple rejected every credit card my wife and I put into the registration. It took days to even reach a rejection, and support had nothing to offer us in help. We ended up using my wife's personal Apple account for the developer program.

Before I had designs, and before my 9 month pause, I did try to publish a closed Beta on TestFlight so my friends could check the game out and give me feedback. Just doing that requires a review/approval from Apple, and my first review failed with no note. How is that even possible? This is a beta. Why do I need review? What do I even fix to pass it?

For an app like Spicebreaker - whose content targets adults - Apple can flat out censor the app, and force us to revise the content.

The kicker

So in these 2 years the Epic vs Apple trial had unraveled. And one of the big arguments Apple made was that they are owed the 30% commission because they provide highly valuable tools to developers.

Given the above rants, I hope my passionately violent gut reaction can be understood through a rational lens.

I would pay lots and lots of money to not have to deal with their developer tools. I would pay a different app store 50% commission if only I got to not have to deal with XCode, TestFlight, the Apple Developer Program, and their review process. Apple fights vigorously against the possibility, though - obviously they are in no shape to compete.

So I had revived the React Native app on my M1. I went back to my TODO list. First item was to make a small website to promote the game on launch. I started up a basic Express+NextJS server, and... re-built the entire game, designs included, in a day or two on a weekend. Oh, and by the way, I no longer have to deal with any of those SQLite issues - because I'm directly connected to my database by default. No build issues. No deploy issues. No issues publishing a Beta, no issues sharing the game with my friends. Christ almighty, what a breath of fresh air.

Switching to web

The pivot to web made me reflect on what pushed me to write an app in the first place.

Mobile apps have done very well in monetization. Mobile has nearly eliminated the friction of payments: on both the app store and inside apps, payments are just a few interactions away.

So what's the problem on the web? There's Stripe, PayPal - I can easily integrate payments. Why is the web an inferior payment platform for applications like Spicebreaker?

Payments and identity

The friction of payments on the web is identity.

Physical goods don't require a digital identity per se - but you'd need to put in your address each time you make a purchase without one.

Digital goods, on the other hand, absolutely require a digital identity, since their ownership is impossible otherwise. They represent most purchases on the app store: content subscriptions, in-game currency, unlockable features.

Spicebreaker sells packs of questions, i.e. digital content; to prove you've made a purchase and claim that digital content a year later on a different device, you need to be able to authenticate with a repeatable credential.

The need to set up those repeatable credentials creates the crux of the friction.

Identity on the web

The problem

Modern mobile devices provide identity by default: e.g. Apple ID or Google Account. That identity is shared by all apps, e.g. in-app purchases are tied to your Apple ID on iOS, and can be recovered when switching devices. The key is that the setup is done just once - when setting up the phone - and then consumed by all apps.

The web does not provide a cohesive identity platform: each account-based website is ignorant of your login information on other websites. This is by design, of course. OAuth is the strongest modern solution to the problem, but the experience of OAuth + Payment is not nearly as seamless as platform-based payment identity. OAuth also forces you to reveal your web activity to OAuth providers.

Today, browser-based web identity does not yet exist. Until recently, the only way to purchase digital goods on the web and retain ownership was to (ugh) Register an Account. This enormous friction is a major reason the web has not yet become a vibrant app publishing platform the way the app store is.

The solution

There already exists a technology that links identity and payments on the web that can act as a platform for applications: web3 wallet plugins. Wallet plugins need to be set up once per browser, and can unify identity across web sites via public keys (and private key signatures verifying ownership of those public keys).

If that sounds complicated, please check out the login flow on Spicebreaker. The UX itself is dead simple (that's the whole point):

  1. Click a button to begin sign in process with Phantom
  2. Click "Approve" inside of a Phantom Wallet popup

Image description
Image description

There are also more technical details below.

The purchase is done via USDC, so it's always $10. The purchase is a 3-step experience:

  1. Connect Phantom Wallet
  2. Click "Purchase"
  3. Confirm payment in Phantom Wallet popup

Here's what it looks like:
Image description
Image description
Image description

The reason I chose Phantom wallet for this technical experiment is that the Solana blockchain facilitates extremely low fees (fractions of a cent). There are certainly alternatives out there (e.g. Polygon), and I look forward to trying them out in the future.

Low fees are extremely important for an application whose most expensive purchase is $10. Ethereum gas fees ($3-$100) are exorbitantly high for in-app purchase applications.

Technical details

How does the web3 identity/purchase solution work, exactly?

The gist of it is that a purchase is tied to a public key, and access is authenticated via a private key signature - the same way blockchains authorize transactions, except done on top of a traditional centralized database application.

A wallet is able to issue signatures and share the public key. So the mechanism is as follows:

  1. The front end requests authentication for a public key via an API call
  2. The API call returns some random string of data
  3. The wallet issues a signature for that random string of data
  4. The front end resolves authentication by providing the signature via an API call
  5. If the signature is correct, the backend issues a session for the front end

A purchase is automatically tied to a public key, since every transaction sent to the blockchain contains information on which public key triggered it - so without any extra effort the purchase is tied to your identity, and you are able to prove your identity as long as you have the corresponding private key. Which you absolutely should always have if that's where your money is stored.

Harsh modern reality

Web3 and crypto are not mainstream.

I was extremely happy to imagine (and implement) a future with web payments as seamless as on the app store.

Today, the harsh reality is that a mass audience is not going to pay that way. So ultimately, Spicebreaker supports creating accounts via email, and paying with PayPal. I don't collect any personal info, and don't store passwords - the email sends a one-time code each login attempt, which I find much more usable than passwords. I'll eventually add various OAuth providers to also help with sign-up friction.

The UX isn't terrible, but it's nothing like the single-click seamless experience with wallets, or with in-app purchases.

There are many advances in the space. Brave browser is pioneering work on becoming a browser-based identity and payments platform, and they are getting traction with users. Even Chrome now supports identity in the browser - though it's to your Google Account, which these days is one of the least private types of accounts you can link to an application. Would you want Google to know what purchases you make on every web page?

In that world, as an indie developer, I would realistically integrate with the most used and least friction-prone payments platforms on the web; I'd grind my teeth but integrate with Google - so true privacy may be a luxury until crypto is adopted in the mainstream.

My hope is that web3 authentication and payments do become more mainstream, and wallets dominate web payments. That way, independent developers like myself can publish to an open, privacy-respecting, universally accessible platform, where we can use the best developer tools in existence: the web.

Top comments (0)