3Smiles staat in productie. De website is live op 3smiles.eu, de back office voor de uitbater op app.3smiles.eu, en de Azure-infrastructuur draait met echte abonnementen, echte transactionele e-mail en echte restaurantgegevens. Het is de eerste bedrijfsapplicatie die FlorisNexus oplevert die géén etalagewebsite is — en een goede gelegenheid om eerlijk te vertellen wat zo'n project vraagt.
Het probleem: een simpele vraag kost een tocht door de zaal
In een restaurant zijn de meeste vragen van gasten piepklein: de rekening, een karaf water, een ontbrekend bestek. De kost zit niet in het uitvoeren — die zit in het doorgeven. Een gast steekt zijn hand op, zoekt oogcontact, wacht. Een kelner steekt de zaal over om de vraag alleen maar te horen, en steekt hem daarna nog een keer over om ze uit te voeren.
Het vertrekpunt van het project was dus: er ontbreekt een direct kanaal tussen de tafel en het team. Met drie harde randvoorwaarden. Geen hardware om te installeren — het knopkastje op elke tafel is het antwoord van een concurrent, niet het onze. Niets om te downloaden voor de gast — een restaurant kan een koppel van vijfendertig niet vragen een app te installeren om water te bestellen. En vooral: het menselijke contact niet vervangen, maar het de nutteloze heen-en-weer besparen.
Wat 3Smiles concreet doet
Elke tafel heeft een QR-code. De gast scant die met de camera van zijn telefoon — geen installatie, geen account, geen wachtwoord — en komt op een scherm met de diensten die dit restaurant aanbiedt. Hij kiest er één. De kelner die verantwoordelijk is voor die ruimte krijgt de aanvraag meteen binnen, op tablet of telefoon, met het tafelnummer.
Het is geen digitale menukaart en er worden geen gerechten besteld: het product lost het roepkanaal op, niet het opnemen van de bestelling. Daarachter krijgt de uitbater een volledige back office: zijn vestigingen, zijn ruimtes (terras, zaal, verdieping), zijn tafels, de lijst diensten die hij wil aanbieden, zijn teamleden en zijn abonnement. Alles in drie talen — Frans, Engels en Nederlands — want een Belgisch restaurant bedient die drie op dezelfde avond.
Waarom dit geen etalagewebsite was
We publiceerden eerder een gids die etalagewebsite en bedrijfsapplicatie vergelijkt. 3Smiles is het schoolvoorbeeld van het tweede geval, en de grens is te zien aan vier tekenen.
Er is een toestand om bij te houden. Een dienstaanvraag ontstaat, wordt opgenomen, wordt afgerond of geannuleerd. Een gastsessie start bij het scannen en sluit later af. Een etalagewebsite onthoudt niets.
Er is realtime. Een melding die dertig seconden te laat komt, is nutteloos: de gast heeft zijn hand al opgestoken.
Er zitten meerdere klanten in hetzelfde product. Elk restaurant is een tenant die nooit de gegevens van een ander mag zien.
Er is geld. Een maandelijks of jaarlijks abonnement, mislukte betalingen, facturen, btw.
Elk van die vier punten vermenigvuldigt het werk in vergelijking met een etalagesite. Daarom is de vraag "website of applicatie?" geen woordenspel: ze verandert het budget, de planning en wat er jarenlang onderhouden moet worden.
De technische keuzes — en wat elke keuze beschermt
3Smiles draait op .NET 10, met een gastenscherm en een back office in Blazor WebAssembly, realtime via SignalR, één Azure SQL-database en Azure-infrastructuur volledig beschreven in Bicep. Niets daarvan is mode; elke keuze beschermt iets concreet.
SignalR in plaats van periodiek verversen: de aanvraag komt binnen enkele seconden op het kelnerscherm, zonder dat de app de server voor niets blijft bevragen.
Eén database, afgeschermd per tenant-identificatie in plaats van één database per restaurant: de afschermingsfilters worden globaal toegepast op de datalaag, waardoor "vergeten te filteren" echt moeilijk wordt — en we één keer uitrollen voor alle klanten.
Microsoft Entra External ID voor identiteit: wij bewaren geen wachtwoorden of tokens, MFA is beschikbaar, en het aanvalsoppervlak ligt bij Microsoft in plaats van zelf herschreven te zijn.
Stripe voor het abonnement: er gaan nooit kaartgegevens door de applicatie.
Bicep voor de infrastructuur: de productieomgeving staat in een bestand onder versiebeheer, met daarnaast een gescheiden testomgeving. Precies dat maakt het mogelijk een infrastructuurwijziging te testen zonder te experimenteren op een restaurant dat in volle service zit.
Eerst België, daarna Europa
3Smiles start op de Belgische markt: daar staan de eerste restaurants, en dat is de markt die de projecteigenaar kent. Maar het product is niet gemaakt om daar te stoppen — en dat zit in de architectuur, niet in een verhaal. Eén multi-tenant instantie bedient alle klanten: een extra land is dus geen extra uitrol. De interface is vanaf dag één drietalig, want talen er achteraf inbouwen is de duurste versie van de oefening. Stripe factureert in meer dan 40 landen. En omdat de infrastructuur in Bicep is beschreven, kan ze in een andere Azure-regio opnieuw worden uitgerold zonder herschreven te worden.
De volgorde is bewust: eerst het product bewijzen in een Belgische eetzaal, dan uitbreiden naar Europa — en waarom niet verder. Producten die vanaf dag één de hele wereld willen aanspreken, overtuigen doorgaans niemand in het bijzonder.
Wat de zaal aan het product veranderde
Het leerrijkste deel van het project is niet de architectuur — het is de lijst dingen die geen enkele specificatie had voorzien.
De volgorde van de ruimtes. De lijst met ruimtes stond alfabetisch. Gevolg: een uitbater wiens hoofdzaal "Terras" heet, zag die altijd in de laatste kolom van het kelnerscherm, zonder enige manier om ze naar voren te halen. Er moest een volgorde komen die de uitbater zelf bepaalt.
Pijltjes, geen drag-and-drop. Om die lijst te herschikken is drag-and-drop de reflex van een ontwikkelaar. Slecht idee: de bijhorende events vuren niet bij aanraking in de meeste mobiele browsers, en deze back office wordt rechtstaand op een tablet in de zaal gebruikt. Twee pijltjes doen het werk en werken overal.
De QR-code opnieuw scannen. Een gast scant de code halverwege de maaltijd opnieuw, of zijn tafelgenoot scant dezelfde tafel. De levenscyclus van sessies en aanvragen vroeg meerdere rondes voordat ze in al die gevallen juist zat.
De geweigerde betaling. Een kaart die vervalt mag de dienst van een restaurant niet midden in een drukke avond afsnijden: er kwam een respijtperiode in de facturatie. Het juiste technische antwoord op een mislukte betaling is zelden "onmiddellijk blokkeren".
Live gaan is niet hetzelfde als uitrollen
Dat is de les die me het meest bijblijft. De code werkte al lang toen de livegang begon. Wat die fase echt vulde, was onzichtbaar voor de gebruiker:
Een eigen verzenddomein. De uitnodigingen vertrokken van een automatisch gegenereerd Azure-adres — precies het type afzender dat een uitbater als spam wegzet zonder te openen. Overschakelen naar een adres op het domein van de klant vroeg een apart subdomein en propere DNS voor e-mailauthenticatie, om de bestaande professionele mailbox niet te breken.
De back office buiten de zoekmachines. De applicatie had noch een robots.txt noch een gelijkwaardige header — en het ontbreken van dat bestand staat crawlen toe in plaats van het te verbieden.
Beveiligingsheaders die echt worden meegegeven. Die van de etalagesite waren correct geschreven maar werden in productie nooit uitgeleverd, omdat het configuratiebestand niet in de gepubliceerde map zat. Geschreven ≠ uitgerold: je moet het op de productie-URL nakijken.
Capaciteit en migraties. Productie op het juiste hostingplan zetten, en ervoor zorgen dat een databasemigratie niet te vroeg op productie kan worden toegepast.
De juridische basis. Gebruiksvoorwaarden, privacyverklaring, wettelijke vermeldingen en een verwerkersovereenkomst in drie talen, met een aanvaarding die bij de eerste aanmelding van de manager wordt bewaard met tijdstip en versie. Bij een product dat gegevens verwerkt voor andere ondernemingen is dat geen formaliteit voor het einde van het project.
Geen van die punten komt in een demo aan bod. Alle zijn blokkerend voor een echte lancering. Als een leverancier je vertelt dat een bedrijfsapplicatie "klaar" is zonder deze onderwerpen te hebben besproken, is ze dat niet.
Wat we meten, en wat we nog niet hebben
De site van 3Smiles wordt zoals al onze projecten in productie gemeten met Lighthouse: 97 voor prestaties, 97 voor toegankelijkheid, 100 voor best practices en 100 voor SEO op desktop; 86, 96, 100 en 100 op mobiel (mediaan van drie metingen, 10 augustus 2026). We publiceren die cijfers ruw, ook wanneer ze niet flatteren, op onze pagina realisaties.
Wat we vandaag níet publiceren, zijn gebruikscijfers: uitgespaarde wachttijd, aanvragen per service, tevredenheid van gasten. Het product is net in productie gegaan. Die metingen bestaan pas nadat ze weken lang in de zaal zijn vastgesteld — niet eerder. Een verzonnen of geëxtrapoleerd cijfer is precies het detail dat de rest van een klantcase ongeloofwaardig maakt.
Wat dit project over het jouwe zegt
Ben je zelfstandig, winkelier of kmo-verantwoordelijke in België en heb je een concrete wrijving in je vak ontdekt — een oproep die niet bij de juiste persoon aankomt, informatie die drie keer wordt overgetypt, een planning op papier — dan gelden drie lessen uit dit project ook voor jou.
Begin bij de wrijving, niet bij de functie. 3Smiles doet niet "alles wat een restaurant zou kunnen willen". Het schrapt één heen-en-terugweg. Een smalle, echt nuttige scope raakt opgeleverd; een wenslijst nooit.
De zaal haalt het altijd van de mockup. De belangrijkste correcties in dit project kwamen van een tablet in de hand in een eetzaal, niet uit een vergadering.
Reken de onzichtbare fase mee. Domeinen, e-mail, beveiliging, GDPR, facturatie: zet ze van het begin in de planning, of ze duwen je lancering weken vooruit.
En nog één punt waarop FlorisNexus niet toegeeft: de infrastructuur en de accounts blijven op naam van de klant. Het Azure-abonnement van 3Smiles is van de projecteigenaar, niet van ons. Je moet van leverancier kunnen veranderen zonder van product te veranderen.