Live Dating Platform
En medlemsbaserad prenumerationsprodukt för dejtning — två klienter på en backend, med riktiga video- och röstsamtal i appen. Registrering och modererad bilduppladdning, en swipe-kortlek med avstånds- och preferensfiltrering, race condition-säker matchning, chatt i realtid, WebRTC-samtal och återkommande fakturering — inbäddat i en Trust & Safety-stack som de flesta dejtingappar lägger till alldeles för sent.
01Översikt
En medlemsbaserad dejtingplattform byggd som två klienter över en enda backend: en fullfjädrad Next.js-webbapp (medlemmar och adminpanelen) och en Expo / React Native-app som pratar med samma API via Bearer-tokens. En medlemsresa — registrera dig, bygg en profil, få den primära bilden genom moderering, bläddra, matcha, chatta och ring samtal ansikte mot ansikte — körs identiskt på webben och i din ficka, och samma återkommande prenumeration låser upp de betalda funktionerna på båda.
Den intressanta delen är inte swipe-kortleken. Det är att en konsumentprodukt som hanterar privata användarbilder, betalningar, meddelanden mellan främlingar och live peer-to-peer-samtal byggdes med kontroller för trygghet, säkerhet och missbruk — AI-moderering, privat media, upprätthållande av bannlysningar/blockeringar, rate limiting, verifiering — designat från databasschemat och uppåt, istället för att eftermonteras efter den första incidenten.
02Problemet den löser
En dejtingapp är bedrägligt djup. Bakom kortleken finns identitets- och sessionssäkerhet, betalningar, en matchningsmotor som inte får dubbelexekvera under belastning, meddelanden i realtid, livesamtal som måste ta sig igenom NAT, och — den del som sänker de flesta lanseringar av sociala konsumentappar — en säkerhetsyta: moderering innan innehåll publiceras, privat media som aldrig läcker, blockering och rapportering som faktiskt håller, hastighetsbegränsningar som dämpar missbruk, samt en väg till verklig ålders- och identitetsverifiering. Bygg det i efterhand och du lanserar en säkerhetsrisk.
Resultat en prenumerationsprodukt för dejtning som lanseras med samtal, moderering, säkerhet och betalningsmaskineri som normalt skjuts upp — webb och native från dag ett, på en backend.
03Vad vi byggde
Konton & identitet
Handskriven autentisering för inloggningsuppgifter — bcrypt plus en signerad JWT (jose) i en httpOnly-cookie — som blockerar åtkomst som standard (fails closed) om autentiseringshemligheten inte är inställd. Tokens bär på en tokenVersion så att "logga ut överallt" och bannlysningar omedelbart återkallar varje aktiv session. Engångs-, hashade, utlöpande tokens driver e-postverifiering och enumereringssäker lösenordsåterställning. OAuth (Google, Facebook, Instagram) använder authorization-code-flödet med state-cookie CSRF och kopplar samman identiteter via e-post — ingen SDK. Kontoborttagning sker via en soft-delete-frist: döljs och loggas ut omedelbart, kan återställas genom att logga in igen, och raderas permanent senare av ett dagligt cron-jobb.
Profiler, upptäckt & matchning
Rika profiler — pronomen, längd, kroppstyp, läggning, mål, intressen och promptkort — med en modererad primärbild begränsad av PENDING / APPROVED / REJECTED och en banner för medlemmen som förklarar synligheten. Upptäckt filtrerar ömsesidigt på kön och åldersintervall, respekterar preferenser (mål, kroppstyper, längd, rökare) och geokodar varje stad till koordinater för avståndsfiltrering. Kortleken stöder gilla / passa / supergilla och ångra (rewind); matchningar bildas på en kanonisk, race condition-säker parnyckel så att en samtidig ömsesidig gillning aldrig kan skapa två matchningar. Runtomkring det: vem som gillat dig, vem som tittat på dig, dagliga val (en deterministisk daglig blandning), avmatcha och ett semester-/pausläge.
Realtidschatt & livesamtal
Per-match-konversationer strömmas över Server-Sent Events på webben (native-appen använder polling), med skrivindikatorer, olästa-brickor, läsmarkörer och röst- och videomeddelanden tillsammans med text. Ovanpå samma per-match-kanal ligger verkliga WebRTC-video- och röstsamtal: en signaleringsslutpunkt förmedlar SDP offer/answer och ICE-kandidater mellan de två parterna, en ICE-konfigurationsslutpunkt delar ut STUN plus tidsbegränsade HMAC TURN-inloggningsuppgifter (så att samtal ansluts även bakom symmetrisk NAT), och ett inkommande samtal väcker den andra enheten via push-notis. Native-klienten kör en fullständig RTCPeerConnection med ljud av, kamera på/av och växling mellan fram/bak; vilken sida som helst kan lägga på med en angiven anledning (nekad / upptagen / avslutad / timeout).
Moderering & media-pipeline
Varje uppladdad bild körs genom en pluggbar AI-moderering (OpenAI:s omni-modereringsmodell): grova policyöverträdelser avvisas direkt, allt annat riskbedöms och går vidare till en kö för mänsklig granskning — och systemet är öppet (fails open) för mänsklig granskning istället för att blockera legitima uppladdningar. Accepterade bilder omkodas med sharp — roteras automatiskt från EXIF, rensas från EXIF för integritet, och sparas som en kompakt huvudbild plus en miniatyrbild.
Prenumerationer & fakturering
Stripe Checkout för den återkommande månadsplanen, en faktureringsportal och en webhook som synkroniserar prenumerationsstatus — inklusive PAST_DUE — tillbaka till medlemmen. Tre nivåer (FREE / PLUS / PREMIUM) driver en kapacitetsmatris: supergilla per dag, vem som tittat på dig, dagliga val, ångra (rewind), läskvitton, avancerade filter och ett inkognito-surfläge. Nivån spåras oberoende av prenumerationsstatus, så en avbruten medlem behåller sin nivå fram till periodens slut. En utvecklar-bypass och lokala kampanjkoder låter hela flödet köras utan skarpa Stripe-nycklar.
04Trygghet, säkerhet & adminpanelen
Medlemsbilder lever utanför webbroten och serveras endast via en autentiserad rutt som omkontrollerar sessionen (bannlysta/återkallade användare avvisas) och auktoriserar per bild: ägaren alltid, annars endast en aktiv medlem som inte är blockerad eller bannlyst — private, nosniff, aldrig läsbart för allmänheten, säkert mot path traversal. Uppladdningar valideras genom magic bytes, inte den klientdeklarerade MIME-typen, för bilder, ljud och video, vilket förhindrar content-type-spoofing och SVG-skripttrick. CSRF upprätthålls genom en same-origin-kontroll på varje muterande rutt utöver SameSite=Lax; rate limits (hastighetsbegränsningar) täcker inloggning, registrering, uppladdning, gilla, meddelande, blockering, rapportering och samtalssignalering. En enda vakt upprätthåller blockeringar och bannlysningar överallt — bläddring, gillningar, matchningar, chatt, samtal och media. Medlemmar kan blockera (åt båda håll) och rapportera; KYC-redo ålders- och selfiefotoverifiering visas som profilbrickor. Administratörer får ett separat, CSRF-skyddat område med 404-svar för icke-administratörer — dashboard, en modereringskö för primärbilder, granskning av fotoverifiering, hantering av rapporter (avvisa / lös / lös&bannlys) och användarverktyg (bannlys / häv bannlysning / återkalla sessioner) — och varje administratörsåtgärd landar i en oföränderlig granskningslogg.
05Teknik
06Höjdpunkter
- WebRTC-video- & röstsamtal i appen — SDP/ICE-signalering över matchningskanalen, tidsbegränsade HMAC TURN-uppgifter, push-väckta inkommande samtal, native peer-anslutning med ljudavstängning och kameraväxling.
- Två klienter, en backend — fullständig medlemsresa på Next.js-webb och en Expo/React Native-app över ett Bearer-token-API.
- AI-bildmoderering på varje uppladdning (direkt avslag + riskbedömd kö för mänsklig granskning), som tillåter granskning istället för att blockera felaktigt (fails open).
- Privat media med åtkomstkontroll: lagras utanför webbroten, auktorisering per bild, EXIF-rensad
sharp-pipeline, validering av magic bytes för bild/ljud/video. - Race condition-säker matchning på en kanonisk parnyckel; gilla / passa / supergilla, ångra (rewind), vem som gillat dig, vem som tittat på dig och dagliga val.
- Realtidschatt via SSE med skrivindikatorer, läsmarkörer och röst-/videomeddelanden; elegant hantering av blockeringar/bannlysningar/utgångstider.
- Stripe-prenumerationer med tillståndssynkronisering via webhook och PAST_DUE-hantering; FREE/PLUS/PREMIUM-kapacitetsmatris inkl. inkognitoläge.
- Autentisering via inloggningsuppgifter som blockerar åtkomst som standard (fails closed); återkallelse av sessioner via
tokenVersion; adminpanel med en oföränderlig granskningslogg; soft-delete med återställning + rensning via cron.