Loading live data… Connecting to Supabase.
Total Revenue
—
Loading…
Total Orders
—
Loading…
Avg. Order Value
—
Per paid order
Pending Fulfilment
—
Loading…
Revenue — Last 7 Months
Recent Orders
| Order | Customer | Products | Total | Payment | Fulfilment | Actions |
|---|
List price
Payment
+ Add customer details (optional)
Optional — leave blank if they'd rather not say
Today
Couldn't refresh — this list may be out of date. Tap Refresh to check again.
Cash box today
S$0.00
No sales recorded yet today.
| Order ID | Date | Customer | Items | Total | Payment | Fulfilment | Actions |
|---|
Stock changes save instantly to Supabase
| Product | Size | SKU | Price | Total Stock | Available | Level | Alert At | Status | Actions |
|---|
Customer Accounts: Guest checkout enabled by default. Customers can optionally create accounts to save shipping info and view order history.
16 total customers
| Customer | Phone | Orders | Total Spent | Last Order | Account | Actions |
|---|
Create Discount Code
Codes here are real, live Stripe promotion codes — creating one makes it valid at checkout immediately, and it's the same code you can reference in a Pop-up Event's Discount Code field. Set a Max Discount to cap a percentage code — e.g. 30% with a S$20 max takes 30% off the cart subtotal but never more than S$20.
Active Discount Codes
| Code | Type | Value | Min. Order | Uses Left | Expires | Note | Actions |
|---|
Pop-up Events
Manage booth events and the Stripe payment QR. When you create an active event, customers who scan the QR page see the event offer and submit their details. The Booth Payment QR (below) is a separate Stripe link for taking payments — both work together at a pop-up.
Booth Payment QR
One QR — all products
Customer scans → Stripe page → types the price of their item → pays with PayNow, card, Apple Pay or Google Pay.
Same as your OCBC PayNow QR, but every sale is logged automatically.
Same as your OCBC PayNow QR, but every sale is logged automatically.
Active Event
—
Total Events
—
All time
Leads This Event
—
From QR scans
All Events
| Event | Date | Location | Offer | Leads | Status | Actions |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Total Leads
—
From QR scans
Coupons Used
—
Claimed at booth
Unclaimed
—
Yet to redeem
Collected via QR opt-in with PDPA-compliant consent (the signup page shows a privacy notice before submission). Use Delete below to honour a removal request — the record is kept for our own reference, but is guaranteed to be excluded from every email and marketing send from that point on.
| Name | Phone | Scent | Event | Date | Actions | |
|---|---|---|---|---|---|---|
| Click "↻ Refresh" or open QR Leads to load data. | ||||||
Loading reports…
Site Reference — Simply Yours
Last updated June 2026 · simplyyours.co is live on Cloudflare Pages
22
Pages Live
14
Admin Tabs
9
API Endpoints
3
Languages (EN/BM/ZH)
📄 Pages
🏠 index.html — Homepage Live
- Gold announcement bar (free shipping, dismissible)
- Sticky nav: desktop grid 1fr/auto/1fr, mobile hamburger overlay
- Hero → catalog CTA · Featured product grid (4 cards)
- Find Your Fragrance: Scent Quiz (3Q → product) + Bespoke 3-step form
- Bespoke submissions → Supabase
bespoke_requeststable → admin Bespoke tab - Newsletter section · WELCOME10 unlock widget (10% off, first-time)
- Language switcher: EN / BM / ZH-Hans — all content strings translated
- Floating WhatsApp button (all pages)
🛍️ catalog.html — Shop All Live
- Filter bar: All / Woody / Floral / Fresh / Bestseller
- 4-product grid with hover image swap + price display
- Language switcher wired
🧴 Product Pages (4) Live
- Autumn Whisper · Coastal Embrace · Embun de Forêt · Discovery Set
- Thumbnail gallery (tap-to-zoom on mobile) · size selector · dynamic pricing
- "Add to Bag" →
sy_cart_v1localStorage - Scent notes accordion · Notify Me · Wishlist heart
- Reviews section (read + write) · review saves to Supabase
reviews
🛒 cart.html Live
- Reads
sy_cart_v1— persists across all pages - Qty +/− · remove · gift wrap (+S$4.90) · upsell row
- Promo codes: WELCOME10 (10%) · SYOPENING (15%) — validated via Stripe
- Free shipping auto-applied above S$80
💳 checkout.html Live
- 3-step breadcrumb: Bag → Checkout → Confirmed
- Full SG address form · Standard S$5.90 / Express S$12 / Free S$80+
- Stripe Checkout: card, PayNow, Apple Pay, Google Pay
- On payment: redirect → order-confirmation.html?session_id=…
✅ order-confirmation.html Live
- Reads Stripe session_id → calls
/api/confirm-order - Saves order + items to Supabase · decrements inventory
- Saves discount_code + discount_amount_cents to order record
- Clears cart on arrival
🎯 popup.html — Event QR Landing Live
- Customer-facing page — Serene prints QR to this URL at pop-up events
- Loads active event from
/api/popup-config - Shows event name, offer (free vial / discount code / custom), configurable form
- Collect name / email / phone / scent preference (per event settings)
- Submission → Supabase
popup_leads→ admin QR Leads tab - Shows blank banner if no active event is configured
👤 account.html Prototype
- Prototype bypass: auto signs in as [email protected]
- Shows orders, wishlist, addresses, account settings (from localStorage)
- To-do: wire to Supabase Auth + real order history per customer
📞 contact.html Live
- Contact form · WhatsApp link · response hours · social links
- Multilingual (EN/BM/ZH)
- Form backend: currently shows success only — not yet saved to Supabase
📝 Blog (3 articles) Live
- best-perfume-gifts-singapore.html
- find-your-signature-scent-singapore.html
- what-is-parfum-extrait.html
- SEO-optimised, multilingual content, linked from footer
🔒 admin.html — Staff Portal Live
- Real Supabase Auth login (email + password)
- 14 tabs — see Admin Tabs section below
- Booth sales write to Supabase automatically via Stripe webhook the instant they're paid; ↻ Refresh reloads all data and is a manual backfill if a sale was ever missed
- All API calls verify JWT + admin_users table before executing
📄 Other Pages Live
- shipping.html · gifting.html · our-story.html
- privacy-policy.html · refund-policy.html · terms-of-service.html
- 404.html — on-brand not-found page
- All pages: mobile hamburger nav, floating WhatsApp button
🖥️ Admin Tabs
Dashboard
- KPI cards: revenue, orders, AOV, pending count — live from Supabase
- Recent orders list · low-stock alert (threshold: 2 units)
- Activity feed · Revenue chart
Orders
- All orders from Supabase: filter by status, search by name/email/order#
- Status badges: pending / processing / dispatched / delivered / cancelled
- Detail modal: items, shipping address, tracking, gift message
- Update status + courier/tracking inline
Products
- Real data from Supabase
products+product_variants - Activate / Deactivate per product (saves to Supabase)
- Sizes & Pricing: inline price editor per variant — saves on change
- Prices are live — changes here update Supabase and the website automatically
- Compare price shows as strikethrough original price on all product pages
Inventory
- Real data from Supabase
inventorytable - Shows Total Stock + Available (stock − reserved) per variant
- Colour-coded: green / amber (low) / red (out of stock)
- Low-stock alert at 2 units · Restock button edits quantity inline
- Stock decrements automatically when customer completes purchase
Customers
- Customer list from Supabase with order count + lifetime value
- Search by name or email
Discounts
- Lists active Stripe promo codes + usage count
- WELCOME10 (10% first-time) · SYOPENING (15%) managed in Stripe Dashboard
Reports
- All data computed from real Supabase orders — no fake numbers
- KPIs: best seller, AOV, coupons used + discount total, repeat rate
- Units Sold table: dynamic rows/columns from actual order_items
- Coupon Usage section: lists every order that applied a code
Pop-up Events
- Create / edit / delete events Serene runs (August 2026 booth etc.)
- Configure: event name, date, location, offer type, which fields to collect
- Active event is shown on popup.html (customer QR landing page)
- Booth Payment QR: Stripe static QR — customer enters amount, pays via PayNow/card/Apple/Google Pay. Every sale writes to Supabase automatically the instant it's paid (Stripe webhook) — no need to press Refresh, though it's still there as a manual backfill
- Download / Print branded QR sheet with Simply Yours header + UEN footer
- "Preview Customer QR Page →" button opens popup.html
QR Leads
- All leads submitted via popup.html — real Supabase data
- Filter by event · KPI counts (total / claimed / unclaimed)
- "Mark Claimed" per lead (records claimed_at timestamp)
- Export as CSV
Reviews · Bespoke · Finance · Marketing
- Reviews: approve/reject customer reviews, send reward codes
- Bespoke: live feed from homepage form, NEW badge, reply + mark read
- Finance: revenue summary cards, export (prototype — needs Supabase wiring)
- Marketing: bundle/GWP rules UI (prototype — no backend yet)
⚙️ Backend & Infrastructure
Cloudflare Pages (Hosting) Live
- Static HTML/CSS/JS deployed to Cloudflare CDN
- Domain: simplyyours.co · Auto-deploy from GitHub main branch
- Pages Functions (serverless JS) in
functions/api/ - Env vars in Cloudflare Dashboard: STRIPE_SECRET_KEY, SUPABASE_SERVICE_ROLE_KEY
_headersfile: security headers + cache rules for i18n.js
Cloudflare Pages Functions (API) Live
admin-orders | Orders list + status updates |
admin-products | Products + variants, price/active toggle |
admin-inventory | Stock levels, restock |
confirm-order | Stripe verify → save order + items + decrement stock |
stripe-booth-qr | Create / fetch Stripe booth payment link |
stripe-booth-sync | Pull booth Stripe sessions → insert missing orders |
popup-config | Public: active event · Admin: CRUD events |
popup-leads | Public: submit lead · Admin: list + mark claimed |
admin-popup-events | Admin: all events list for admin UI |
Supabase (Database + Auth) Live
- Project: kbdwgayqspdozzxalczy · Region: ap-southeast-1 (Singapore)
- Admin auth: real email + password via Supabase Auth ·
admin_userswhitelist - RLS enabled · service role key used only in Cloudflare Functions (never client)
- RPC:
decrement_inventory(variant_uuid, qty_sold)— atomic stock update - Auto order number:
SY-YYYY-XXXXXXvia DB trigger
Supabase Tables
| products | 4 products, is_active, category, tagline |
| product_variants | 10 variants (size_ml, price_sgd, stripe_price_id) |
| inventory | quantity, reserved, low_stock_alert per variant |
| orders | All orders incl. discount_code, shipping_method=booth |
| order_items | Line items per order with variant_id + qty |
| popup_events | Booth events: offer type, fields to collect, is_active |
| popup_leads | QR leads: name/email/phone/scent, coupon_used |
| discounts | Synced from Stripe promo codes |
| reviews | Customer product reviews (approve/reject) |
| admin_users · bespoke_requests · leads | Staff whitelist · bespoke form · newsletter |
Stripe Live
- Checkout: card + PayNow + Apple Pay + Google Pay (SG account)
- Promo codes: WELCOME10 (10%) · SYOPENING (15%) — set in Stripe Dashboard
- Booth Payment Link: static QR,
custom_unit_amount(customer enters price) - Booth link collects: Your Name (custom field) + mobile + email (receipt)
- Stripe Link (green wallet button): disable in Stripe Dashboard → Settings → Link
- Booth sales write to Supabase automatically via the Stripe webhook the moment they're paid (↻ Refresh remains as a manual backfill)
Multilingual (i18n) Live
- Languages: English · Bahasa Melayu · 简体中文
i18n.js— translation strings +data-i18nattribute system- Language switcher on homepage, catalog, contact, blog pages
- Cache rule:
Cache-Control: no-cache, must-revalidatefor i18n.js in_headers - To add a page: add
data-i18n="key"attrs + keys to i18n.js
🔧 What Still Needs Doing
| Item | Priority | Notes |
|---|---|---|
| Contact form backend | Done | Saves to Supabase contact_requests table. Serene receives an email via Resend on every submission. |
| Transactional emails | Done | Branded order confirmation email sent to customer automatically on payment. Powered by Resend (simplyyours.co domain verified). |
| Live prices & OOS overlays | Done | All product pages, catalog, and homepage fetch prices from Supabase on load. Out-of-stock overlays appear when inventory hits 0. Change prices here — website updates instantly. |
| GA4 analytics | Done | G-FZR9KHZMNM tracking on all pages including blog. View data in Google Analytics dashboard. |
| Customer account — email & magic link | Done | account.html has real Supabase Auth — email/password sign-up, magic link login, and order history all work. Guest orders are linked to account on first sign-in. |
| Customer account — Google Sign-In | Done | Google OAuth wired via Supabase Auth. Customers can sign up and log in with their Google account. |
| Finance tab — live data | Done | All figures pull from real Supabase orders — gross sales, discounts (from discount_amount_cents), shipping, gift wrap, and discount code breakdown are all accurate. |
| Announcement Bar | Done | Marketing tab → edit text → Save Bar Text. Updates all customer-facing pages instantly via Supabase site_config. Falls back to page default if left blank. |
| Spam protection on contact form | Low | Cloudflare Turnstile backend code is ready in submit-contact.js — add TURNSTILE_SECRET_KEY to Cloudflare env vars and widget to contact.html when traffic picks up. |
| Customer reviews — collect & display | Serene to do | Product pages currently show "Be the first to leave a review" — a conversion trust gap. Action: reach out to early customers on Instagram / TikTok / WhatsApp and ask them to submit a review via the product page review form (or share a screenshot you can post with consent). Even 5–10 genuine reviews significantly improve purchase confidence. The review display system is already built — reviews just need to be approved in the Admin → Reviews tab. |
| Founder name & photo on Our Story page | Serene to do | The Our Story narrative is personal and strong (leaving corporate life, motherhood, the "triumph of a smile") but doesn't name or show the founder. Adding Serene's name and a warm founder photo converts the story into a real trust signal — especially important for a brand whose entire positioning is personal and artisanal. Supply a photo to dev and it can be wired in with a caption in under an hour. |
| Gift box photography — gifting.html | Serene to do | The gifting page has a placeholder section reserved for gift box photography. The wooden gift box + red wax seal is the brand's core differentiator — document it properly with hero shots: box closed, box open, wax seal close-up, and an unboxing sequence. Once photos are ready, replace the placeholder section in gifting.html. |
| Hero packaging photography | Serene to do | Current product imagery mixes polished editorial .webp shots with off-brand /Resources/perfume_*.png images. Commission a consistent set of hero packaging shots for each scent: bottle alone on linen, bottle with wax-sealed box, unboxing flat-lay, and lifestyle (fragrance on a vanity or beside flowers). Once received, replace the /Resources/perfume_*.png images across product pages and retire them. The craftsmanship is the product — show it front and centre. |
| Lock one primary brand positioning line | Serene to do | Currently three identities rotate across pages: (a) artisanal perfume house, (b) memory/time-capsule brand, (c) gifting brand. These are compatible but the brand would be stronger with one dominant one-liner used consistently as the lead on every hero section. Suggested options — pick one: "Singapore's original artisan perfume house." / "Scents made to hold your most precious memories." / "Fragrances crafted for the people of this region." Once decided, update all hero headlines to lead with it consistently. |
💡 Future Features
🟡 Phase 1 — Next
Monthly Vial SubscriptionS$18/month rotating 10ml vial. Stripe recurring billing. Subscriber dashboard in account.html.Ready to design
Digital Gift CardsS$25 / S$50 / S$100. Purchasable online, redeemable at checkout via Stripe.Revenue opportunity
WhatsApp Order UpdatesAuto-send status updates via WhatsApp Business API when order status changes.High customer impact
Site SearchLive search bar in nav. Fuzzy-match on product names, scent notes, fragrance family.Medium effort
⚪ Phase 2 & Beyond
Simply Club LoyaltyPoints per purchase. Silver / Gold / Platinum tiers. Free samples on redemption.High retention value
Influencer Affiliate PortalUnique codes per creator, commission dashboard, auto payout.Growth channel
MY / ID ExpansionMYR pricing, Malaysia + Indonesia shipping rates, BM-first landing pages.Market expansion
Progressive Web AppAdd to Home Screen, offline cart, push notifications for order updates.Mobile experience
Revenue Breakdown
| Line Item | Amount |
|---|
By Payment Status
| Status | Orders | Value |
|---|
By Fulfilment Status
| Status | Orders | Value |
|---|
Discount Code Usage
| Code | Orders Using | Total Revenue | Est. Discount Given |
|---|
Gift & Special Orders
🏷 Discount Codes
| Code | Note | Value | Usage | Expires | Status |
|---|
📣 Announcement Bar
Instant preview below. Wires to live site via Supabase config.
✦ Free standard shipping on orders S$80 and above · Use code ROADSHOW10 for 10% off ✦
Product Catalogue
Prices are fully live — changes here save to Supabase and appear on the website automatically (no HTML editing needed). Refresh the product page to see the new price.
Compare price — set a higher "compare" price to show a strikethrough original price (e.g. S$38 → S$28) on product pages, catalog, and homepage.
Deactivate — hides the price and prevents new orders, but the product page itself stays visible. To fully hide a page, ask Mathew to remove it from the navigation.
Compare price — set a higher "compare" price to show a strikethrough original price (e.g. S$
Deactivate — hides the price and prevents new orders, but the product page itself stays visible. To fully hide a page, ask Mathew to remove it from the navigation.
Loading products…
Customer Reviews
| Date | Customer | Product | Stars | Review | Reward Code | Status | Actions |
|---|
✦ Bespoke Fragrance Requests