Een companion-webapp is het browseroppervlak van een product dat vooral in een mobiele app leeft: de plek waar een klant zich aanmeldt vóór het installeren, waar een gedeelde link opent voor iemand zonder de app, waar werk dat op een telefoon begon op een desktop verdergaat. Het is hetzelfde product, op dezelfde API, gevormd naar waar een browser werkelijk goed in is — in plaats van een port van de app of een brochure erover.

De meeste bureaus bouwen de ene of de andere kant. Wij leveren Flutter-apps, webfront-ends en de backendservices die beide gebruiken — en dat verandert de engineering, want de vraag "op welk oppervlak hoort deze functie thuis" wordt beantwoord door één team dat naar één systeem kijkt, niet uitonderhandeld tussen twee leveranciers.

De producten die we bouwen

  • Klantwebapps naast mobiele apps — het volledige product in de browser waar dat zinvol is, of de bewuste deelverzameling waar dat niet zo is
  • Publieke, deelbare oppervlakken — de pagina's waarop een gedeelde link uitkomt, gerenderd en indexeerbaar, die overdragen aan de app wanneer die is geïnstalleerd
  • Realtime webclients — live data in de browser uit dezelfde feed die de apps gebruiken
  • Backoffices voor hetzelfde product — de kant voor operators is een eigen discipline, behandeld op beheerpanelen en dashboards
  • De webkant gebouwd op Nuxt — moet het companionoppervlak scoren, dan is de machinerie onze praktijk voor Nuxt-ontwikkeling

Wie je companion-webapp bouwt

Twee producten in productie laten het patroon zien, elk met een app en een weboppervlak op één backend.

Formtastic — één platform, drie clients

Formtastic draait als een Nuxt-webapplicatie plus Flutter-apps voor iOS, iPad en Android, allemaal tegen dezelfde backend in Django en Go. Het leerzame is hoe functies per oppervlak anders landen: spraak naar tekst neemt op het web audio op in de browser en stuurt die naar een transcriptie-endpoint, omdat er al een backend was om uit te breiden — terwijl de mobiele apps Whisper op het toestel meebundelen, omdat bouwplaatsen geen bereik hebben. Dezelfde functie, twee implementaties, elk eerlijk over zijn oppervlak. Dat oordeel, meer nog dan frameworkvaardigheid, is wat een product met twee oppervlakken werkelijk vraagt.

ExtraETF — één realtime feed, elke client

Voor ExtraETF bouwden we de -service in Go die live marktdata uitzendt naar zowel web- als mobiele clients — duizenden gelijktijdige verbindingen, updates samengevoegd tot het tempo dat een mens die naar een koers kijkt werkelijk nodig heeft. Wij bouwden de mobiele apps en de realtimelaag; de webclient die haar consumeert is van het eigen team van de klant. Een goed ontworpen service voedt ook oppervlakken die je zelf nooit bouwt.

Wat een product met twee oppervlakken werkelijk vraagt

Vier disciplines voorkomen dat een app en een weboppervlak uiteendrijven tot twee producten.

Eén API die beide eerlijk bedient

Op het moment dat het web "gewoon één speciaal endpoint" nodig heeft, heb je twee backends onder één naam. We ontwerpen de API als het enige contract van het product — dezelfde authenticatie, dezelfde modellen, dezelfde versionering voor elke client — en waar de oppervlakken oprecht verschillende vormen van data nodig hebben, staat dat verschil in het contract zelf, in plaats van weggemoffeld in een client.

Bepalen wat de webversie is

De dure fout is "de app, maar dan in een browser". Een companionoppervlak verdient zijn budget door te doen wat de app niet kan: bereikbaar zijn vanuit een zoekresultaat, direct openen vanuit een gedeelde link, een toetsenbord en een groot scherm bieden voor zwaar bewerkwerk. We scopen het weboppervlak functie voor functie tegen die toets — en een functie uit de webversie schrappen is een besluit dat we hardop verdedigen, geen gat dat later wordt ontdekt.

De overdracht tussen web en app

Een gedeelde link hoort de app te openen wanneer die is geïnstalleerd, de webpagina wanneer niet, en nooit een kapot tussenscherm. Universal links op iOS en app links op Android, de terugvalpagina's erachter, en de aanmeldstroom die in een browser begint en in de app verdergaat — deze naad is waar producten met twee oppervlakken het zichtbaarst gebruikers lekken, dus engineeren we hem bewust in plaats van aan te nemen dat hij werkt.

Rendering afgestemd op de taak van de pagina

De publieke, deelbare pagina's renderen op de server zodat crawlers en linkvoorbeelden echte content zien; de ingelogde werkruimte erachter rendert als de applicatie die ze is. De afwegingen staan uitgewerkt op de pijler webontwikkeling, en de keuze is per route, niet per project.

Hoe we werken

