G.STANCUTA
Publicat · 2026 · 05 · 278 min de citit

Better Auth și Resend: autentificare pe care un dezvoltator solo o poate livra cu adevărat

  • auth
  • email
  • better-auth
  • resend

Auth self-hosted cu Better Auth, email tranzacțional cu Resend. Fără vendor lock-in, fără costuri ascunse și o configurare pe care un agent AI de programare o poate reproduce dintr-un fișier markdown.

Autentificarea este partea fiecărui proiect care pare simplă până când ești la trei zile distanță și depanezi bucle de redirect OAuth la miezul nopții. Cerința mea pentru NearYou era clară: autentificare cu email și parolă, login social cu Google, verificare email, resetare parolă, doi factori pe viitor și zero costuri lunare pentru un serviciu care ar putea sta inactiv săptămâni în timpul dezvoltării timpurii. Better Auth plus Resend este acel stack. Îți arăt exact cum se îmbină.

De ce Better Auth

Better Auth este o bibliotecă de autentificare self-hosted pentru ecosistemul JavaScript. O instalezi ca pachet, o conectezi la baza de date existentă printr-un adapter și deții întreaga tabelă de sesiuni și utilizatori. Niciun serviciu extern de autentificare nu sună acasă. Niciun preț per utilizator activ lunar care te surprinde când o postare devine virală. Nicio migrare de la vendor când prețurile se schimbă.

Setul de funcționalități este pregătit pentru producție de la bun început: email și parolă, provideri sociali (Google, Facebook, GitHub și altele), verificare email, resetare parolă, autentificare cu doi factori prin TOTP și un adapter Prisma care generează automat modelele de schemă necesare. Sesiunile sunt stocate în propria ta bază de date. Rotația tokenurilor este gestionată. Biblioteca client include hookuri tipizate pentru React și alte framework-uri, astfel încât să nu scrii propria logică useSession.

Singurul lucru pe care Better Auth nu îl include este livrarea email-urilor. Expune hookuri, tu conectezi transportul. Aceasta este separarea corectă: logica de autentificare rămâne în Better Auth, livrarea merge la un serviciu construit exact pentru acel scop.

Schemă izometrică a Better Auth poziționat între aplicație și baza de date, cu o săgeată spre Resend pentru livrarea email-urilor de ieșire
Better Auth deține sesiunile și utilizatorii. Resend deține livrarea. Aplicația nu deține niciunul direct.

De ce Resend pentru email tranzacțional

Resend este un serviciu de email tranzacțional orientat spre dezvoltatori. Nivelul gratuit oferă 3.000 de email-uri pe lună și 100 pe zi, ceea ce acoperă confortabil orice proiect în stadiu timpuriu. Prețurile plătite sunt suficient de mici pentru a nu-ți face griji până nu ai o bază reală de utilizatori. API-ul este un singur apel de funcție. Nicio configurare SMTP, niciun coșmar de headere de autentificare, niciun XML nicăieri.

Cerințele sunt minimale dar non-negociabile. Ai nevoie de un domeniu de trimitere pe care îl controlezi. Trebuie să adaugi trei înregistrări DNS la acel domeniu: o înregistrare SPF, o cheie DKIM pe care Resend o generează pentru tine și o politică DMARC. Ai nevoie de o cheie API din dashboard-ul Resend. Și ai nevoie de o adresă from clară și consecventă care să corespundă domeniului tău verificat. Odată ce acestea sunt la locul lor, livrarea funcționează și plasarea în inbox este solidă.

Conectarea apelului Resend

SDK-ul Resend pentru Node este un mic wrapper în jurul API-ului lor REST. Instalează-l cu npm install resend, exportă o funcție tipizată per tip de email și apeleaz-o din hookurile tale Better Auth. Disciplina cheie: nu construi niciodată șiruri HTML inline în configurația auth. Mută-le într-un modul dedicat lib/email.ts astfel încât să fie testabil și înlocuibil.

ts
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendVerificationEmail(to: string, url: string) {
  await resend.emails.send({
    from: 'NearYou <noreply@mail.nearyou.app>',
    to,
    subject: 'Verify your email address',
    html:
      '<p>Click the link below to verify your account:</p>' +
      '<p><a href="' + url + '">' + url + '</a></p>',
  });
}

