← Terug naar projects
9 min
StaticForm: formulierverwerker met spamfiltering en volledig inzicht

StaticForm: formulierverwerker met spamfiltering en volledig inzicht

Formulierverwerking voor websites, met meer dan tien spamcontroles, een volledig actielogboek en directe meldingen als er iets misgaat. Ontstaan uit frustratie over het telkens opnieuw bouwen van dezelfde formulierverwerker voor klanten. Inmiddels in gebruik bij developers en agencies die formulieren beheren voor meerdere sites.
  • .NET
  • C#
  • Nuxt

Inhoudsopgave

  1. Twee problemen die eenvoudig lijken tot ze dat niet zijn
  2. De oplossing: StaticForm
  3. Wat ik heb gebouwd
  4. Spamfiltering
  5. Volledig Inzicht
  6. Notificaties en bezorging
  7. Eenvoudige integratie
  8. Het technische fundament
  9. Gebouwd voor het beheren van meerdere sites
  10. Wat ik heb geleerd
  11. Huidige status

Bij het bouwen van websites voor klanten liep ik telkens tegen dezelfde twee problemen aan. Het eerste was spam. Contactformulieren, nieuwsbriefinschrijvingen, sollicitatieformulieren: ze trokken allemaal bots aan zodra ze live gingen. Klanten belden om te zeggen dat ze tientallen inzendingen per dag kregen, waarvan er vrijwel geen enkele echt was. Het tweede probleem was subtieler: formulieren die er prima uitzagen maar het niet waren. E-mails of webhooks werden niet afgeleverd en niemand merkte het, totdat een klant vroeg waarom ze al weken niets van klanten hadden gehoord.

Veel projecten hadden een formulierverwerker nodig, en elke formulierverwerker vroeg om spambescherming, betrouwbare bezorging en een manier om te weten wanneer er iets misging. Ik bouwde telkens dezelfde oplossing opnieuw. Daarom heb ik StaticForm gebouwd.

Twee problemen die eenvoudig lijken tot ze dat niet zijn

Vrijwel elke website heeft formulieren nodig. Een HTML-formulier bouwen kost minuten. Het betrouwbaar maken is waar het echte werk begint.

Spam was het meest zichtbare probleem. Binnen dagen na het live gaan van een formulier begon de inbox vol te lopen met rommel. Bots bestoken publieke endpoints continu, en hun inzendingen zijn niet te onderscheiden van echte berichten. Zo’n 95% van het formulierverkeer op het web is spam, en je weet het pas als je elk bericht apart opent en leest, dus dat was grotendeels wat klanten zaten te doen. Daardoor voelde het formulier nutteloos aan, ook al werkte het technisch gewoon.

Het tweede probleem was stiller van aard, en daardoor lastiger op te merken. Een formulier kon volledig kapot zijn zonder dat iemand het doorhad. E-mailbezorging mislukte zonder enige foutmelding. Een webhook tikte een timeout aan. Het formulier toonde nog steeds “bedankt” aan wie het invulde, maar de inzending verdween gewoon. Ik had klanten die weken lang niet doorhadden dat er geen aanvragen meer binnenkwamen, niet omdat niemand contact opnam, maar omdat niets meer aankwam.

Daarboven op had ik bij elk project ook te maken met versnippering over platforms. Static site generators, WordPress, GitHub Pages, Netlify en Vercel vragen allemaal dezelfde backendoplossing, maar via totaal verschillende routes. En elke oplossing stond los van de andere, zonder gedeeld overzicht.

De oplossing: StaticForm

Ik heb StaticForm gebouwd om dit allemaal op één plek te regelen. Het idee is eenvoudig: stel een formulier in via het dashboard, kopieer de endpoint-URL en zet die in het action-attribuut van je formulier. Je kiest waar inzendingen naartoe moeten (e-mail, Slack, Discord, een webhook) en StaticForm regelt de rest, inclusief het opslaan van de inzending in Europa ongeacht of de notificatie aankomt. De hele setup duurt zo’n vijf minuten.

StaticForm inzendingen inbox

Wat ik heb gebouwd

StaticForm bouwen draaide om één ding: alle storingen aanpakken die in de praktijk voor problemen zorgen, terwijl de setup eenvoudig genoeg blijft om er niet over na te hoeven denken.

Spamfiltering

