English version available Switch to English →
Studiu de caz · Build complet

Lashstudio.ro — site beauty construit ca produs.

8 minute citire · Publicat 13 mai 2026 · Mugur Marinescu

Salonul Andreei din Popești-Leordeni avea Instagram activ și un site vechi care abia apărea pe Google. L-am construit de la zero pe Next.js + Vercel + Tailwind, cu schema completă și multe iterații pe mobile. După 4 săptămâni: Lighthouse 91 Performance, 96 Accessibility, 100 Best Practices, 100 SEO. Mai jos: ce a mers, ce nu, cu cifre.

Vezi site-ul live → Înapoi la studii
1. Contextul

Piața beauty crește. Majoritatea pierd online.

În București și Ilfov sunt câteva mii de saloane beauty. Toate oferă cam aceleași lucruri: extensii gene, micropigmentare, laminare, faciale. Diferențierea offline ține până la un punct. Pentru un client nou, primul contact e o căutare pe Google sau scroll pe Instagram.

Și aici e problema. Majoritatea saloanelor au site-uri lente, fără SEO, fără date structurate. WordPress cu teme generice și 20+ pluginuri care încarcă a doua imagine după 5 secunde. Bara competitivă tehnic e jos. Oricine vine cu un site curat și rapid intră peste ele.

Homepage lashstudio.ro — hero cu Andreea Marinescu
Hero homepage — design clean, paletă cream + dark warm, CTA direct la programare.
2. Clienta

Andreea Marinescu — 5000+ cliente, vizibilitate online mică.

Lash & brow master din 2016. Salon propriu în Popești-Leordeni, peste 5000 de cliente, produse premium pe fiecare procedură (InLei, Tabya, Neicha, RefectoCil), recenzii constante. Online era altă poveste: Instagram activ, dar site vechi care apărea greu în căutările organice.

Înainte să scriu cod, am stabilit trei obiective:

  1. Site rapid pe mobile, pentru că acolo se decide totul în beauty
  2. Apariție în primele rezultate Google pentru căutări locale tip „extensii gene popești leordeni" sau „micropigmentare buze ilfov"
  3. Drum scurt de la prima vizită la programare: telefon, WhatsApp sau email, în maxim două click-uri
3. Tech stack

De ce nu WordPress.

Am exclus WordPress din start. Nu pentru că WordPress e prost — e o platformă matură. Dar pluginurile multiple, baza de date suprasolicitată și overhead-ul temelor beauty din România fac performanța aproape imposibilă fără efort de tuning continuu. Pentru un site de prezentare cu booking, există variante mai curate.

Stack-ul ales:

  • Next.js 16 cu App Router: componente server-side, image optimization integrată, ISR pentru pagini frecvent actualizate
  • Tailwind CSS 4: fără fișier de config, paleta direct în globals.css, zero overhead de runtime
  • Neon Postgres: baza de date a programărilor și clientelor
  • Vercel: hosting și CDN global
  • NameHero: email pe domeniu propriu ([email protected])
  • NextAuth: autentificare admin

Cu stack-ul ăsta, Best Practices și SEO erau 100 din primul deploy. Performance și Accessibility au cerut muncă suplimentară.

4. Performance

Imaginile, fonturile, efectele CSS.

Imaginile

Beauty înseamnă poze multe. Dacă nu le optimizezi, încarci megabytes per pagină și scorul pe mobile cade. Cum am rezolvat:

  • Toate imaginile prin <Image> Next.js. Servește automat AVIF sau WebP, după browser, cu lazy loading.
  • Pentru poze din portofoliu, convertesc manual la WebP cu sharp quality 82. Un JPEG de 400KB ajunge 80–150KB fără diferență vizibilă.
  • Hero-ul homepage are priority activ — preload + fetchPriority="high" pentru LCP.
  • Atributul sizes e explicit pe fiecare imagine. Nu trimit 2048px când am nevoie de 400px.

Fonturile

Inițial aveam Cormorant Garamond și Jost cu toate weight-urile (300, 400, 500, 600) plus italics. 11 fișiere font per load. Render blocking aproape o secundă. Am tăiat la 6 variante. PSI a urcat 5 puncte doar din asta.

Efecte CSS pe mobile