Păstrează RESEND_API_KEY în fișierul tău .env și nu o commite niciodată. Adresa from trebuie să corespundă exact domeniului tău verificat. Dacă schimbi domeniul de trimitere mai târziu, actualizează acest șir și reverificați în dashboard-ul Resend. Funcția este deliberat simplă: un apel de trimitere, o suprafață de eroare. Adaugă gestionare corectă a erorilor și logging înainte de a merge în producție.

Conectarea Better Auth să o folosească

Configurarea Better Auth trăiește într-un singur fișier auth.ts la rădăcina proiectului sau în lib/. Blocul emailVerification este locul unde îți transmiți funcția de trimitere. Hookul primește obiectul utilizator și un URL de verificare pre-construit. Le transmiți pe ambele la wrapper-ul tău Resend. URL-ul este semnat și limitat în timp intern de Better Auth, deci nu gestionezi tu însuți tokenurile.

ts
import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma';
import { prisma } from './lib/prisma';
import { sendVerificationEmail } from './lib/email';

export const auth = betterAuth({
  database: prismaAdapter(prisma, { provider: 'mysql' }),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
  },
  emailVerification: {
    sendOnSignUp: true,
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user, url }) => {
      await sendVerificationEmail(user.email, url);
    },
  },
});

Flag-ul requireEmailVerification: true blochează autentificarea până când email-ul este confirmat. autoSignInAfterVerification: true înseamnă că utilizatorul ajunge în aplicație imediat după ce face clic pe link-ul din inbox, fără un al doilea pas de autentificare. Această combinație îți oferă un flux de onboarding curat cu cod minim.

  • Resetare parolă: adaugă sendResetPassword la blocul emailAndPassword, același model ca hookul de verificare.
  • Provideri sociali: setează google.clientId și google.clientSecret din mediu. Better Auth gestionează automat ruta de callback OAuth.
  • Doi factori: adaugă import { twoFactor } from "better-auth/plugins" și include-l în array-ul plugins. Better Auth livrează logica TOTP.
  • Expirare sesiune: setează session.expiresIn și session.updateAge pentru a controla cât timp trăiesc tokenurile și când se reîmprospătează automat.

Cerințe DNS: partea care te blochează

Livrabilitatea email-urilor trăiește și moare cu DNS. Resend nu va trimite de la un domeniu neverificat. Chiar dacă ocolești cumva această verificare, email-urile ajung în spam fără alinierea SPF și DKIM. Acesta este singurul pas cu o perioadă reală de așteptare: modificările DNS pot dura până la 48 de ore pentru a se propaga global, deși în practică este de obicei sub o oră cu registratorii moderni.

Cele trei înregistrări de care ai nevoie pe subdomeniul tău de trimitere: SPF spune serverelor receptoare ce gazde au voie să trimită pentru domeniul tău. DKIM atașează o semnătură criptografică la mesajele de ieșire astfel încât destinatarii să poată verifica că nu au fost modificate. DMARC spune serverelor receptoare ce să facă când verificările SPF sau DKIM eșuează. Resend îți arată valorile exacte de lipit în furnizorul tău DNS după ce adaugi domeniul.

Schemă a unui agent AI care citește un fișier AGENTS.md cu domeniu de trimitere, adresă from și checklist DNS, apoi configurează corect setările de email
Fișierul de memorie markdown este sursa unică de adevăr pentru configurarea email-ului. Agentul îl citește, nu variabilele de mediu pe care nu le poate vedea.

Persistarea configurației într-un fișier de memorie markdown

Folosesc Claude Code ca agent AI de programare pe NearYou. Agentul scrie configurații auth, conectează hookuri de email, actualizează fișiere de mediu și depanează probleme de livrare. Pentru ca aceasta să funcționeze fiabil între sesiuni, agentul are nevoie de memorie persistentă a configurației exacte de email: care domeniu este verificat, care este adresa from, ce înregistrări DNS sunt în vigoare și care sunt numele variabilelor de mediu.

