Why we ship installable web apps before native apps
"Do we need an app?" is one of the first questions we hear when a new project starts. For most business software our answer is: yes, but not the kind you download from a store, at least not first. We usually ship an installable web app, a progressive web app (PWA), and only build native apps when the project clearly needs them.
Here's why, what "installable" actually means today, and where the line sits for us.
What "installable" means in 2026
An installable web app is a normal website that a browser allows people to add to their device like an app: it gets its own icon, opens in its own window without browser bars, and appears in the app switcher. The requirements are smaller than many people think. According to MDN and Chrome's install criteria, you need:
- the site served over HTTPS,
- a web app manifest linked from every page,
- in the manifest: a
nameorshort_name,iconsin 192 and 512 pixels, astart_urland adisplaymode such asstandalone.
That's it. A service worker is not required for installation any more. It's still what makes the app work offline, which we cover below. A manifest that meets the criteria looks like this:
{
"name": "Events Žilina",
"short_name": "Events",
"start_url": "/",
"display": "standalone",
"background_color": "#0A1128",
"theme_color": "#0A1128",
"icons": [
{ "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" }
]
}
and one line in the page's <head>:
<link rel="manifest" href="/manifest.webmanifest">
Why we start there
One codebase, every device. The same app runs on Android phones, iPhones, tablets, laptops and office PCs. For a small or mid-sized business that is often the difference between affording a product at all and not.
No store review between you and your users. When we fix a bug or ship a feature, people get it on their next visit. There's no review queue and no waiting for users to update.
Links and search still work. Every screen has a URL. You can share an event, a product or a report in a chat message, and search engines can find public pages. Native apps lose this almost completely.
Install is optional, not a barrier. People can use the app immediately in the browser and install it later if they come back often. Nobody has to visit an app store before seeing what you offer.
Notifications are no longer Android-only. Since iOS and iPadOS 16.4, web apps added to the Home Screen can ask for permission to send push notifications, as long as the request follows a direct user action like tapping a "Subscribe" button (WebKit announcement).
A real example: ĽAĽA HO
ĽAĽA HO brings the cultural, social and leisure events of Žilina and its surroundings into one place. It was created by the Žilina Regional Cultural Centre (KrKS) together with Mestská kultúra Žilina, and we designed and built it as lead developer and technologist.
We built it as an installable React web app on a NestJS API, with Prisma and Supabase underneath. The audience made that choice easy:
- People arrive through links. An event gets shared on social media or in a group chat. A link that opens the event straight away beats "download our app first".
- Content changes every day. Partner organisations publish and manage their own events in a role-based admin area, and visitors see changes at once.
- Two languages, one app. Visitors browse events, a calendar and venue pages in Slovak and English.
- Regulars can install it. People who check the programme every week can add it to their Home Screen and open it like any other app.
The admin side lives in the same codebase, behind the same login system. A separate native app for visitors would have doubled the work without giving them anything they need.
Making it work offline
Offline support comes from a service worker, a small script the browser runs between your app and the network (MDN: Service Worker API). A minimal one caches the app shell and falls back to it when the network is gone:
// sw.js
const CACHE = 'shell-v1'
const SHELL = ['/', '/index.html', '/app.css', '/app.js']
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(CACHE).then((cache) => cache.addAll(SHELL)))
})
self.addEventListener('activate', (event) => {
// Remove caches from older versions of the app
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((key) => key !== CACHE).map((key) => caches.delete(key)))
)
)
})
self.addEventListener('fetch', (event) => {
// Pages: try the network first, show the cached shell when offline
if (event.request.mode === 'navigate') {
event.respondWith(fetch(event.request).catch(() => caches.match('/index.html')))
}
})
Register it once from your app:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
}
In production we also cache API responses that are safe to show slightly out of date, such as an event list, and we version the cache name with every release so users never get stuck on old files.
When we still build native apps
A web app isn't always the right answer, and we also build native apps with Expo/React Native and games with Unity. We go native when:
- The product depends on device features the web can't reach reliably, like long-running background work, deep integration with the operating system, or hardware the browser doesn't expose on every platform. Support differs between browsers, so we check each API on MDN before promising it.
- Being in the App Store or Google Play is part of the business, for discovery, in-app purchases, or because customers simply expect it.
- Performance is the product, such as rich 3D, games or heavy real-time graphics.
Even then, the web version rarely goes to waste. With React on the web and React Native on mobile, much of the business logic and the API stay shared.
A quick way to decide
If you're planning an app, ask yourself:
- Do most users arrive through links, search or a QR code? → web first.
- Does the content or the product change often? → web first.
- Do you need store presence or in-app purchases from day one? → native.
- Does the core feature need device access the web can't offer on all your users' phones? → native, or native for that part only.
For most business tools the honest answer to the first two questions is yes, and starting with an installable web app gets a working product to real users faster and for less. Native can come later, when you know exactly what it needs to do.