Spambescherming werd het onderdeel waar ik verreweg de meeste tijd aan besteedde, omdat het het moeilijkst goed te doen is op schaal. Er draaien nu meer dan tien controles op elke inzending: lokvelden die eenvoudige bots vangen, blokkering op basis van IP-reputatie, detectie van datacenter-IP-adressen (de meeste bots draaien via cloudproviders, niet via thuisverbindingen), filtering op wegwerp-e-mailadressen, controles op domeinleeftijd, e-maildomeinvalidatie, inhoudsanalyse op verdachte patronen, en detectie van ongewenste verkoopberichten: het soort “ik zag dat uw website beter gevonden kan worden in Google”-berichten dat grotendeels uit automatisch gegenereerde sjablonen bestaat.

Wat ik bijzonder interessant vind is de misleidingslaag. StaticForm stuurt spam-inzendingen een 200 OK terug in plaats van een fout. Bots die fouten krijgen passen zich aan; ze proberen andere payloads, wisselen van IP, veranderen tactiek. Bots die een 200 OK krijgen denken dat ze geslaagd zijn en gaan door. Na verloop van tijd versterkt dit effect zich: spambronnen stoppen met het aanvallen van je endpoint zonder te weten dat ze gefilterd worden. Onderschepte inzendingen verdwijnen voordat ze een notificatiekanaal bereiken.

Spaminzending detail met filteringsreden

Volledig Inzicht

Het probleem dat ik telkens tegenkwam met bestaande formuliertools was niet alleen spam, maar ook het gebrek aan zicht op wat er fout ging. E-mailbezorging mislukt stilletjes. Webhooks lopen vast zonder dat iemand een melding krijgt. Een inzending komt nergens terecht, en niemand weet het totdat een klant meldt dat hij al twee weken niets van klanten heeft gehoord.

StaticForm legt elke actie per inzending vast, met resultaat en eventuele foutdetails. Als e-mailbezorging mislukt, zie je precies waarom (SMTP-fout, mailbox vol, geweigerd door de ontvangende server) en wanneer het gebeurde. Als een webhook uitvalt, staat dat er ook bij. Bij een storing krijg je meteen een melding, niet pas wanneer de klant erover begint.

Elke inzending wordt eerst opgeslagen, voordat er een notificatie uitgaat. Daardoor kun je een mislukte notificatie met één klik opnieuw versturen vanuit het dashboard, naar een inzending die op het moment van binnenkomst al veilig was weggeschreven. Niets gaat verloren doordat een afhankelijke dienst een slechte dag had.

Actielogboek met bezorgingsfout details

Notificaties en bezorging

E-mail valt vaker uit dan mensen denken. SMTP-servers gaan offline, inboxen lopen vol, berichten belanden in de spammap. Daarom ondersteunt StaticForm meerdere notificatiekanalen tegelijk. Je kunt inzendingen sturen naar e-mail én Slack én Discord én een eigen webhook, welke combinatie ook het meest logisch is voor het project.

Je kunt naast formulierinzendingen ook bestanden ontvangen. Sollicitaties met cv’s, contactformulieren met bijlagen, alles waarbij je documenten wilt ontvangen. Bestanden worden veilig opgeslagen en zijn te downloaden via het dashboard.

Acties configureren voor meerdere notificatiekanalen

Eenvoudige integratie

Voor een developer is de integratie simpelweg een HTML-formulier dat naar een endpoint-URL wijst. Je bouwt het formulier zoals je dat altijd zou doen, en StaticForm neemt het daarna over. Het dashboard genereert kant-en-klare code voor plain HTML en een versie met het staticform.js-hulpscript dat validatie, laadindicatie en foutmeldingen meteen afhandelt. Voor framework-specifieke code is er ook een kant-en-klare AI-prompt die je aan Claude, Codex of een andere AI-assistent naar keuze kunt geven. Het werkt op Jekyll, Hugo, Gatsby, Next.js, Astro, GitHub Pages, Netlify, Vercel, Cloudflare Pages, WordPress, of elk platform dat een POST request naar een endpoint kan versturen.

Integratievenster met gegenereerde code snippets

Het technische fundament

Achter die eenvoudige setup zit infrastructuur die is gebouwd op betrouwbaarheid. De API-gateway verwerkt elke inzending met snelheidsbegrenzing, validatie en wachtrijverwerking. Bij verkeerspieken gaat niets verloren. Als een afhankelijke dienst traag is, wachten inzendingen in de wachtrij totdat verwerking mogelijk is.