Fără un fișier de memorie, agentul trebuie să întrebe, să deducă sau să ghicească de fiecare dată când începe o nouă sesiune. Ar putea folosi adresa from greșită, referenția un domeniu neverificat sau conecta hookul la o variabilă de mediu cu un nume diferit față de ceea ce este de fapt în .env. Acestea sunt greșeli mici care costă timp real de depanare.

Soluția este o secțiune scurtă și precisă în AGENTS.md-ul proiectului (sau un .claude/email.md dedicat dacă proiectul este mare). Păstrează acolo domeniul de trimitere, adresa from, checklista înregistrărilor DNS și notele de conectare a hookurilor. Agentul citește acest fișier la pornirea sesiunii și operează configurarea email-ului corect la prima încercare, de fiecare dată.

md
## Auth + Email (Better Auth + Resend)

Sending domain: mail.nearyou.app
From address:   noreply@mail.nearyou.app
Resend API key: env var RESEND_API_KEY

### DNS records required on mail.nearyou.app
- SPF:   TXT  "v=spf1 include:amazonses.com ~all"
- DKIM:  TXT  resend._domainkey  <value from Resend dashboard>
- DMARC: TXT  _dmarc  "v=DMARC1; p=quarantine; rua=mailto:dmarc@nearyou.app"

### Email hooks wired in auth.ts
- emailVerification.sendVerificationEmail  -> sendVerificationEmail()
- emailAndPassword.sendResetPassword       -> sendPasswordResetEmail()

### Gotchas
- Resend requires the from domain to be verified before any email sends.
- DNS propagation can take up to 48h; verify in the Resend dashboard.
- Always set autoSignInAfterVerification: true so the UX is not broken post-verify.
- Never hardcode the from address; keep it in this file so the agent reads it.

Acest fișier este diferența dintre un agent care configurează cu încredere stack-ul tău de email și unul care îți pune trei întrebări înainte de a scrie o singură linie. Nu este documentație pentru oameni. Este un document de context compact pentru un sistem care nu poate vedea dashboard-ul tău Resend, înregistrările tale DNS sau fișierul tău .env. Fiecare linie din el își câștigă locul prevenind o greșeală reală.

Stack-ul complet în producție

Pe NearYou, Better Auth și Resend sunt în producție de la primii utilizatori beta. Fluxul auth: înregistrare cu email și parolă sau Google, primire a unui email de verificare trimis prin Resend în câteva secunde, clic pe link, aterizare în aplicație. Resetarea parolei folosește același wrapper Resend. Doi factori prin TOTP este conectat dar opțional pentru utilizatori. Întreaga suprafață auth este self-hosted, nicio dependență de vendor în afara Resend pentru livrare.

Costul operațional este neglijabil. Nivelul gratuit Resend gestionează baza actuală de utilizatori cu marjă. Când depășește limita gratuită, costul per email este suficient de mic pentru a rămâne o eroare de rotunjire în bugetul de infrastructură. Better Auth nu are absolut niciun cost per utilizator. Compară asta cu prețurile Auth0 sau Clerk la scară și calculul nu este nici măcar aproape.

Cea mai bună configurare auth este cea pe care o deții, o înțelegi și o poți depana la 2 noaptea fără a deschide un tichet de suport la vendor.

Dacă construiești un nou proiect JavaScript sau TypeScript și ai nevoie de autentificare, începe de aici. Instalează Better Auth, conectează-l la baza ta de date Prisma existentă, adaugă wrapper-ul Resend, adaugă înregistrările DNS și completează-ți AGENTS.md. Vei avea un sistem de autentificare funcțional, pregătit pentru producție în jumătate de zi, și nu te vei gândi deloc la el în următorul an.

Portofoliu · Indicator
Desenat de
G. STANCUTA
Disciplină
AI & AUTOMATION
Locație
MORTER · SÜDTIROL
Stare
Disponibil
Limbi
IT · EN · RO · DE+
Stack
PLOI · HETZNER
Revizie
REV 2026.A
2026

© 2026 Gabriel Stancuta · jumpinotech.com — Proiectat cu AI, construit să funcționeze singur.