november 2025GitHubWebsite

Studio Peau — Lip Blushing in Delhi

Premium Korean-inspired landing page for a lip blushing studio in Delhi.


Tech Stack

LayerTechnology
FrameworkNext.js 14 (App Router)
StylingTailwind CSS + CSS Variables
UI Componentsshadcn/ui + Radix UI
StateZustand
FormsReact Hook Form + Zod
Smooth ScrollLenis (@studio-freight/lenis)
Scroll EffectsGSAP + ScrollTrigger
MotionFramer Motion
BackendNext.js App Router API Route
DatabaseNone (static landing / serverless lead capture)
ValidationZod (shared schema)
ContainerisationDocker + Docker Compose

Quick Start

Option A — Local (without Docker)

# 1. Clone and enter the repo
git clone <your-repo-url> lip-blushing-delhi
cd lip-blushing-delhi

# 2. Frontend setup
cd frontend
cp .env.local.example .env.local   # Edit values
npm install
npm run dev                        # Starts on http://localhost:3000

Option B — Docker Compose

cp .env.example .env   # Set WHATSAPP_NUMBER as needed
docker compose up --build

Frontend: http://localhost:3000


Environment Variables

frontend/.env.local

VariableDescriptionExample
NEXT_PUBLIC_WHATSAPP_NUMBERWhatsApp number without + or spaces919999999999

Project Structure

lip-blushing-delhi/
├── frontend/
│   ├── app/
│   │   ├── layout.tsx              ← Root layout: Lenis + JSON-LD + fonts
│   │   ├── page.tsx                ← Main page assembling all sections
│   │   ├── globals.css             ← Design tokens + base styles
│   │   └── api/lead/route.ts       ← Next.js API fallback route
│   ├── components/
│   │   ├── providers/
│   │   │   └── LenisProvider.tsx   ← Lenis smooth scroll + RAF loop
│   │   ├── sections/
│   │   │   ├── HeroSection.tsx     ← Parallax + Framer Motion
│   │   │   ├── BeforeAfterSection  ← Custom drag comparison slider
│   │   │   ├── BenefitsSection     ← Staggered scroll reveal grid
│   │   │   ├── ProcedureSection    ← GSAP ScrollTrigger horizontal scroll
│   │   │   ├── PricingSection      ← Microinteraction pricing cards
│   │   │   ├── TestimonialsSection ← Dual-row infinite marquee
│   │   │   └── LeadFormSection     ← RHF + Zod inline form
│   │   ├── ui/                     ← shadcn/ui: dialog, button, card, input...
│   │   ├── CustomCursor.tsx        ← Framer Motion magnetic cursor
│   │   ├── StickyNav.tsx           ← WhatsApp + Book Now sticky bar
│   │   └── BookingModal.tsx        ← shadcn Dialog + RHF booking form
│   ├── hooks/
│   │   └── useScrollAnimation.ts  ← useMagnetic, useScrollReveal, useLenisScrollTo
│   ├── lib/
│   │   ├── schema.ts              ← Shared Zod validation schema
│   │   ├── store.ts               ← Zustand global UI store
│   │   └── utils.ts               ← cn(), formatCurrency(), slugify()
│   └── public/
│       └── images/                ← See Image Guide below

Image Guide

Place the following WebP images in frontend/public/images/:

FilenameDimensionsUsagePriority
hero-bg.jpg1920×1080Hero section backgroundLCP — use priority
before.jpg1200×800Before/After left panel
after.jpg1200×800Before/After right panel

Recommended sources:

  • Licensed stock: Shutterstock, Getty, Adobe Stock
  • Search: "lip blushing before after", "semi permanent lips close up"
  • Always secure model release rights for medical/cosmetic procedures

Optimisation checklist:

  • Export as WebP at 85% quality
  • Use next/image with fill + sizes (already configured)
  • Hero image: compress to under 250 KB for Core Web Vitals LCP

SEO Configuration

The following is pre-configured and production-ready:

Metadata (layout.tsx)

  • Title: Lip Blushing in Delhi | Semi-Permanent Lip Color by Studio Peau
  • Description optimised for the keyword lip blushing in delhi
  • OpenGraph, Twitter Card, canonical URL
  • robots: index: true, follow: true

JSON-LD Schema (layout.tsx)

  • Type: LocalBusiness
  • Includes: name, address, coordinates, phone, hours, services, aggregate rating

Update before launch:

  • Replace placeholder coordinates with real Delhi GPS coordinates
  • Update phone, address, email
  • Replace studiopeau.in with real domain
  • Add real aggregateRating.reviewCount

API Reference

POST /api/lead

Handles lead submissions from the landing page. The route validates form input and returns a JSON success response.

Request body:

{
  "name": "Priya Mehta",
  "phone": "9811234567",
  "package": "Bloom"
}

Response 201:

{
  "success": true,
  "message": "Your enquiry has been received. We will contact you shortly.",
  "leadId": "clxyz123..."
}

Response 400 (validation failure):

{
  "success": false,
  "message": "Validation failed.",
  "errors": { "phone": ["Must be a valid 10-digit Indian mobile number."] }
}

Performance Targets

MetricTargetImplementation
LCP< 2.5spriority on hero image, WebP, next/image
FID / INP< 100msNo blocking scripts, Lenis passive scroll
CLS< 0.1Fixed dimensions on all images
TTFB< 800msStatic generation + CDN
Lighthouse> 90 allMetadata, semantics, alt text

Production Deployment

Vercel (Frontend)

cd frontend
vercel --prod

# Set environment variables in Vercel dashboard:
# NEXT_PUBLIC_WHATSAPP_NUMBER

License

Private — all rights reserved. Studio Peau.