# tayebbb/valore-parfums architecture

> Architecture diagram of the GitHub repository tayebbb/valore-parfums, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tayebbb/valore-parfums
- Repository: https://github.com/tayebbb/valore-parfums

## Overview

1. The repository is a two-app monorepo split by responsibility. `frontend/` is the customer-facing storefront plus admin UI, deployed on Netlify. `backend/` is an API-only Next.js app deployed on Render. The frontend does not talk to Firestore directly; it forwards all `/api/*` traffic to the backend.

2. The main runtime boundary is “browser → frontend → backend → Firebase/third parties.” The frontend serves SSR/ISR pages, while the backend owns all mutable business operations: authentication, product CRUD, orders, pricing, finance, uploads, and notifications. This separation is central to any architecture diagram.

3. Firestore is the primary system of record, accessed only through the Firebase Admin SDK on the backend. Client Firestore rules deny all reads/writes. Collections are organized around commerce and operations: `perfumes`, `orders`, `users`, `settings`, `decantSizes`, `bottles`, `vouchers`, `notifications`, `requests`, `stockRequests`, `wishlists`, `ownerAccounts`, `profitTransactions`, `auditLogs`, and others.

4. Authentication is custom session-based. Email/password signup and login are handled server-side with PBKDF2 hashing and an HMAC-signed cookie (`vp-session`). Google sign-in uses Firebase client SDK on the frontend to obtain an ID token, which the backend verifies before creating the same session cookie. Admin access is enforced both in API routes and in the admin layout redirect logic.

5. The storefront is a classic commerce flow: browse homepage/shop/category/brand pages, view SEO-optimized product details, add items to a client-side cart, and check out. The cart lives in Zustand/localStorage on the frontend, but order creation is server-side, where the backend validates the cart, calculates pricing, deducts stock, stores the order snapshot, and triggers email plus admin alert hooks.

6. Pricing and finance are a separate subsystem, not embedded in the UI. Selling prices are derived from market price per ml, tier-based margin rules, bottle cost, and packaging cost, then rounded psychologically. Orders store immutable financial snapshots in minor units, and item-level profit is computed separately. This enables reporting, owner balance tracking, and later reconciliation.

7. Fulfillment supports two business paths: customer orders and sourcing requests. Standard orders can be delivery or pickup, with manual payment methods for bKash/bank transfer or COD. Separate request flows capture customer sourcing requests and full-bottle leads. Admin-created stock requests can also become sourcing-driven order records.

8. The admin panel is a second major UI surface, protected by role checks. It manages the catalogue, stock, bottle inventory, decant sizes, vouchers, pickup locations, notifications, store settings, requests, orders, exports, and reports. Dashboard charts and KPIs are fed by backend aggregates, including owner balances and low-stock signals.

9. Media and messaging are handled by external services. Product and QR images upload to Cloudinary, then their URLs are stored in Firestore. Emails are sent via Nodemailer over Gmail SMTP, with different templates for order confirmation, payment confirmation, dispatch, delivery, cancellation, and pickup events.

10. The frontend has a substantial SEO/content subsystem. It renders product pages with canonical URLs, JSON-LD schema, sitemap generation, robots directives, blog content, and six programmatic landing pages. There is also a Google Shopping-style merchant feed exposed from the backend, though it is not a primary user-facing path.

11. Cross-cutting concerns are implemented in shared server libraries: input validation, rate limiting, audit logging, order status configuration, image helpers, and cached reads for high-traffic endpoints. Some caches are in-memory per process, so they are not shared across instances; that matters for any deployment diagram showing horizontal scaling.

12. There are also maintenance and operational scripts in `backend/scripts/` and duplicated in `frontend/scripts/`. These are one-off data repair and audit tools for stock, margins, decant sizes, perfumes, and finances. They are not runtime components, but they reflect that the backend is the authoritative place where operational data corrections happen.

Main entry points: [`backend/src/app/api`](https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api) (Backend API), [`backend/src/lib/firebase-admin.ts`](https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/firebase-admin.ts) (Firebase Admin), [`frontend/src/app`](https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app) (Frontend shell), [`backend/src/lib/email.ts`](https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/email.ts) (Media & email)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend app"]
  node_frontend_shell["Frontend shell<br/>Next.js UI"]
  node_storefront["Storefront<br/>commerce UI"]
  node_admin_ui["Admin panel<br/>ops UI"]
  node_seo_content["SEO content<br/>content system"]
  node_frontend_proxy["API proxy<br/>route proxy<br/>[route.ts]"]
  node_frontend_cache["Browser state<br/>client state<br/>[cart.ts]"]
end