Bouw met vaste scope. Wij nemen het weboppervlak van functiescoping tot uitrol, tegen je bestaande API of een die we ernaast bouwen.

Teamuitbreiding. Onze engineers sluiten aan bij het team dat het product bezit — zie teamuitbreiding. Moet de mobiele kant ook gebouwd worden, dan is dat onze Flutter-praktijk.

Hoe dan ook sturen we, zodra we de eisen scherp hebben, binnen twee werkdagen een offerte met duidelijke scope.

Wat een companion-webapp kost

Een companionoppervlak wordt geprijsd vanuit dezelfde gepubliceerde niveaus als de pagina webontwikkeling: een geauthenticeerde webapp op je bestaande API valt in het webappniveau op € 12.000-32.000, terwijl een volwaardig tweede oppervlak met realtimefuncties, betalingen of een multi-tenant-structuur als werk op SaaS-niveau wordt geprijsd vanaf vanaf € 40.000.

Dit zijn dezelfde sleutels die de prijstabel van de pijler renderen, dus de twee kunnen niet uiteenlopen. Wat het bedrag beweegt: hoeveel van de API al bestaat en hoe zuiver hij voor meer dan één client is ontworpen, hoeveel van het product de webversie dekt, en of realtimefuncties op een bestaande feed meerijden of er een gebouwd moet worden.

Veelgestelde vragen

Veelgestelde vragen van teams wier product in een app leeft en waar steeds vaker om een browserversie wordt gevraagd.

Niet altijd — en het eerlijke antwoord hangt af van waar je groei weglekt. Een weboppervlak verdient zijn budget wanneer aanmeldingen beginnen bij zoekresultaten of gedeelde links, wanneer gebruikers op een groot scherm willen werken, of wanneer elk gedeeld stuk content nu doodloopt voor mensen zonder de app. Geldt geen van die drie, dan zeggen we dat; een goed gemaakte winkelvermelding en deep links kunnen alle webaanwezigheid zijn die je nodig hebt.
Meestal niet, en bepalen wat je weglaat is het grootste deel van het scopingwerk. De browser wint op bereikbaarheid — zoeken, gedeelde links, directe toegang zonder installatie — en op werk met toetsenbord en groot scherm; de app wint op camera, offline gebruik, meldingen, en doordat hij één tik verwijderd is. Formtastics spraak naar tekst is het patroon: het web neemt op in de browser en transcribeert op de server, de apps transcriberen op het toestel omdat bouwplaatsen geen bereik hebben. Dezelfde functie, verschillende eerlijke implementaties — en sommige functies blijven terecht alleen in de app.
We bouwen routinematig tegen bestaande API's — de webfront-end van Formtastic draait op de Django-backend die het product al had, uitgebreid waar het web dat nodig had. Wat we eerst doen is beoordelen of de API werkelijk geschikt is voor meerdere clients: authenticatie die een browser veilig kan gebruiken, modellen die geen app-only stromen aannemen, en versionering die twee clients laat evolueren. Waar hij tekortschiet zeggen we precies wat er moet veranderen, en we kunnen beide kanten zelf doen wanneer dat sneller is.
Ja — dat is een vraag over feedontwerp, niet over frameworks. Voor ExtraETF bouwden we de WebSocket-service in Go die live marktdata uitzendt naar web- en mobiele clients, met duizenden gelijktijdige verbindingen en updates samengevoegd tot ruwweg één per instrument per seconde, het tempo dat een mens werkelijk nodig heeft. Ontwerp de realtimelaag één keer, goed, en elke huidige en toekomstige client consumeert dezelfde stream.
Via universal links op iOS en app links op Android: dezelfde URL opent de app wanneer die is geïnstalleerd en de webpagina wanneer niet, waarbij de webpagina de volledige content draagt in plaats van een installatie-aansporing. Goed gedaan overleeft de link ook de installatie — iemand die op het web landt, de app installeert en hem opent, komt uit bij de content die hem was beloofd. Deze overdracht is waar producten met twee oppervlakken de meeste gebruikers verliezen, dus behandelen we haar als functie met een eigen engineeringbudget.
Een geauthenticeerde webapp op een bestaande API kost doorgaans 15.000 tot 40.000 dollar over één tot drie maanden — het gepubliceerde webappniveau op onze pagina over webontwikkeling. Een volwaardig tweede oppervlak met realtime data, betalingen of een multi-tenant-structuur wordt als werk op SaaS-niveau geprijsd, meer dan 50.000. De grootste hefboom is je API: een die voor meerdere clients is ontworpen houdt de webbouw slank, terwijl een die app-only stromen aanneemt backendwerk toevoegt dat we expliciet scopen.

Bekijk beide oppervlakken in de casestudy over Formtastic, lees hoe de realtime feed van ExtraETF naar elke client uitwaaiert, of begin bij de pijler webontwikkeling.