Hero-ul are un blur radial subtil în fundal, efect „watercolor". Pe desktop, filter: blur(40px) arată bine. Pe telefoane mid-range, GPU-ul suferă și paint-ul întârzie. Am redus la 24px doar pe mobile, printr-un media query. Diferența vizuală e mică, Time to Interactive a scăzut cu aproape jumătate de secundă.

Lashstudio.ro pe mobile — vedere homepage
Homepage pe mobile — design optimizat pentru ecran mic, CTA dominant.

Rezultate Lighthouse

După optimizări, scorurile pe mobile:

Metric Score
Performance91
Accessibility96
Best Practices100
SEO100

LCP a scăzut de la 3.4s la 2.6s. FCP de la 2.2s la 1.4s. Page weight pe homepage de la 850KB la 420KB. Design-ul a rămas neschimbat.

5. SEO

Ce contează acum într-o nișă locală.

Datele structurate

Schema.org JSON-LD e cum Google și motoarele AI (ChatGPT Search, Perplexity, AI Overviews) înțeleg ce face site-ul tău. Fără ele, ești tăcut pentru sistemele astea — apari poate, dar nu te citează nimeni în răspunsuri AI.

Lashstudio are mai multe straturi de schema:

  • BeautySalon schema globală în root layout: adresă completă, telefon, email, ore, social media, coordonate geo
  • Service schema pe fiecare pagină de serviciu: preț, durată, descriere, offers
  • FAQPage schema: 9–10 întrebări per serviciu cu răspunsuri formatate corect
  • BreadcrumbList pentru navigația ierarhică
Pagina serviciului Micropigmentare — schema Service + FAQ
Pagină serviciu — schema Service + Offer + FAQPage stratificate.

Keywords pe coadă lungă

Pe „micropigmentare" simplu nu poți câștiga. Acolo concurezi cu toate clinicile mari și cu portalurile Treatwell, Booksy. Am mers pe queries cu intent specific:

  • „cum se îngrijesc extensiile de gene"
  • „contraindicații micropigmentare buze"
  • „cât durează vindecarea după carbon peel"
  • „pot face stilizare sprâncene după botox"

