VogueLens AI is an intelligent fashion advisor that helps users make better style choices through AI-powered analysis. Upload clothing items, get color palette insights, style recommendations, and build your perfect wardrobe — in English or Romanian.
- AI-powered style analysis and outfit recommendations
- Image upload with Google Cloud Vision analysis
- AI image generation via DALL-E 3
- Virtual wardrobe management with weather-based suggestions
- Shopping compatibility checker
- Credits system — first 100 users get 100 free credits (1 per text message, 5 per image)
- English / Romanian i18n with URL-based locale switching (
/en,/ro) - Dark / light mode
- Responsive design
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router), TypeScript 5.x |
| Styling | Tailwind CSS 4.x, shadcn/ui, motion/react |
| Auth | Clerk (SSO + Google) |
| AI | OpenAI GPT-4 / GPT-4o, DALL-E 3, Google Cloud Vision |
| Database | Supabase (PostgreSQL), Drizzle ORM |
| Rate limiting | Upstash Redis + @upstash/ratelimit |
| i18n | next-intl |
| Testing | Jest + React Testing Library, Playwright |
| Deployment | Vercel |
node >= 18.0.0
npm >= 9.0.0
git clone git@github.com:Alexandra2888/VogueLens-AI.git
cd VogueLens-AI
npm install
cp .env.example .env.local # fill in variables below
npm run devVisit http://localhost:3000 — redirects to /en automatically.
# Clerk authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/en/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/en/sign-up
# OpenAI
NEXT_OPENAI_API_KEY=
# Google Cloud Vision (JSON credentials as string)
NEXT_GOOGLE_CLOUD_CREDENTIALS=
# Supabase — pooled connection (runtime, e.g. serverless)
DATABASE_URL=
# Supabase — direct connection (Drizzle migrations / DDL)
DIRECT_URL=
# Upstash Redis (rate limiting)
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
NEXT_PUBLIC_CLERK_BYPASS_AUTH=trueis injected only by Playwright for E2E tests. Never set it in production.
VogueLens-AI/
├── app/ # Next.js App Router
│ ├── [locale]/ # i18n routes (/en/*, /ro/*)
│ │ ├── (home)/ # Landing page
│ │ ├── chat/ # AI chat
│ │ ├── wardrobe/ # Wardrobe manager
│ │ ├── profile/ # User profile + credits
│ │ ├── privacy/
│ │ └── terms/
│ ├── api/ # API routes (no locale prefix)
│ │ ├── chat/
│ │ ├── analyze-image/
│ │ ├── wardrobe/
│ │ └── user/credits/
│ └── _components/ # Shared UI components
├── src/
│ ├── db/schema.ts # Drizzle schema (users, wardrobe_items)
│ ├── lib/
│ │ ├── rate-limit.ts # Upstash rate limiters
│ │ ├── security.ts # Zod schemas, sanitization, SSRF guard
│ │ ├── db.ts
│ │ └── openai.ts
│ └── i18n/ # next-intl routing config
├── messages/
│ ├── en.json # English strings
│ └── ro.json # Romanian strings
├── tests/e2e/ # Playwright E2E tests
├── __tests__/ # Jest unit tests
└── docs/rfc.md # Technical RFC
npm run dev # Development server (webpack)
npm run build # Production build
npm run start # Production server
npm run lint # ESLint
npm run lint:fix # ESLint with auto-fix
npm run format # Prettier
npm run test # Jest unit tests
npm run test:unit # Jest (alias)
npm run test:e2e # Playwright E2E tests
npm run test:e2e:ui # Playwright with UInpm run test
# or run a single file:
npx jest __tests__/lib/security.test.tsTests cover:
sanitizeText— XSS/script injection strippingisPublicHttpsUrl— SSRF prevention- Zod schemas (
chatSchema,wardrobePostSchema) - Credit allocation and deduction logic
generateChatTitleutilityMessagecomponent rendering
# Playwright starts its own dev server with auth bypass enabled automatically
npm run test:e2eTests cover: home, hero, features, how-it-works, footer, header, theme toggle, terms, privacy, 404, language switcher, chat page, security headers, and API auth/CSRF checks.
If reusing an existing dev server for E2E tests, add
NEXT_PUBLIC_CLERK_BYPASS_AUTH=trueto.env.localand restart it.
The app is hardened to OWASP Top 10 standards:
| Threat | Mitigation |
|---|---|
| XSS | sanitizeText() strips scripts/event handlers on all API input; React JSX escapes all output |
| CSRF | Origin header checked against Host on all mutating API requests (middleware) |
| DDoS / brute force | Upstash sliding-window rate limits at two levels: 60 req/min/IP (middleware), per-user limits per route |
| Clickjacking | X-Frame-Options: DENY, CSP frame-ancestors 'none' |
| MIME sniffing | X-Content-Type-Options: nosniff |
| Prompt injection | User input sanitized; imageAnalysis passed as user message, not interpolated into system prompt |
| SSRF | isPublicHttpsUrl() blocks private IP ranges on all user-supplied URLs |
| Info leakage | Error handlers never return stack traces; only error.message is logged server-side |
| Insecure transport | Strict-Transport-Security (1 year, includeSubDomains, preload) |
| LLM output trust | Wardrobe AI response fields are whitelist-validated before hitting the DB |
| File upload abuse | MIME type whitelist + 5 MB size cap on /api/analyze-image |
- First 100 registered users receive 100 free credits (
earlyAccess: true) - Users 101+ see a gate screen and receive 0 credits
- Cost: 1 credit per text message, 5 credits per image upload or AI image generation
- Balance is displayed on the Profile page; chat is disabled when credits reach 0
Schema managed with Drizzle ORM. After schema changes:
npx drizzle-kit push # push directly (dev/staging)
# or
npx drizzle-kit generate # generate SQL migration files
npx drizzle-kit migrate # apply migrationsMIT — see LICENSE.