---
title: Should My App Be a PWA or Native?
url: https://varstatt.com/jurij/p/should-my-app-be-a-pwa-or-native
author: Jurij Tokarski
date: 2026-06-30
description: A gym is quoted two native apps for member bookings. A PWA does it from one codebase that installs from a link, unless the core needs hardware like Bluetooth.
section: Blog (https://varstatt.com/jurij/archive)
tags: Q&A (https://varstatt.com/jurij/c/questions)
---

<Quote>
  We need a booking app for our gym members. Agencies quote us two native apps, for iPhone and Android. Someone said a PWA would do. Will members even find it without the App Store?
</Quote>

A PWA, not a native app, unless the core needs hardware a browser can't reach. One codebase installs from a link, works offline and can go in the stores later.

A progressive web app is a website that installs like an app. It sits on the home screen and sends push notifications. The two native apps in your quotes are two separate builds, plus the website, each with its own upkeep.

Members find it through a link the gym sends them. A few taps later, it sits on their home screen next to their other apps.

## Hardware Is the Only Real Test

Bluetooth, NFC or heavy background work need native. Everything else fits a PWA.

[Find the Core](/principles/discovery/find-the-core) names the one thing the app exists to do. If that thing talks to a Bluetooth device or reads NFC tags, the app should be native.

Browsers reach some of that hardware, mostly in Chrome on Android and with limits. That's not enough to bet a product's core on.

The core of your app is booking a class. That is screens and data, and nothing in it talks to hardware.

The camera is where the line gets drawn wrong. A [barcode scanner I built](/jurij/p/the-algorithm-that-transformed-warehouse) runs in the browser. It reads codes through the phone camera and switches the torch on in dim rooms.

Advanced camera control belongs to native apps; scanning a barcode doesn't.

Short of that line, a PWA runs wherever a browser does. The easiest proof is one you can open. [Fidder](https://fidder.app), my own RSS reader, has been a PWA since September 2024.

Open it on your phone and add it to your home screen. It installs like an app, sends push notifications and follows your dark mode.

Native, meanwhile, has costs that keep coming back. Three codebases instead of one. Store review before launch and before every update, where a PWA fix goes live with the next deploy.

When the core passes the test, your question comes next: how members get it onto their phones.

## Installing Takes a Link, Offline Takes Design

On iPhone, it's Share, then Add to Home Screen. Offline works when it's designed in.

Both steps work in Safari, and since iOS 16.4 in Chrome and Edge too. The app gets its own icon next to the native ones. Android is simpler: Chrome offers to install the app on its own.

Push notifications on iPhone work from the home screen, not from a Safari tab. Apple added them for home-screen web apps in iOS 16.4, which [WebKit announced in February 2023](https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/).

New web features tend to reach iPhone later than Android, so test on an iPhone first when a feature matters.

Once it's on the home screen, members expect it to behave like an app, signal or not. Offline doesn't come with the label.

Two parts do the work. A service worker caches the app itself, so it opens without a connection.

The data needs its own copy. [Firestore keeps one on the device](https://firebase.google.com/docs/firestore/manage-data/enable-offline) and syncs changes back when the signal returns.

The design question is which data the user needs before the signal drops. The barcode scanner answered it by loading all its data onto the device up front. For a gym member, that is likely their own bookings.

Offline has a failure of its own: a cache that keeps serving the old version after a fix ships. I've hit it on two projects.

Both times the fix was removing the service worker. A user stuck on the old version couldn't receive the fix from it. So the update flow is part of the offline work.

With install and offline in place, some owners want the app in the stores too.

## The Stores Come After Launch

A store listing is a layer on the same code, added once users are in.

Google Play takes a PWA wrapped as a [Trusted Web Activity](https://developer.chrome.com/docs/android/trusted-web-activity). Tools like [Bubblewrap](https://github.com/GoogleChromeLabs/bubblewrap) and [PWABuilder](https://www.pwabuilder.com) generate the package from the site you already have.

Apple is stricter. Its [review guidelines](https://developer.apple.com/app-store/review/guidelines/#minimum-functionality) ask for more than a website in a frame. Thin wrappers often get rejected.

An iPhone listing needs a native wrapper, such as [Capacitor](https://capacitorjs.com), that adds real phone features.

That's why the stores come after launch. The web version proves members use the app. The store listing then becomes a set of tasks on the same codebase.

All of this assumes a new build. If the gym already takes bookings on a website, part of the work is done.

## Your Web App Is Halfway There

Turning a web app into a PWA often costs less than a rebuild.

Three pieces make a web app a PWA: HTTPS, a web app manifest and a service worker. The manifest holds its name and icons, and the service worker handles offline and push.

The icons are the easy part. The free [favicon generator](/toolkit/favicon) makes the manifest icons and the manifest JSON from one image.

The rest depends on the code. When it's JavaScript or TypeScript, install, offline and push land on the code that's already there.

Apps built on [Bubble](https://bubble.io) or [Glide](https://www.glideapps.com) are different: they mean a new build. Whether to rebuild at all is [its own question](/jurij/p/should-i-rebuild-my-app-from-scratch).

Your quotes are for new builds, and that's where the cost question sits.

## One Codebase Shrinks the Bill

The cost is the same sum as any app: the time it takes times the rate of whoever builds it. A PWA shrinks the first number, because there's one codebase instead of three.

[What an MVP really costs](/jurij/p/how-much-does-it-really-cost-to-build-an-mvp) walks through that sum.

Running costs are a separate line. Early on, hosting on one platform costs little, and the paid services real users need add to that. [What an app costs after launch](/jurij/p/what-will-my-app-cost-after-launch) puts numbers on both.

## How I Build One

A new build takes six weeks. The time is fixed first and the features are cut to fit, the same box as an [MVP](/x/founders/mvp-development).

Week one puts sign-in, the data and the install setup on your phone. Weeks two and three build the screens members need first.

Week four is offline and speed. Weeks five and six bring hosting, push, analytics and a [Firestore cost review](/jurij/p/why-is-my-firebase-bill-so-high), then the launch.

For an existing JavaScript or TypeScript app, setup in [Week 0](/principles/partnership/onboarding) includes reading the code. Then install, offline and push land as tasks, one at a time, about 72 hours each on average.

When the core fails the hardware test, that's a native developer's job, and I point founders to one. When it passes, that's a [PWA build](/x/founders/pwa-development), and my weekly price is on the [homepage](/).

## What the Owner Should Do Now

Run the hardware test on your own core first. Booking a class passes it, so one codebase can cover iPhone, Android and the web.

Then size the scope before you answer the agencies. The free [build cost tool](/discovery/build-cost) turns it into weeks, and your scope sets the real length.

Then send members the link. If enough of them ask for the App Store, the listing is a task on the same code.
