Waarom ik native apps bouw in plaats van een PWA
Ik heb één regel waar alles onder valt: er komt geen technologie bij die permanent aandacht vraagt. Native apps zijn ongeveer het slechtst denkbare voorbeeld van zo'n technologie — twee platformen, twee reviewprocessen, jaarlijkse verplichte upgrades. En toch staan er vier van mijn producten met een eigen app in de stores. Dit is waarom ik mijn eigen regel heb gebroken, en wat dat kost.
Eerst maar eens eerlijk over wat een PWA kan
Het is verleidelijk om dit soort stukken te beginnen met een lijstje waarin de webtechniek tekortschiet. Dat lijstje is korter dan mensen denken, en het wordt elk jaar korter.
Een progressive web app installeert zich op het beginscherm, draait zonder browserbalk, werkt offline via een service worker, bewaart data lokaal, en kan sinds iOS 16.4 — maart 2023 — ook op de iPhone pushmeldingen ontvangen. Eén codebase, geen reviewproces, en een bugfix die om tien uur 's avonds live staat in plaats van ergens volgende week. Voor drie van mijn zeven platforms zou dat ruim voldoende zijn geweest, en voor de prijsgrafiek van SlimHuys is het dat eerlijk gezegd nog steeds.
Dat maakt de vraag ook interessanter. Ik heb niet native gekozen omdat het web niet kon wat ik wilde. Ik heb het gekozen omdat er per product één ding was dat het web nét niet kon — en dat ene ding was elke keer het hele product.
Muur 1: de melding die niet gemist mag worden
Dit is de belangrijkste; de andere twee zijn er bijna kanttekeningen bij. KorpsApp stuurt manschappen een oproep om zich beschikbaar te stellen. GrootIncident stuurt een melding bij een GRIP-opschaling. Bij 112Radar willen kazernes een seintje bij een incident in hun verzorgingsgebied. Als die melding niet aankomt, is er geen product — dan is er een website die je zelf moet openen, en dat is iets fundamenteel anders.
Web push op iOS is er, maar met een voorwaarde die in de praktijk fataal is: het werkt alleen als de gebruiker de site eerst via het deelmenu aan zijn beginscherm heeft toegevoegd. Dat zijn drie handelingen die niemand kent, op een plek waar niemand kijkt, en je verliest er het overgrote deel van je gebruikers mee. Een installatiestap die je moet uitleggen is geen installatiestap maar een lek.
En dan zijn er nog de twee knoppen die er echt toe doen. Een native app kan een melding als tijdgevoelig markeren, waardoor hij door een focusstand heen breekt. En met een aparte toestemming van Apple — die je moet aanvragen en verantwoorden — kan een app kritieke meldingen sturen die ook door de stille stand heen komen. Precies dat is waar dit soort apps voor bestaat. Iemand die om kwart over drie 's nachts zijn telefoon op stil heeft liggen, is nu net degene die je wilt bereiken. Geen van beide bestaat op het web, en het valt niet te verwachten dat dat gaat veranderen: het is niet toevallig weggelaten.
Muur 2: werk dat doorgaat als de app dicht is
Een webapp leeft zolang zijn tabblad leeft. Een service worker mag heel kort wakker worden om een binnengekomen melding te tonen, en daar houdt het zo'n beetje op. Er is geen betrouwbare achtergrondverwerking, geen langlopende verbinding, geen locatie in de achtergrond.
Voor 112Radar betekent dat het verschil tussen een kaart die actueel is op het moment dat je hem opent, en een app die de stroom meldingen ook bijhoudt terwijl hij in je zak zit. Voor een functie als “waarschuw me bij incidenten binnen vijf kilometer” heb je locatie in de achtergrond nodig, en die geeft geen enkele browser weg — terecht, trouwens.
Op Android komt daar een tweede laag ellende bij die je op geen enkel specificatieblad tegenkomt: fabrikanten die achtergrondprocessen agressief afknijpen om batterijduur te winnen. Een native app met een correcte pushimplementatie overleeft dat meestal; een webapp op het beginscherm ruimt als een van de eersten het veld. Dat is geen technische onmogelijkheid, het is een gedragsverschil dat je pas ziet als de meldingen bij een specifiek merk telefoon structureel te laat aankomen.
Muur 3: hoe het ding op de telefoon komt
Deze onderschatte ik zelf het langst. De App Store is niet alleen een distributiekanaal, hij is de manier waarop mensen weten dat iets bestaat en dat het echt is.
Concreet: een postcommandant moet KorpsApp uitrollen onder veertig vrijwilligers, van wie de helft de telefoon vooral gebruikt om te bellen. Je hebt de keuze tussen “ga naar deze URL, tik op het deelicoon, scroll naar beneden en kies Zet op beginscherm” en “zoek KorpsApp in de App Store”. Dat is geen technische afweging meer. Dat is het verschil tussen een uitrol die lukt en een uitrol die na twee weken doodbloedt in de appgroep.
Daar komt bij dat een app in de store voor organisaties in dit domein een vertrouwenssignaal is. Er staat een uitgever bij, er staat een privacyverklaring, er staat wat er aan data wordt verzameld, en de veiligheidsregio die erover moet beslissen kan hem via beheerde distributie uitzetten op diensttelefoons. Een bookmark kan dat allemaal niet, hoe goed hij ook werkt.
En dan is er nog het risico waar zelden over wordt gesproken. In het voorjaar van 2024 kondigde Apple aan webapps op het beginscherm in de EU helemaal te schrappen, als bijvangst van de aanpassingen aan de Digital Markets Act. Na een storm van protest is dat teruggedraaid. Maar het bleef even hangen: mijn hele distributiekanaal kan verdwijnen door een beslissing waar ik part noch deel aan heb, aangekondigd in een voetnoot bij een bètaversie.
Wat het kost, zonder er omheen te draaien
Ik heb met deze keuze mijn eigen belangrijkste bouwregel gebroken: geen technologie erbij die permanent aandacht vraagt. Native apps vragen permanent aandacht. De rekening, zonder verzachtende omstandigheden:
- Twee extra platforms die niet stilstaan. Elk najaar een nieuwe iOS- en Android-versie, elk jaar een verplichte minimum-API-versie bij Google, elk jaar SDK's die verlopen. Dit is werk dat niets oplevert en dat je niet kunt uitstellen.
- Releases die niet van jou zijn. Een serverfix zet ik in twee minuten live. Een appfix moet door twee reviewprocessen. Meestal is dat binnen een dag geregeld, maar “meestal” is precies het woord dat je niet wilt horen als er iets stuk is.
- Vaste kosten en administratie. Negenennegentig dollar per jaar bij Apple, vijfentwintig dollar eenmalig bij Google, plus privacylabels, datatoelichtingen en verklaringen die per store anders heten en anders werken.
- Certificaten die verlopen op het slechtst denkbare moment. Vraag niet hoe ik dat weet.
- Gebruikers die niet updaten. Dit is de duurste van allemaal. Zodra er een app in het veld is, kun je je API niet meer zomaar veranderen. Er loopt altijd iemand rond met de versie van veertien maanden geleden, en die moet blijven werken. Op het web bepaal ik zelf welke code er draait; met apps in de store onderhoud ik voor onbepaalde tijd een contract met mijn eigen verleden.
Hoe ik de last klein houd
De enige manier waarop dit naast een baan en een pieper te doen is, is door de apps zo dom mogelijk te maken. Alle logica staat op de server; de app is een schil die data ophaalt en toont. Schermen worden voor een groot deel door de server beschreven, zodat ik iets kan wijzigen zonder release. Nieuwe functies gaan achter een schakelaar aan de serverkant, zodat uitrollen en terugdraaien niets met de store te maken heeft.
Daar hoort één harde regel bij: er komt geen functie in de app die niet ook op het web bestaat. De app mag prettiger zijn, sneller, met meldingen — maar hij mag nooit de enige plek zijn waar iets kan. Dat houdt het web de bron van waarheid, het scheelt me een tweede implementatie van elk idee, en het betekent dat een app die twee weken in de review hangt niemand blokkeert.
En de apps delen alles: dezelfde API, dezelfde authenticatie, dezelfde pushinfrastructuur, dezelfde serverinrichting op eigen hardware. De vierde app kostte daardoor een fractie van de eerste, precies zoals het zevende platform een fractie kostte van het eerste.
Waar ik géén app voor bouw
Het rijtje waar ik het web koos is net zo leerzaam. NetwerkBouwer is een webshop met een prijscalculator: mensen bestellen daar één keer per paar jaar een switch, en niemand installeert een app voor een aankoop die hij daarna vergeet. HulpdienstVoertuigen is een opzoekdatabase — je komt er via een zoekmachine, vindt je antwoord en gaat weg. Een app zou daar bezoekers kosten in plaats van opleveren, want elke installatiestap is een drempel.
Het patroon is telkens hetzelfde: apps zijn voor terugkerend gebruik en voor meldingen. Voor alles wat je één keer opzoekt, is het web niet het compromis maar de betere oplossing.
Conclusie
“Native of PWA” is bijna nooit de goede vraag, omdat hij over techniek gaat terwijl de beslissing over gedrag gaat. Bouw je iets dat mensen opzoeken, dan wint het web — goedkoper, sneller te wijzigen, vindbaar, en zonder poortwachter tussen jou en je gebruiker. Bouw je iets dat mensen moet bereiken op een moment dat zij niet hebben gekozen, dan is native de enige route, en dan koop je die ene mogelijkheid met jaren onderhoud.
Ik heb die rekening vier keer betaald en zou het elke keer opnieuw doen, om precies één reden: een pieper die niet afgaat is geen pieper.