Pentru fiecare serviciu am identificat 10–15 astfel de întrebări — parte din People Also Ask, parte din ce o întreabă Andreea cliente la fiecare programare. Răspunsurile apar în două locuri. Pe pagină, ca chenare informative („Reguli de îngrijire", „Contraindicații", „Pregătirea înainte de procedură"). Și în FAQ schema, ca să poată fi citate în featured snippets sau în răspunsurile AI.

Chenare aftercare şi contraindicații pe pagina Micropigmentare
Chenarele cu aftercare + contraindicații — dublu folosite: UX util + FAQ schema pentru featured snippets.

NAP consistency

Numele, adresa și telefonul trebuie identice peste tot. Pe site, în schema JSON-LD, pe Google Business Profile, în directoriile locale. Google folosește asta ca semnal de încredere. O virgulă în plus, o cifră inversată sau o adresă scurtată într-un singur loc slăbește ranking-ul local. Am centralizat datele într-un singur loc în cod și verific manual oriunde apar.

Sitemap dinamic

app/sitemap.ts generează automat sitemap.xml cu toate URL-urile, priority și changeFrequency per tip de pagină. Adăugarea unei pagini noi intră în sitemap fără cod suplimentar.

6. Conversie

Design + UX pentru conversie.

CTA-uri în locurile potrivite

Fiecare pagină are minim două CTA-uri vizibile fără scroll: buton primar pentru programare (dark #2d2020 pe fundal cream) și buton secundar contextual (prețuri, contact, link relevant). Utilizatorul are mereu un drum spre acțiune, indiferent de unde intră pe site.

Butonul WhatsApp flotant

Verde brand WhatsApp (#25d366), fix în colțul dreapta jos pe toate paginile publice. Pe mobile e cea mai accesibilă cale de contact: un tap deschide chat-ul cu salonul. Conversia pe WhatsApp e mare în beauty pentru că oamenii preferă conversația rapidă în locul unui formular cu 8 câmpuri.

Voucher cadou

Pagina /voucher are pondere disproporționată în conversie. Beauty e sezonier: Crăciun, Valentine's, Mărțișor, Ziua Mamei, aniversări. Cadourile cu voucher generează clienți noi cu cost de achiziție mic, și majoritatea revin ca clienți recurenți.

Lightbox pe galerie

Click pe orice poză deschide un overlay fullscreen. Esc, click pe fundal sau X închid. Vanilla cu React Context, fără librării: 50 de linii de cod, zero dependențe noi în bundle. Pare detaliu mic. În practică, timpul petrecut în galerie a crescut sensibil. Oamenii vor să vadă lucrările în detaliu înainte să rezerve.

Galeria lashstudio.ro cu filtre categorii şi lightbox click-to-zoom
Galerie cu filtre pe categorii + lightbox custom în 50 linii cod.
7. Accesibilitate

WCAG 2.1 AA, unde se vede în cod.

Câteva detalii practice:

  • Meniul mobil închis primește atributul inert prin useEffect. Linkurile dispar din tab order, iar utilizatorii cu tastatură nu mai nimeresc invizibili.
  • Skip link „Sari la conținut" — focusabil, ascuns vizual, apare doar la tabulare.
  • Toate textele cu contrast minim 4.5:1. Opacitățile /60 sau /50 pe text le-am înlocuit cu culori solide din paletă.
  • Focus visible explicit pe toate butoanele și linkurile, cu ring colorat.
  • ARIA labels pe iconițe, aria-hidden pe decorative.

Scorul final: 96. Pentru 100, ar trebui revizuite câteva texte mici care folosesc accent color. Mai jos explic de ce am ales să rămân la 96.

Pagina Despre Noi — Andreea Marinescu, valori, branduri
Despre Noi — Andreea în prim plan, branduri folosite, valori clare.
8. Concurența

Ce am găsit la concurență.

Înainte de build, am analizat ~20 de saloane din București + Ilfov pe servicii similare. Pattern-uri repetate:

  • Majoritatea folosesc WordPress cu teme generice, fără optimizare imagini. Lighthouse Performance pe mobile sub 50 în multe cazuri.
  • Sub jumătate au schema JSON-LD completă. Restul fie nu o au, fie e cu erori care o fac inutilizabilă pentru Google.
  • Foarte puține au FAQ structurat pe pagini de servicii. Pierd astfel tot traficul long-tail.
  • Mulți nu au Google Business Profile complet: adresă incompletă, ore lipsă, fără foto, fără răspuns la recenzii.
  • Politica de cookies și GDPR — frecvent incomplete sau absente.

Pentru un salon nou: un site făcut tehnic corect poate intra în top 3 organic local fără buget mare de paid ads. Asta a fost teza inițială. Datele de mai jos confirmă că funcționează.

9. Lecții reale

Ce nu a mers — trei reverts.

După prima săptămână live, am revenit pentru o rundă de optimizări țintite. PageSpeed Insights ne-a marcat câteva probleme: render blocking 900ms, forced reflow 348ms, unused JS 29 KiB.

Am încercat 6 lucruri. Trei au mers, trei nu. Le povestesc pe toate, pentru că „ce nu funcționează" e la fel de util ca „ce funcționează".

Ce a mers

1. Resize logo de la 5000×2092 la 600×251 — logo-ul livrat era 5000px lățime, 306 KB. Pe site se afișa la maxim 80 CSS pixels. Adică livram o imagine de 13× mai mare decât era nevoie. Resize cu sharp la 600×251, quality 90, output WebP: rezultatul a ajuns la 26 KB. Câștig direct: −280 KB la fiecare prim load, fără absolut nicio diferență vizuală.

2. Scroll listener cu requestAnimationFrame — navul scurta înălțimea când utilizatorul scrolla mai jos de 40px. Handler-ul citea window.scrollY și seta state-ul direct. PSI marca „forced reflow 348ms". Soluția: throttle cu requestAnimationFrame și setState doar când valoarea chiar se schimbă. Plus am scurtat tranziția CSS de la 500ms la 300ms. Forced reflow a trecut la verde.

3. Hero image cu placeholder blur<Image> din Next.js suportă placeholder="blur" cu blurDataURL. Am generat un base64 minuscul (10×10px blurat) pentru hero. Utilizatorul vede ceva pictat pe ecran instant, înainte ca imaginea reală să se descarce. Perceived performance ↑ chiar și fără îmbunătățire reală de LCP.

Ce nu a mers

4. experimental.optimizeCss: true — pe hârtie sună perfect: extrage critical CSS, inline-uiește, defer restul. Rezultat real: Performance a scăzut de la 91 la 89. Forced reflow a reapărut. Flag-ul experimental chiar e experimental. Rollback în 2 secunde. Lecție: testează flag-uri experimentale separat, nu în producție pe trafic real.

5. Dynamic import pentru CookieConsent și GoogleAnalytics — am vrut să scot cele două componente client-side din bundle-ul inițial via next/dynamic. Logic — sunt non-critice. Rezultat: Performance a scăzut de la 91 la 87. Pentru componente atât de mici (sub 3 KB fiecare), overhead-ul unei runtime fetch separate e mai mare decât câștigul din bundle splitting. Lecție: code splitting are sens pentru componente mari sau rar folosite, nu pentru cele care apar pe primul paint.

6. Schimbare accent color pentru Accessibility 100 — cea mai dureroasă decizie. PSI marca contrast fail pe #e8967e (pink-coral) folosit ca text pe fundal cream. Pentru 100 perfect ar trebui schimbat la o variantă mai închisă (#a4502f, rust). 115 înlocuiri în 19 fișiere. Am făcut schimbarea, apoi am revenit. Accentul a devenit ruginiu, paleta și-a pierdut feel-ul „warm coral" care era parte din identitatea vizuală. Câștigul de 4 puncte la Accessibility nu compensa schimbarea de paletă. Salonul a ales să rămână la 96 cu paleta originală. 96 e tot scor industry-leading.

Ce am învățat din runda asta

Două lucruri practice care-mi rămân:

Primul: nu fiecare „best practice" recomandată de PSI se aplică universal. Flag-uri experimentale și dynamic imports pentru chunk-uri mici pot avea efect invers. Măsoară după fiecare modificare. Nu presupune că direcția e bună doar pentru că documentația o spune.

Al doilea: există un punct dincolo de care optimizările tehnice nu mai aduc câștig real pentru utilizator. Diferența între 91 și 95 la PSI nu se vede în comportamentul real. Câștigul vine după aceea din content nou, backlink-uri, conversie — nu dintr-un kilobyte tăiat dintr-un chunk shared.

10. Mobile

Mobile, testat pe device-uri reale.

Peste 80% din traficul saloanelor beauty vine de pe mobile. Dacă site-ul nu funcționează decent pe telefoane mid-range (iPhone vechi, Samsung A-series, Android sub €300), conversia se pierde înainte ca cineva să citească ceva.

Am testat constant pe 3 device-uri reale: iPhone 11, Samsung A52, Xiaomi Redmi Note 10. Nu doar Chrome DevTools simulator. A scos la suprafață probleme pe care emulatorul nu le vede: GPU lag pe blur-uri, touch targets prea mici, scroll lag pe galerie cu multe imagini.

Pagina Micropigmentare pe mobile — chenare aftercare
Pagină Micropigmentare pe mobile — chenarele de aftercare optimizate pentru ecran mic.
11. Lecții transferabile

Lecții pe care le iau mai departe.

  1. WordPress nu e cea mai bună alegere pentru saloane mici dacă vrei performance real. Cost-benefit slab vs alternative moderne.
  2. Schema JSON-LD e cea mai subestimată optimizare SEO. Două ore de muncă, beneficii măsurabile pe luni întregi.
  3. FAQ extins pe pagina serviciului funcționează mai bine decât blog separat pentru long-tail searches. Plus, Google îl citează mai des în featured snippets.
  4. JPEG → WebP salvează 50–80% din mărimea imaginilor fără pierdere vizibilă. Pentru un site beauty cu zeci de poze, înseamnă megabytes economisiți la fiecare load.
  5. Nu adăuga librării pentru lucruri simple. Un lightbox funcțional în React e 50 linii cu Context. O librărie de 30KB pentru același rezultat e overkill.
Stack folosit

Tech stack complet.

  • Frontend: Next.js 16, React 19, TypeScript, Tailwind CSS 4
  • Backend: Next.js API Routes, NextAuth pentru autentificare admin
  • Database: Neon Postgres (serverless)
  • Hosting: Vercel cu edge CDN global
  • Email business: NameHero ([email protected])
  • DNS: Vercel
  • Monitoring: Google Search Console + Vercel Analytics

Vrei ceva similar?

Dacă vrei un site care performează — nu doar arată bine — și care aduce clienți organic prin Google, nu doar prin paid ads, scrie-mi. La primul apel discutăm scope concret și recovery math.

Aplică pentru o discuție →

Site-ul live: www.lashstudio.ro