subgraph group_backend["Backend app"]
  node_backend_api["Backend API<br/>Next.js API"]
  node_auth_service["Auth service<br/>session auth<br/>[auth.ts]"]
  node_commerce_ops["Commerce ops<br/>business logic"]
  node_pricing_finance["Pricing & finance<br/>calc engine<br/>[finance.ts]"]
  node_admin_aggregates["Admin aggregates<br/>reports"]
  node_media_messaging["Media & email<br/>integrations<br/>[email.ts]"]
end

subgraph group_data["Data layer"]
  node_firebase_admin[("Firebase Admin<br/>data access<br/>[firebase-admin.ts]")]
  node_firestore[("Firestore<br/>primary datastore<br/>[firestore.rules]")]
  node_client_rules["Client rules<br/>security rules<br/>[firestore.rules]"]
  node_cloudinary[("Cloudinary<br/>media storage")]
  node_smtp_gmail["Gmail SMTP<br/>email transport"]
end

subgraph group_ops["Operations"]
  node_scripts["Repair scripts<br/>maintenance tools"]
end

node_browser(("Browser<br/>client"))

node_browser -->|"use UI"| node_frontend_shell
node_frontend_shell -->|"forward /api"| node_frontend_proxy
node_storefront -->|"cart state"| node_frontend_cache
node_admin_ui -->|"admin calls"| node_backend_api
node_frontend_shell -->|"render SEO"| node_seo_content
node_frontend_proxy -->|"proxy request"| node_backend_api
node_backend_api -->|"auth flows"| node_auth_service
node_backend_api -->|"mutations"| node_commerce_ops
node_backend_api -->|"price/finance"| node_pricing_finance
node_backend_api -->|"dashboards"| node_admin_aggregates
node_backend_api -->|"uploads/email"| node_media_messaging
node_auth_service -->|"verify token"| node_firebase_admin
node_commerce_ops -->|"read/write"| node_firebase_admin
node_pricing_finance -->|"store snapshots"| node_firebase_admin
node_admin_aggregates -->|"aggregate reads"| node_firebase_admin
node_firebase_admin -->|"access data"| node_firestore
node_client_rules -->|"deny client access"| node_firestore
node_media_messaging -->|"upload media"| node_cloudinary
node_media_messaging -->|"send mail"| node_smtp_gmail
node_scripts -.->|"repair data"| node_firestore
node_browser -->|"local state"| node_frontend_cache

