Mobile apps
Mobile apps for B2B: why we route most clients to a PWA
A construction supplier asked us for native iOS and Android. We talked them into a PWA. Three B2B jobs taught us where native still earns its budget and where it does not.

A construction supplier in Eindhoven sat across from us in February with a printed brief: iOS and Android, native, field crew app, 120 users. We spent the first hour talking them out of it. By the end of the call we had scoped a Progressive Web App with push notifications instead. They shipped in five weeks, paid roughly a third of the native quote, and the savings paid for two years of operational support.
That conversation is now our default. For most sub-€2M B2B clients, we route them to a PWA + push hybrid before we will quote a native build. The policy was not theoretical. Three jobs taught us, one of which we lost.
The economics that never make it onto the deck
A native B2B app, done properly, runs €40-80k for the first version. That is two codebases (or one React Native codebase with platform-specific patches that act like two codebases on bad days), Apple Developer and Google Play accounts, signing infrastructure, a release pipeline, and a review cycle measured in days. Every iOS major version means a sprint of regression work. Every brand colour tweak means a binary upload.
For a B2B portal where the user list is known (employees, dealers, contracted customers), the real killer is not cost. It is install friction. Your operations lead emails the new feature link. The user taps it. Nothing happens, because the app wants an update. They tap the App Store. They forget their Apple ID. They give up. Multiply by 400 dealers.
Rejection one: the field-service crew that did not need an app
A facilities-management firm asked for a native Android tool for around 120 field crew. Job sheets, photo upload, ticket status, push when a new ticket lands. We quoted both options. The PWA quote was 28% of the native quote, the timeline was 5 weeks instead of 14, and the crew already had Chrome installed because they used it for routing.
We installed it to home screen during the kickoff visit. Thirty seconds per crew member, done in a single morning. Service-worker cache for the job sheet so it survives a dead zone on a roof. Push for new tickets. Eighteen months in, nobody has asked when the real app is shipping.
Rejection two: the dealer portal that proved push is the feature
A Dutch building-materials wholesaler wanted a dealer ordering app for around 400 small construction businesses. We could see the native route ending one of two ways. Enterprise distribution via MDM, which 400 single-laptop dealers will not accept. Or public App Store with a login wall, which gets single-digit install rates in B2B because nobody downloads their supplier's app.
We shipped a PWA: catalogue, price by dealer code, one-tap reorder, push notifications for order status and stock alerts. Installs hit 73% within two months, because the wholesaler already had the dealers' attention through invoices and a sales rep. The push channel turned out to be the actual product. Reorder volume on push-triggered restock alerts ran four to five times higher than on the previous SMS workflow.
Rejection three: the one we lost
A B2B services firm wanted a premium-feeling customer app for around 3,000 customers. We argued against it. The behaviour did not exist: nobody opens an app for the company that fixes their copiers. We sketched a PWA with monthly statements, ticket creation, and push for resolution updates. They went with a competitor who built the native iOS and Android apps.
Fourteen months later we heard, through a shared contact at the firm, that install rates sat in the single digits. The competitor is now charging them again to improve discovery. That is the rejection we keep telling other clients about, because nobody believes the open-rate problem until they have already spent the money.
Where native still earns its budget
The policy is PWA by default, not PWA always. A native build still earns its money when:
- You need continuous Bluetooth, background location, NFC writing, or ARKit/ARCore. The web cannot do these reliably and Apple is in no hurry to let it.
- The product is consumer-facing, used daily, and paid for. Our work on consumer health apps is native because it runs in the morning before breakfast and competes for the same attention as Instagram.
- The App Store itself is your discovery channel. For most B2B portals it is not. For a paid consumer utility it might be.
- You need foreground media (camera-heavy AR, video calls with custom processing) that the web still approximates badly.
If your brief is login + dashboard + push, the web does that now. The bridge that made it real was iOS 16.4 in March 2023, when Safari shipped Web Push for installed home-screen PWAs. Before that, PWA on iOS was a polite fiction.
The stack we actually ship
Standard build: Next.js or Vite + React on the front, a Workbox-generated service worker for caching and push, and the Web Push API with VAPID keys on the server. Notifications route through Apple's APNs for iOS users and FCM or autopush for Android and desktop, transparently, because that is what Web Push routes to underneath.
The service-worker push handler is forty lines and it is the only piece that feels native:
// public/sw.js
self.addEventListener('push', (event) => {
const data = event.data?.json() ?? {}
event.waitUntil(
self.registration.showNotification(data.title || 'Update', {
body: data.body,
icon: '/icons/icon-192.png',
badge: '/icons/badge.png',
tag: data.tag,
data: { url: data.url || '/' },
})
)
})
self.addEventListener('notificationclick', (event) => {
event.notification.close()
event.waitUntil(
self.clients.matchAll({ type: 'window' }).then((clients) => {
const target = event.notification.data.url
const open = clients.find((c) => c.url.includes(target))
if (open) return open.focus()
return self.clients.openWindow(target)
})
)
})
On iOS, Web Push only works after the user installs the PWA to their home screen. If you call Notification.requestPermission() from a Safari tab, the prompt will not appear. Gate the ask behind an in-app moment (first order confirmed, first ticket created) that comes after install.
Where it breaks, plainly
We are not selling a free lunch. The places PWAs still bleed:
- iOS install friction. Add-to-home-screen is a three-tap dance that no marketing page will fix. You plan for an onboarding moment that walks the user through it, ideally in person for high-value B2B portals.
- Background sync is thinner than on native. Long-running uploads benefit from a leave-this-tab-open pattern instead of fire-and-forget.
- Enterprise MDM profiles sometimes block PWA installation or strip the service worker. Test on the target fleet before you commit.
- If you genuinely need NFC writing or continuous BLE, the web is not there. Stop reading and quote native.
A five-minute audit before you scope native
Walk through three questions with the client in the room:
- Will the user open this daily because they want to, or only when a task forces them?
- Do you actually need any of: continuous Bluetooth, background location, ARKit, NFC writing, custom camera processing?
- Is the App Store your discovery channel, or are you handing users a link yourself?
If question two is no and question three is we send them the link, you do not need a native app. You need a fast site, a service worker, a push key pair, and an install moment.
When we built the dealer portal for the wholesaler in rejection two, the iOS permission flow was the part we kept getting wrong: we ended up gating the push prompt behind the first successful reorder, which lifted opt-in from 19% to 64% across the active dealer base. The same scoping conversation is most of what our website and SaaS work looks like in the first month with a new B2B client.
Today's smallest move: open your last mobile-app brief, find the feature list, and circle anything that needs continuous Bluetooth, background location, or NFC writing. If nothing is circled, you have your answer.
Key takeaway
If your B2B brief is login plus dashboard plus push, the web does that now. Keep native for daily-use consumer apps and genuine hardware needs.
FAQ
When does a B2B client still need a native app?
When you need continuous Bluetooth, background location, NFC writing, ARKit/ARCore, or the App Store itself is your discovery channel. Most sub-€2M B2B portals need none of those.
Does Web Push actually work on iPhone now?
Yes, since iOS 16.4 in March 2023, but only after the user installs the PWA to their home screen. Push permission cannot be requested from a regular Safari tab.
How long does a PWA build take versus native?
Our dealer portal shipped in five weeks against a 14-week native quote, at roughly a third of the cost. The ratio holds across most B2B portal work we have scoped.
What about React Native or Flutter as a middle ground?
They still ship native binaries with App Store review, signing, and update friction. The savings are in build, not in distribution. For B2B portals, distribution is the actual problem.