- Overview
- What's New
- Tech Stack
- System Architecture
- Module Map
- Routing
- Data Model
- Checkout & Order Lifecycle
- Order Email Pipeline
- Authentication
- Admin Panel
- Analytics & Tracking
- Internationalisation (i18n)
- Cart State Management
- Features
- Project Structure
- Getting Started
- Environment & Configuration
- Deployment
- Scripts
- Contributing
Hygenc Covers is a high-conversion, mobile-first e-commerce platform for intimate hygiene toilet seat covers targeting the Sri Lankan market. It began as a client-only WhatsApp storefront and has grown into a full-stack application with a Supabase backend, a serverless order-email API, customer accounts, and a complete admin console.
The platform serves three customer segments:
| Segment | Product | Channel |
|---|---|---|
| Retail / Personal | Single Use Pack | Cart ยท COD checkout ยท WhatsApp |
| Travellers | Travel Pack (Waterproof) | Cart ยท COD checkout ยท WhatsApp |
| Hotels / Corporates | Enterprise Bulk Pack | B2B Enquiry Form |
The storefront is fully internationalised across English, Sinhala (เทเทเถเทเถฝ), and Tamil (เฎคเฎฎเฎฟเฎดเฏ). Customers can check out three ways: a cash-on-delivery (COD) order persisted to Supabase with an emailed confirmation, a WhatsApp deep-link order, or a B2B enquiry for bulk buyers.
The platform has expanded well beyond the original WhatsApp-only storefront. Recent additions:
- ๐ COD checkout + order persistence โ orders saved to Supabase via a
create_checkout_orderRPC with an idempotent, offline-tolerant fallback path. - ๐ง Transactional order emails โ a serverless function renders a branded HTML receipt and sends it through Resend (with a verified-sender fallback).
- ๐ Customer accounts โ sign-up / sign-in, profile, and order history backed by Supabase Auth.
- ๐ก๏ธ Admin console โ dashboard, orders, products, customers, inquiries, newsletter, analytics, quiz, and settings, behind an admin auth guard.
- ๐ Analytics & tracking โ page views, conversions, and custom events stored in Supabase and surfaced in the admin analytics page.
- ๐งช Product finder quiz โ guided recommendation flow with responses stored for insight.
- ๐๏ธ Product catalog & bundles โ a data-driven catalog (6 products) with bundle rules (add-ons require a base bundle).
- ๐ Policy pages โ privacy, terms, refund, and shipping policy pages wired into the footer.
- ๐ค Admin export โ orders/customers exportable to CSV/HTML.
- ๐ SEO โ per-page metadata via a reusable
SEOcomponent.
| Layer | Technology |
|---|---|
| UI Framework | React 19 |
| Build Tool | Vite 8 |
| Styling | Tailwind CSS 4 (@tailwindcss/vite JIT) |
| Routing | React Router DOM 7 |
| Icons | Font Awesome 7 (SVG Core) + Lucide React |
| Animation | Framer Motion + CSS keyframes / IntersectionObserver |
| Charts | Recharts (admin analytics) |
| Dates | date-fns |
| Client State | React Context API (Cart ยท Lang ยท CustomerAuth ยท AdminAuth) |
| Backend (BaaS) | Supabase โ Postgres, Auth, Row-Level Security, RPC functions |
| Serverless API | Vercel Functions (/api/*, Node handler) |
| Transactional Email | Resend (production) ยท Nodemailer (local tooling) |
| Hosting / CI-CD | Vercel (static SPA + serverless functions) |
| Checkout Channels | COD form ยท WhatsApp deep link (wa.me) ยท B2B enquiry |
| Browser Persistence | localStorage / sessionStorage |
| Linting | ESLint + react-hooks + react-refresh |
graph TB
subgraph Browser["๐ Client (Browser SPA)"]
direction TB
subgraph Providers["Context Providers"]
LC[LangContext<br/>EN ยท SI ยท TA]
CC[CartContext<br/>localStorage]
CAC[CustomerAuthContext]
AAC[AdminAuthContext]
end
subgraph Surfaces["UI Surfaces"]
Store[Storefront Pages]
Acct[Customer Account]
Admin[Admin Console]
Quiz[Product Quiz]
end
Lib[lib/ ยท database.js ยท supabase.js ยท orderEmail.js ยท adminExport.js]
AT[AnalyticsTracker]
Providers --> Surfaces
Surfaces --> Lib
Surfaces --> AT
end
subgraph Vercel["โฒ Vercel Edge / Functions"]
SPA[Static SPA<br/>intimate-react/dist]
FN["/api/send-order-email<br/>(serverless handler)"]
end
subgraph Supabase["๐ข Supabase"]
DB[(Postgres<br/>+ RLS)]
AUTH[Supabase Auth]
RPC[RPC: create_checkout_order<br/>save_customer_profile ยท delete_order_admin]
end
subgraph Ext["External Services"]
RESEND[Resend Email API]
WA[WhatsApp<br/>wa.me]
GF[Google Fonts]
end
Browser -->|served by| SPA
Lib -->|"REST ยท Auth ยท RPC"| DB
Lib --> AUTH
Lib --> RPC
AT -->|events| DB
Lib -->|"POST order"| FN
FN -->|"RPC create_checkout_order"| RPC
FN -->|"send receipt"| RESEND
Surfaces -->|"deep link"| WA
Browser --> GF
graph TD
main[main.jsx] --> App
App --> Ctx[Context Providers]
App --> GlobalUI[Global UI Layer]
App --> Router[React Router]
App --> Track[AnalyticsTracker]
Ctx --> Lang[LangContext]
Ctx --> Cart[CartContext]
Ctx --> CustAuth[CustomerAuthContext]
Ctx --> AdminAuth[AdminAuthContext]
GlobalUI --> AnnouncementBar
GlobalUI --> WhatsAppButton
GlobalUI --> DiscountPopup
GlobalUI --> LivePurchaseNotification
GlobalUI --> CartDrawer
GlobalUI --> StickyMobileCTA
GlobalUI --> SEO
GlobalUI --> ScrollToTop
Router --> Storefront
Router --> Customer
Router --> AdminRouter
Storefront --> Home & Products & ProductDetail[Product1..6] & Compare
Storefront --> About & Benefits & Blog & FAQ & B2B & Referral
Storefront --> Delivery & Contact & Quiz & PolicyPages & OrderTemplate
Customer --> CustomerAuth & CustomerAccount
AdminRouter --> AdminLogin
AdminRouter --> AdminLayout
AdminLayout --> AdminDashboard & AdminOrders & AdminProducts & AdminCustomers
AdminLayout --> AdminInquiries & AdminNewsletter & AdminAnalytics & AdminQuiz & AdminSettings
ProductDetail --> Catalog[data/catalog.js]
ProductDetail --> ProductContent[data/productContent.js]
AdminOrders --> adminExport[lib/adminExport.js]
CartDrawer --> orderEmail[lib/orderEmail.js]
orderEmail --> API["/api/send-order-email"]
AdminDashboard --> database[lib/database.js]
database --> supabase[lib/supabase.js]
The app splits at the top level into an admin tree (/admin/*, fully isolated โ no storefront overlays) and the customer tree (/*). Source of truth: App.jsx.
flowchart LR
root["/"] -->|redirect| splash["/splash<br/>brand intro"]
splash --> home["/home"]
subgraph Store["๐๏ธ Storefront (/*)"]
home --> products["/products"]
products --> pd["/products/1 โฆ /products/6"]
products --> compare["/compare"]
home --> quiz["/quiz"]
home --> about["/about"] & benefits["/benefits"] & blog["/blog"] & faq["/faq"]
home --> b2b["/b2b"] & referral["/referral"] & delivery["/delivery"] & contact["/contact"]
home --> policies["/privacy-policy ยท /refund-policy ยท /terms-and-conditions"]
home --> order["/order"]
end
subgraph Cust["๐ค Customer (/*)"]
login["/login<br/>sign in / up"]
account["/account<br/>profile + orders"]
end
subgraph Adm["๐ก๏ธ Admin (/admin/*)"]
adminidx["/admin<br/>(AdminLogin ยท index)"]
adminidx --> dash["/admin/dashboard"]
dash --> aorders["/admin/orders"]
dash --> aproducts["/admin/products"]
dash --> acustomers["/admin/customers"]
dash --> ainquiries["/admin/inquiries"]
dash --> anewsletter["/admin/newsletter"]
dash --> aanalytics["/admin/analytics"]
dash --> aquiz["/admin/quiz"]
dash --> asettings["/admin/settings"]
end
home -.-> login
login -.-> account
wildcard["unknown path"] -->|redirect| splash
Eight tables back the platform. customer_profiles and orders.customer_id reference Supabase's auth.users. The authoritative schema (columns, RLS policies, RPCs, seed data) lives in supabase-schema.sql.
erDiagram
AUTH_USERS ||--o| CUSTOMER_PROFILES : "has profile"
AUTH_USERS ||--o{ ORDERS : "places (optional)"
ORDERS ||--|{ ORDER_ITEMS : contains
PRODUCTS ||--o{ ORDER_ITEMS : "referenced by"
AUTH_USERS {
uuid id PK
text email
jsonb app_metadata "role=admin gate"
}
CUSTOMER_PROFILES {
uuid id PK "= auth.users.id"
text email
text name
text phone
text address
text city
text preferred_payment_method
}
ORDERS {
uuid id PK
uuid customer_id FK "nullable"
text order_ref UK
text customer_name
text customer_email
text customer_phone
text address
text city
numeric total
text status
text payment_method
text discount_code
text note
timestamptz created_at
}
ORDER_ITEMS {
uuid id PK
uuid order_id FK
uuid product_id FK "nullable"
text product_name
int quantity
numeric price
}
PRODUCTS {
uuid id PK
text slug UK
text name
numeric price
numeric cost
int stock
int sold
numeric rating
text category
bool active
}
INQUIRIES {
uuid id PK
text company
text name
text email
text message
text status
}
NEWSLETTER_SUBSCRIBERS {
uuid id PK
text email UK
bool active
}
QUIZ_RESPONSES {
uuid id PK
text name
text phone
jsonb answers
text result
int score
}
SITE_EVENTS {
uuid id PK
text event_type
text path
text label
jsonb metadata
timestamptz created_at
}
RLS, RPC & Realtime:
- All eight tables enable Row-Level Security. Public can
insertorders, inquiries, newsletter, quiz, and site events; reads of sensitive data require theadminrole (checked viaauth.jwt() -> 'app_metadata' ->> 'role'). Customers can read only their own profile and orders.- SECURITY DEFINER RPCs:
create_checkout_order(atomic order + items insert, idempotent onorder_ref),save_customer_profile(upsert), anddelete_order_admin(admin-gated cascade delete).- Tables are added to the
supabase_realtimepublication, so the admin dashboard and product feed update live viapostgres_changessubscriptions.
sequenceDiagram
actor User
participant Cart as CartDrawer
participant OE as lib/orderEmail.js
participant FN as /api/send-order-email
participant SB as Supabase RPC
participant RS as Resend
participant WA as WhatsApp
User->>Cart: Review cart (free-delivery progress)
alt COD checkout
User->>Cart: Submit name / phone / address / city
Note over Cart: lib/database.js captureLocalOrder()<br/>โ localStorage pending queue (offline-safe)
Cart->>SB: rpc create_checkout_order (client, idempotent)
Cart->>OE: build order + items (order_ref)
OE->>FN: POST { order, items } (+ X-Customer-Access-Token)
FN->>SB: rpc create_checkout_order (server, idempotent)
alt RPC ok / duplicate (23505)
SB-->>FN: saved (no-op on duplicate order_ref)
else RPC missing
FN->>SB: direct insert orders + order_items
end
FN->>RS: send branded HTML receipt
RS-->>FN: message id
FN-->>OE: { ok, id, order_saved, order_save_via }
OE-->>User: confirmation + /order template
else WhatsApp order
User->>Cart: "Order via WhatsApp"
Cart->>WA: wa.me?text=<encoded order>
WA-->>User: pre-filled chat
end
Note over Cart,FN: Both client and server save via the same idempotent RPC<br/>(keyed on order_ref) โ a failed leg never double-charges or duplicates
flowchart TD
A[POST /api/send-order-email] --> B{Method = POST?}
B -->|No| Z1[405 Method Not Allowed]
B -->|Yes| C{RESEND_API_KEY set?}
C -->|No| Z2[500 Email not configured]
C -->|Yes| D{order_ref + email + items?}
D -->|No| Z3[400 Missing fields]
D -->|Yes| E[Start Supabase save - async]
E --> F[Build branded HTML receipt]
F --> G[Resend: send from ORDER_EMAIL_FROM]
G --> H{Sender/domain error?}
H -->|Yes| I[Retry from onboarding@resend.dev]
H -->|No| J[Use response]
I --> J
J --> K{Email sent?}
K -->|No| Z4[Return Resend error status]
K -->|Yes| L[await Supabase save result]
L --> M[200 ok ยท id ยท order_saved ยท order_save_via]
Server-side environment knobs: ORDER_EMAIL_FROM, ORDER_EMAIL_REPLY_TO, ORDER_EMAIL_BCC, plus SITE_URL / VERCEL_URL for the logo base URL.
Two independent auth contexts, both backed by Supabase Auth, guard their respective areas.
flowchart TB
subgraph Customer["๐ค Customer Auth ยท CustomerAuthContext"]
c1["/login โ sign up or sign in"] --> c2["Supabase Auth session"]
c2 --> c3["/account โ profile + order history"]
c2 -->|access token| c4["X-Customer-Access-Token<br/>sent to order API"]
end
subgraph Admin["๐ก๏ธ Admin Auth ยท AdminAuthContext"]
a1["/admin โ AdminLogin"] --> a2["Supabase session +<br/>app_metadata.role = admin"]
a2 -->|authorised| a3["AdminLayout + pages"]
a2 -->|denied| a1
a3 --> a4["admin-gated RPC / RLS<br/>e.g. delete_order_admin"]
end
A protected console (/admin/*) for operating the store. Wrapped by AdminLayout and guarded by AdminAuthContext.
graph LR
Login[AdminLogin] --> Layout[AdminLayout]
Layout --> D[Dashboard<br/>today's views + conversions]
Layout --> O[Orders<br/>view ยท delete ยท export]
Layout --> P[Products<br/>catalog management]
Layout --> C[Customers]
Layout --> I[Inquiries<br/>B2B + contact]
Layout --> N[Newsletter<br/>subscribers]
Layout --> A[Analytics<br/>events + funnels]
Layout --> Q[Quiz<br/>responses]
Layout --> S[Settings]
| Page | Purpose |
|---|---|
| Dashboard | KPIs โ today's page views, conversions, recent orders |
| Orders | List, inspect, delete (admin-checked RPC), CSV/HTML export |
| Products | Manage the product catalog |
| Customers | Registered customer accounts |
| Inquiries | B2B + contact-form submissions |
| Newsletter | Email subscribers |
| Analytics | Event stream, page views, conversion insight |
| Quiz | Product-finder quiz responses |
| Settings | Store configuration |
flowchart LR
subgraph Client
Route[Route change] --> AT[AnalyticsTracker]
UI[CTA clicks ยท add-to-cart ยท checkout] --> AT
end
AT -->|"trackSiteEvent()"| DB[(site_events)]
DB -->|realtime + queries| Dash[Admin ยท Analytics + Dashboard]
Dash --> Insight[Views ยท conversions ยท funnels]
AnalyticsTracker records page views on navigation and custom conversion events via trackSiteEvent() (lib/database.js), writing to the site_events table (event_type, path, label, metadata). The admin dashboard aggregates today's views and conversions, updating live through realtime subscriptions.
graph LR
LangContext -->|"t = translations[lang]"| EN[English ๐ฌ๐ง]
LangContext -->|"t = translations[lang]"| SI[เทเทเถเทเถฝ ๐ฑ๐ฐ]
LangContext -->|"t = translations[lang]"| TA[เฎคเฎฎเฎฟเฎดเฏ ๐ฎ๐ณ]
subgraph Keys["Translation Key Groups"]
direction TB
NAV[Navigation]
HERO[Hero]
PRODUCTS[Products]
CART[Cart & checkout]
TRUST[Trust badges]
FAQ[FAQ Q&A]
NEWSLETTER[Newsletter]
ANNOUNCE[Announcement bar]
NOTIFY[Live notifications]
end
LangContext --> Keys
Language is toggled via LangToggle in the Navbar. English is the default audience language.
stateDiagram-v2
[*] --> Empty : App load / localStorage empty
Empty --> HasItems : add(product)
HasItems --> HasItems : updateQty(id, delta)
HasItems --> HasItems : remove(id)
HasItems --> Empty : clear()
HasItems --> DrawerOpen : open()
DrawerOpen --> Checkout : COD checkout
DrawerOpen --> WhatsApp : Order via WhatsApp
DrawerOpen --> HasItems : close()
Checkout --> Saved : order persisted + emailed
Saved --> Empty : clear() after success
WhatsApp --> [*] : deep link opens
note right of HasItems
Persisted to localStorage
Subtotal computed on render
Free-delivery progress at LKR 3,000
Bundle rule: add-ons require a base bundle
end note
| Feature | Description |
|---|---|
| Splash & Premium Hero | Animated brand intro, gradient/blob hero, trust chips, hero stats |
| Product Catalog (ร6) | Data-driven catalog with bundles; add-ons require a base bundle |
| COD Checkout | Order form โ Supabase persistence โ emailed receipt |
| WhatsApp Checkout | Pre-filled order deep link, zero payment infra |
| Product Quiz | Guided product-finder with stored responses |
| Customer Accounts | Sign-up/in, profile, order history (Supabase Auth) |
| Live Purchase Notifications | Cycling social-proof toasts |
| Announcement Bar | 24h countdown, dismissible, gradient shimmer |
| Before/After Slider | Drag/touch hygiene-contrast reveal |
| Scroll Reveals & CountUp | IntersectionObserver animations + animated stats |
| Cart Drawer | Qty controls, free-delivery progress, dual checkout |
| Sticky Mobile CTA | Shop + WhatsApp bar after scroll |
| Discount Popup & Newsletter | Timed offer + email capture |
| FAQ Accordion | Pure-CSS grid-rows animation |
| B2B & Referral | Bulk enquiry + referral entry points |
| Policy Pages | Privacy / terms / refund / shipping |
| SEO | Per-page metadata via SEO component |
| Feature | Description |
|---|---|
| Order Persistence | create_checkout_order RPC with idempotent + direct-insert fallback |
| Transactional Email | Branded HTML receipts via Resend with sender fallback |
| Admin Console | Full CRUD/insight surface behind admin auth |
| Realtime | Admin dashboard + product feed update live via postgres_changes |
| Offline-safe orders | Local pending-order queue with idempotent cloud sync |
| Analytics | Page views, conversions, custom events in site_events |
| Export | Orders/customers โ CSV/HTML |
| RLS & RPC | Least-privilege client; admin-checked destructive ops |
| Feature | Description |
|---|---|
| Vite HMR | Sub-100ms hot module replacement |
| Tailwind v4 | Zero-config JIT via @tailwindcss/vite |
| Custom animations | 12+ keyframes; prefers-reduced-motion honoured |
| Graceful degradation | App runs even when Supabase/Resend env vars are absent |
| ESLint | react-hooks + react-refresh rules |
INTIMATE_HYGIENE/
โโโ api/
โ โโโ send-order-email.js # Vercel serverless: save order (RPC) + Resend receipt
โโโ supabase/
โ โโโ email-templates/ # Supabase auth email templates
โโโ supabase-schema.sql # Authoritative DB schema (tables, RLS, RPC)
โโโ vercel.json # Build + SPA rewrite + serverless config
โโโ package.json # Root scripts & backend deps (supabase-js, resend, nodemailer)
โ
โโโ intimate-react/ # Frontend SPA
โโโ public/ # Logos, favicons, product images
โโโ index.html
โโโ vite.config.js # Vite + Tailwind + dev API middleware
โโโ eslint.config.js
โโโ src/
โโโ main.jsx # Entry โ mounts <App/>
โโโ App.jsx # Providers + global UI + router
โโโ index.css # Global styles & keyframes
โ
โโโ context/
โ โโโ LangContext.jsx # EN/SI/TA translations
โ โโโ CartContext.jsx # Cart state + bundle rules
โ โโโ CustomerAuthContext.jsx # Customer Supabase Auth
โ โโโ AdminAuthContext.jsx # Admin auth + guard
โ
โโโ lib/
โ โโโ supabase.js # Supabase client (env-guarded)
โ โโโ database.js # Data access (orders, analytics, etc.)
โ โโโ orderEmail.js # Client โ /api/send-order-email
โ โโโ adminExport.js # CSV/HTML export helpers
โ
โโโ data/
โ โโโ catalog.js # Product catalog + bundle definitions
โ โโโ productContent.js # Per-product marketing content
โ
โโโ hooks/
โ โโโ useInView.js # IntersectionObserver hook
โ
โโโ components/ # Navbar, Footer, CartDrawer, SEO,
โ โ # AnalyticsTracker, TrustBadges, Reveal,
โ โ # BeforeAfterSlider, CountUp, LangToggle, โฆ
โ โโโ ...
โ
โโโ pages/
โ โโโ Splash ยท Home ยท Products ยท Product1..6 ยท Compare
โ โโโ About ยท Benefits ยท Blog ยท FAQ ยท B2B ยท Referral ยท Delivery ยท Contact
โ โโโ Quiz ยท PolicyPages ยท OrderTemplate
โ โโโ CustomerAuth ยท CustomerAccount
โ
โโโ admin/
โโโ AdminLayout.jsx ยท AdminLogin.jsx
โโโ pages/
โโโ AdminDashboard ยท AdminOrders ยท AdminProducts ยท AdminCustomers
โโโ AdminInquiries ยท AdminNewsletter ยท AdminAnalytics
โโโ AdminQuiz ยท AdminSettings
- Node.js โฅ 18
- npm โฅ 9
- (Optional for full backend) A Supabase project + a Resend API key
git clone https://github.com/your-org/INTIMATE_HYGIENE.git
cd INTIMATE_HYGIENE/intimate-react
npm install# From intimate-react/
npm run dev
# โ http://localhost:5173/Vite mounts the order-email API in dev via a custom middleware plugin (orderEmailDevApi in vite.config.js) that runs the very same api/send-order-email.js handler used in production โ so POST /api/send-order-email works locally with no separate server process.
The frontend runs even without Supabase/Resend configured โ
lib/supabase.jsis env-guarded (isSupabaseConfigured) and the app degrades gracefully: orders fall back to a local pending queue + WhatsApp, and analytics/admin features stay dormant. Configure the env vars below to enable the full stack.
# From intimate-react/
npm run build # โ intimate-react/dist
npm run preview # serve the production build locallyCreate a .env.local at the repo root (server/serverless) and the matching VITE_-prefixed values for the client.
| Variable | Purpose |
|---|---|
VITE_SUPABASE_URL |
Supabase project URL |
VITE_SUPABASE_PUBLISHABLE_KEY |
Supabase anon/publishable key |
VITE_ORDER_EMAIL_API_URL |
(optional) base URL for the order-email API (defaults to same origin) |
| Variable | Purpose |
|---|---|
RESEND_API_KEY |
Required โ Resend API key for sending receipts |
SUPABASE_URL (or VITE_SUPABASE_URL) |
Supabase URL for server-side order save |
SUPABASE_SERVICE_ROLE_KEY (or anon/publishable) |
Key used by the function for RPC/insert |
ORDER_EMAIL_FROM |
Verified sender (falls back to onboarding@resend.dev) |
ORDER_EMAIL_REPLY_TO |
Reply-to address |
ORDER_EMAIL_BCC |
BCC for internal order copies |
SITE_URL / VERCEL_URL |
Base URL used for the email logo |
Sends the customer a branded status update whenever an admin changes an order's status in the dashboard (pending โ processing โ shipped โ delivered, plus cancelled). Reuses RESEND_API_KEY, ORDER_EMAIL_FROM, ORDER_EMAIL_REPLY_TO and SITE_URL.
| Variable | Purpose |
|---|---|
ORDER_STATUS_EMAIL_BCC |
(optional) BCC for internal copies of status updates โ unset means the customer alone is emailed |
| Setting | Location |
|---|---|
| WhatsApp number | whatsappMsg strings + CartDrawer.jsx / WhatsAppButton.jsx / StickyMobileCTA.jsx |
| Free-delivery threshold (LKR 3,000) | DeliveryProgressBar.jsx / CartDrawer.jsx |
| Product catalog & bundles | src/data/catalog.js |
flowchart LR
Dev[git push main] --> Vercel
subgraph Vercel["โฒ Vercel"]
Build["buildCommand:<br/>cd intimate-react && npm install && npm run build"]
Build --> Static[Static SPA<br/>intimate-react/dist]
Func[Serverless<br/>/api/send-order-email]
end
Static -->|"rewrite all routes โ /index.html"| Client[Browser]
Client --> Func
Func --> SB[(Supabase)]
Func --> RS[Resend]
Deployment is driven by vercel.json:
{
"buildCommand": "cd intimate-react && npm install && npm run build",
"outputDirectory": "intimate-react/dist",
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}- Files in
api/are deployed as Vercel serverless functions (/api/send-order-email,/api/send-order-status-email). - The SPA rewrite ensures client-side routes (e.g.
/admin/orders,/products/3) resolve on refresh/direct visit. - Set all environment variables in the Vercel project settings.
- Run supabase-schema.sql against your Supabase project to provision tables, RLS, and RPCs.
All scripts run from intimate-react/:
| Script | Description |
|---|---|
npm run dev |
Vite dev server + dev order-email API, HMR (:5173) |
npm run build |
Production bundle โ dist/ |
npm run preview |
Serve the production build locally |
npm run lint |
Run ESLint |
- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Commit using conventional commits:
git commit -m "feat: add X" - Push:
git push origin feat/your-feature - Open a Pull Request against
main
Hygenc Covers ยท Made with โค๏ธ for Sri Lanka
WhatsApp ยท Intimate Hygiene Enterprises