click node_frontend_shell "https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app"
click node_storefront "https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app/(store)"
click node_admin_ui "https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app/admin"
click node_seo_content "https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app"
click node_frontend_proxy "https://github.com/tayebbb/valore-parfums/blob/main/frontend/src/app/api/[...path]/route.ts"
click node_backend_api "https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api"
click node_auth_service "https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/auth.ts"
click node_commerce_ops "https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api/orders"
click node_pricing_finance "https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/finance.ts"
click node_admin_aggregates "https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api/dashboard"
click node_media_messaging "https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/email.ts"
click node_firebase_admin "https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/firebase-admin.ts"
click node_firestore "https://github.com/tayebbb/valore-parfums/blob/main/backend/firestore.rules"
click node_client_rules "https://github.com/tayebbb/valore-parfums/blob/main/frontend/firestore.rules"
click node_frontend_cache "https://github.com/tayebbb/valore-parfums/blob/main/frontend/src/store/cart.ts"
click node_scripts "https://github.com/tayebbb/valore-parfums/tree/main/backend/scripts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_frontend_shell,node_storefront,node_admin_ui,node_seo_content,node_frontend_proxy,node_frontend_cache toneBlue
class node_backend_api,node_auth_service,node_commerce_ops,node_pricing_finance,node_admin_aggregates,node_media_messaging toneAmber
class node_firebase_admin,node_firestore,node_client_rules,node_cloudinary,node_smtp_gmail toneMint
class node_scripts toneRose
class node_browser toneNeutral
```

## Components

### Frontend app

Netlify-hosted customer storefront and admin UI

- [Frontend shell](https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app): Next.js UI · SSR/ISR storefront, admin UI, SEO pages, and edge proxy · `frontend/src/app`
- [Storefront](https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app/(store)): commerce UI · Browse, product, cart, checkout, wishlist, and request flows · `frontend/src/app/(store)`
- [Admin panel](https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app/admin): ops UI · Protected back-office for catalogue, orders, inventory, reports, and settings · `frontend/src/app/admin`
- [SEO content](https://github.com/tayebbb/valore-parfums/tree/main/frontend/src/app): content system · Canonical pages, JSON-LD, sitemap, robots, blog, and landing pages · `frontend/src/app`
- [API proxy](https://github.com/tayebbb/valore-parfums/blob/main/frontend/src/app/api/[...path]/route.ts): route proxy · Forwards frontend /api traffic to the backend service · `frontend/src/app/api/[...path]/route.ts`
- [Browser state](https://github.com/tayebbb/valore-parfums/blob/main/frontend/src/store/cart.ts): client state · Cart and other local UI state in Zustand/localStorage · `frontend/src/store/cart.ts`

### Backend app

Render-hosted API-only Next.js service and authoritative business logic

- [Backend API](https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api): Next.js API · Authoritative server for auth, commerce, pricing, inventory, and admin operations · `backend/src/app/api`
- [Auth service](https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/auth.ts): session auth · Email/password signup and login, Google token verification, session cookie issuance · `backend/src/lib/auth.ts`
- [Commerce ops](https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api/orders): business logic · Products, carts, orders, requests, vouchers, wishlist, pickup, and fulfillment · `backend/src/app/api/orders`
- [Pricing & finance](https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/finance.ts): calc engine · Margin rules, price derivation, financial snapshots, owner balances, and reporting aggregates · `backend/src/lib/finance.ts`
- [Admin aggregates](https://github.com/tayebbb/valore-parfums/tree/main/backend/src/app/api/dashboard): reports · Dashboard KPIs, low-stock signals, exports, and operational summaries · `backend/src/app/api/dashboard`
- [Media & email](https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/email.ts): integrations · Cloudinary uploads and SMTP email templates for order and fulfillment events · `backend/src/lib/email.ts`

### Data layer

Primary storage and external integrations

- [Firebase Admin](https://github.com/tayebbb/valore-parfums/blob/main/backend/src/lib/firebase-admin.ts): data access · Server-side Firestore access with admin credentials · `backend/src/lib/firebase-admin.ts`
- [Firestore](https://github.com/tayebbb/valore-parfums/blob/main/backend/firestore.rules): primary datastore · System of record for commerce, inventory, users, settings, notifications, and logs · `backend/firestore.rules`
- [Client rules](https://github.com/tayebbb/valore-parfums/blob/main/frontend/firestore.rules): security rules · Client Firestore reads and writes are denied · `frontend/firestore.rules`
- **Cloudinary**: media storage · Stores product and QR images referenced from Firestore
- **Gmail SMTP**: email transport · Outbound email delivery via Nodemailer

### Operations

One-off maintenance scripts

- [Repair scripts](https://github.com/tayebbb/valore-parfums/tree/main/backend/scripts): maintenance tools · One-off data fixes and audits for stock, margins, bottles, decants, and finances · `backend/scripts`

### Other components

- **Browser**: client · Customer and admin users interact here

## Connections

- Browser → Frontend shell: use UI · Users interact with storefront and admin surfaces
- Frontend shell → API proxy: forward /api · Frontend routes delegate API traffic to the backend
- Storefront → Browser state: cart state · Cart is kept client-side in local storage/state
- Admin panel → Backend API: admin calls · Protected admin operations are executed server-side
- Frontend shell → SEO content: render SEO · Frontend renders programmatic content and search pages
- API proxy → Backend API: proxy request · All frontend API traffic is forwarded to the backend
- Backend API → Auth service: auth flows · Login, signup, Google sign-in, logout, and session checks
- Backend API → Commerce ops: mutations · Product, order, request, voucher, wishlist, and fulfillment endpoints
- Backend API → Pricing & finance: price/finance · Pricing calculations and financial snapshots are computed server-side
- Backend API → Admin aggregates: dashboards · Dashboard and export endpoints read aggregate reporting data
- Backend API → Media & email: uploads/email · Uploads and notification emails are issued from backend handlers
- Auth service → Firebase Admin: verify token · Server auth verifies IDs and manages session state using admin access
- Commerce ops → Firebase Admin: read/write · Business operations use the Firebase Admin SDK
- Pricing & finance → Firebase Admin: store snapshots · Financial and owner balance data is persisted through admin access
- Admin aggregates → Firebase Admin: aggregate reads · Dashboard metrics and exports are derived from Firestore data
- Firebase Admin → Firestore: access data · Admin SDK is the only write-capable Firestore path
- Client rules → Firestore: deny client access · Client rules block direct reads and writes
- Media & email → Cloudinary: upload media · Product and QR images are stored externally
- Media & email → Gmail SMTP: send mail · Transactional emails are delivered through Gmail SMTP
- Repair scripts → Firestore: repair data · Maintenance scripts correct operational records and balances
- Browser → Browser state: local state · Client-side state supports cart and UI persistence
