eduardweb.
Prezentări & ShowcaseIntermediar#nextjs#prisma#showcase#dashboard#fullstack

Am construit un dashboard intern pentru o agenție în 3 luni: Next.js, Prisma și lecțiile învățate

De Delia Petre, 24 apr. 2026 · 2 vizualizări · 2 like-uri

Postat acum 3 zile
typescript
// Exemplu de pattern pe care l-am folosit pentru a evita N+1 în rapoartele de campanii
// Folosind Prisma, dar filtrând inteligent

export async function getCampaignStats(agencyId: string) {
  const campaigns = await prisma.campaign.findMany({
    where: { agencyId },
    include: {
      _count: {
        select: { ads: true }
      }
    }
  });

  // Calculăm agregatele direct în memorie sau via un query separat pentru viteză
  const stats = await prisma.dailyStat.groupBy({
    by: ['campaignId'],
    _sum: {
      spend: true,
      clicks: true,
      conversions: true
    },
    where: {
      campaignId: { in: campaigns.map(c => c.id) }
    }
  });

  return campaigns.map(c => ({
    ...c,
    stats: stats.find(s => s.campaignId === c.id) || { _sum: { spend: 0, clicks: 0, conversions: 0 } }
  }));
}

Recent am livrat un dashboard intern pentru o agenție de marketing cu vreo 25 de angajați. Oamenii ăștia își petreceau jumătate din viață copiind date din Facebook Ads și Google Ads în niște spreadsheet-uri gigantice care se încărcau în 30 de secunde. Am avut la dispoziție 3 luni să transform haosul ăsta în ceva utilizabil. Am mers pe stack-ul meu de încredere: Next.js (App Router), Prisma și NextAuth.

După 90 de zile de dev, am tras linie și am vrut să dau mai departe câteva chestii concrete pe care le-am învățat, că poate vă loviți și voi de ele.

De ce am ales stack-ul ăsta și unde m-am păcălit

Am ales Next.js pentru că aveam nevoie de Server Components. În marketing, datele sunt multe și grele. Să tragi 50MB de JSON pe client ca să randezi un grafic e sinucidere curată. Cu RSC (React Server Components), am mutat tot procesul de agregare pe server, lângă baza de date. Am reușit să scădem timpul de încărcare a unui raport lunar de la 2 minute (cât dura manual în Excel) la sub 2 secunde.

Prisma e dragostea mea veche, dar are un trade-off pe care mulți îl ignoră: N+1 query-urile sunt extrem de ușor de ignorat dacă nu ești atent la include. La un moment dat, aveam un query care făcea 150 de request-uri la DB pentru o singură listă de campanii. Am rezolvat asta cu un join manual via $queryRaw pentru secțiunile critice, restul au rămas pe ORM. Am economisit cam 40% din timpul de execuție pe query-urile complexe după optimizarea asta.

NextAuth și bătăile de cap cu Refresh Tokens

NextAuth e super dacă vrei doar „Login with Google”. Dar când agenția are nevoie să se lege la API-ul de Google Ads în numele userului, lucrurile devin dubioase. Gestionarea refresh token-urilor în baza de date via NextAuth e un pic „clunky”. Am pierdut vreo 4 zile bune încercând să prind momentul în care token-ul expiră fără să forțez userul să dea logout.

Sfatul meu: dacă aveți nevoie de acces persistent la API-uri externe, scrieți-vă propria logică de token management separat de sesiunea de auth a userului. E mai curat și nu riști să bușești login-ul dacă API-ul extern e jos.

UI: Shadcn/ui versus biblioteci „grele”

Am mers pe shadcn/ui (Radix + Tailwind). Arată brici și ai control total. Totuși, trade-off-ul e real: scrii mult mai mult cod de mână. Pentru un dashboard intern unde contează mai mult viteza de livrare decât dacă butonul are border-radius de 4 sau 8 pixeli, uneori o bibliotecă mai „opinioned” ca Mantine sau MUI te-ar putea scoate la liman mai repede. Eu am ales calea grea pentru că voiam un bundle size mic și flexibilitate pe termen lung, dar am simțit efortul suplimentar în a treia lună când trebuia să termin tabelele complexe cu filtrare.

Ce am câștigat după 3 luni

La final, am automatizat raportarea pentru 80 de clienți activi. Account managerii au estimat că salvează cam 15 ore pe săptămână, timp pe care înainte îl pierdeau cu copy-paste.

Cel mai important task n-a fost codul, ci să înțeleg cum gândesc ei datele. Degeaba e codul curat dacă userul nu înțelege de ce ROAS-ul (Return on Ad Spend) e calculat diferit față de ce vede el în platforma Facebook.

Voi ce folosiți pentru tool-uri interne? Mergeți pe low-code gen Retool sau preferați să scrieți totul de la zero pentru control maxim?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.