De architectuur is gebouwd rond één principe: data wordt altijd als eerste opgeslagen. Pas daarna gaan notificaties uit. Zelfs als het volledige notificatiesysteem uitvalt, gaat er geen inzending verloren.

Alles draait in containers via CI/CD-pipelines. De infrastructuur is volledig in code vastgelegd, zodat het volledige platform herstelbaar is vanuit configuratiebestanden. Monitoring en alerting draaien dag en nacht. Het platform haalt 99,9% uptime doordat het is gebouwd om storingen op te vangen: services herstarten automatisch, wachtrijen bufferen verkeerspieken, databaseverbindingen zijn gepoold en snelheidsbegrenzing voorkomt misbruik.

Gebouwd voor het beheren van meerdere sites

Het dashboard is ook ingericht voor het beheren van veel formulieren en klanten vanuit één plek. Elk formulier is te taggen per klant of site, zodat je één overzicht hebt van alle klantformulieren (inzendingen, statussen, recente fouten) zonder van account te wisselen. Je kunt klanten uitnodigen zodat ze zelf toegang hebben, of notificaties rechtstreeks naar hen sturen zodat ze op de hoogte blijven zonder in te hoeven loggen, of beide.

Hier is volledig inzicht het allerbelangrijkst. Als het formulier van een klant stilletjes stukgaat, laat het actielogboek dat zien. Je kunt het probleem oplossen voordat de klant het merkt. En omdat je een vast maandelijks bedrag betaalt ongeacht hoeveel formulieren of klanten je toevoegt, zijn de kosten per project voor formulierverwerking feitelijk nul.

Dashboard overzicht van meerdere formulieren en klanten

Wat ik heb geleerd

StaticForm bouwen liet me zien dat productwerk fundamenteel anders is dan klantwerk:

Productbeslissingen zijn moeilijker dan technische keuzes. De technologiekeuzes waren eenvoudig. Het moeilijke was de prijs bepalen, uitvinden welke functies er echt toe doen en beslissen wat prioriteit krijgt. Er is geen klant die je dat vertelt, in elk geval niet als je net begint.

Marketing is lastiger dan bouwen. Een formulierverwerker bouwen kan ik in een paar weken. Mensen genoeg vertrouwen geven om het ook echt te gebruiken? Dat is de echte uitdaging. Ik leer waarde te bieden op platforms zoals Reddit, contact te leggen met agencies, developers en communities, en echte gesprekken het werk te laten doen.

Onderhoud stopt nooit. Klantprojecten hebben vaak een duidelijk eindpunt. Een SaaS-product draait voor altijd. Elke gebruiker verwacht 99,9% uptime. Die verantwoordelijkheid kleurt alles.

Eenvoud wint van features. Mijn eerste neiging was zoveel mogelijk functies inbouwen. Maar wat StaticForm nuttig maakt, is dat het een paar dingen extreem goed doet. Minder complexiteit betekent meer betrouwbaarheid.

De prijs telt. Ik begon met een creditmodel waarbij spam niet meetelde voor het saldo van de klant. Een redelijke aanpak, maar het zorgde voor wrijving; potentiële gebruikers moesten van tevoren inschatten hoeveel credits ze nodig hadden. Het huidige model is gebouwd rond het idee van betalen voor functies, niet voor inzendingen. Beide abonnementen bevatten onbeperkte inzendingen en formulieren. Wat wél begrensd is, zijn onderdelen met echte kosten per eenheid: e-mailacties (25.000 per maand op Starter, onbeperkt op Pro) en bestandsopslag. Spam telt nooit mee voor die grenzen. Dat geeft de juiste prikkel: ik heb er alle belang bij om spam goed te filteren, want wat er toch doorheen glipt kost mij geld, niet de klant.

Huidige status

StaticForm is live en verwerkt inzendingen voor betalende klanten in meerdere landen. Het platform haalt 99,9% uptime en verwerkt alles van eenvoudige contactformulieren tot complexe sollicitaties met bestandsuploads.

De prijsstelling is een vast maandelijks bedrag met onbeperkte inzendingen. Uitproberen kan zonder creditcard. Een WordPress-plugin is in ontwikkeling voor sites die een native CMS-integratie willen.

Het doel blijft hetzelfde: spam die wordt tegengehouden, volledig inzicht in elke inzending, een eerlijk tarief zonder verrassingen en een integratie die in minuten staat. Bekijken kan op staticform.app.

Feedback, feature requests en ervaringen zijn altijd welkom. Neem gerust contact op bij ideeën of problemen.