Back to site/Strategy Docs
10·Strategy Pack

Implementation Plan

Stack: Next.js 14 (App Router) + Tailwind CSS Hosting: Vercel (free tier) Budget: $0–30/month total (no Shopify) Design source: /Design prototype development/design_handoff_alnuzha_website/


Stack Decision

LayerToolCostWhy
FrameworkNext.js 14 App RouterFreeSSR + SSG + API routes in one; design README recommends it explicitly
StylingTailwind CSSFreeMaps directly to design tokens; no extra CSS framework needed
FontsGoogle FontsFreeFraunces, Source Sans 3, IBM Plex Sans Arabic, IBM Plex Mono — all available
Cart stateReact Context + localStorageFreeAlready specified in design README (nuzha_cart key, merge logic documented)
FormsReact Hook Form + ZodFreeValidation without a library bloat
Email (forms)ResendFree (100/day)Wholesale inquiry + catalogue gate emails; simple API route
HostingVercelFree tierNext.js native, global CDN, automatic deploys from GitHub
AnalyticsGoogle Analytics 4FreeAlready called out in business strategy
Product dataStatic JSON filesFreeNo DB needed for MVP; easy to migrate later
CMS (Phase 2)Supabase free tierFreeIf dynamic content needed; 500 MB free
Payments (Phase 3)Stripe2.9% + 30¢/txnNo monthly fee; only pay on sales

Total monthly cost: $0 to start. Domain ($12/year) is the only required spend.


Project File Structure

alnuzhadates/
│
├── app/                              # Next.js App Router
│   ├── layout.tsx                   # Root layout (fonts, cart provider, WhatsApp btn)
│   ├── page.tsx                     # Homepage
│   ├── shop/
│   │   └── page.tsx                 # Shop / product listing
│   ├── products/
│   │   └── [slug]/
│   │       └── page.tsx             # Product detail (dynamic route)
│   ├── cart/
│   │   └── page.tsx                 # Cart + checkout
│   ├── wholesale/
│   │   ├── page.tsx                 # Wholesale hub landing
│   │   ├── request-quote/
│   │   │   └── page.tsx             # Inquiry form page
│   │   ├── private-label/
│   │   │   └── page.tsx
│   │   └── catalogue/
│   │       └── page.tsx             # Gated catalogue download
│   ├── our-story/
│   │   └── page.tsx
│   ├── certifications/
│   │   └── page.tsx
│   ├── markets/
│   │   └── page.tsx
│   ├── blog/
│   │   ├── page.tsx                 # Blog index
│   │   └── [slug]/
│   │       └── page.tsx             # Blog post
│   ├── contact/
│   │   └── page.tsx
│   └── api/
│       ├── inquiry/
│       │   └── route.ts             # Wholesale inquiry → email
│       └── catalogue/
│           └── route.ts             # Catalogue gate → email + download link
│
├── components/
│   ├── layout/
│   │   ├── AnnouncementBar.tsx
│   │   ├── Header.tsx               # Sticky, scroll-aware, cart count badge
│   │   ├── Footer.tsx
│   │   └── WhatsAppButton.tsx       # Fixed floating green button
│   ├── home/
│   │   ├── Hero.tsx
│   │   ├── TrustStrip.tsx
│   │   ├── VarietiesGrid.tsx
│   │   ├── DualPath.tsx
│   │   ├── FromMadinah.tsx
│   │   ├── WhySourceFromUs.tsx
│   │   ├── ValueAddedRange.tsx
│   │   ├── MarketsProof.tsx
│   │   └── LeadMagnet.tsx
│   ├── shop/
│   │   ├── FilterSidebar.tsx
│   │   ├── ProductGrid.tsx
│   │   ├── ProductCard.tsx
│   │   └── Toast.tsx
│   ├── product/
│   │   ├── Gallery.tsx
│   │   ├── ProductInfo.tsx          # Grade selector, qty stepper, add-to-cart
│   │   ├── CertStrip.tsx
│   │   └── RelatedProducts.tsx
│   ├── cart/
│   │   ├── CartEmpty.tsx
│   │   ├── CartLineItem.tsx
│   │   └── OrderSummary.tsx
│   ├── wholesale/
│   │   ├── InquiryForm.tsx          # The primary lead-capture form
│   │   └── CatalogueGate.tsx
│   └── ui/                          # Reusable design system components
│       ├── Button.tsx               # Primary / secondary / green variants
│       ├── Badge.tsx                # In stock / Best seller / New harvest / Wholesale only
│       ├── Input.tsx                # Shared form input (focus → amber border)
│       ├── Card.tsx                 # Variety card / value-prop card
│       ├── Eyebrow.tsx              # Uppercase label component
│       └── SectionWrapper.tsx      # Max-width 1240px + horizontal padding
│
├── context/
│   └── CartContext.tsx              # Cart state, localStorage sync, tab sync
│
├── data/
│   ├── products.ts                  # All product data (varieties, value-added, gift boxes)
│   └── content.ts                   # Static text strings (markets, testimonials, certs)
│
├── hooks/
│   ├── useCart.ts
│   └── useScrolled.ts               # Header scroll-aware hook
│
├── lib/
│   ├── email.ts                     # Resend email sender utility
│   └── i18n.ts                      # EN/AR translation map
│
├── public/
│   ├── fonts/                       # Self-hosted fallback if needed
│   ├── images/                      # Product photos, cert logos (when available)
│   └── catalogue.pdf                # The gated wholesale catalogue
│
├── styles/
│   └── globals.css                  # Tailwind base + custom CSS variables
│
├── tailwind.config.ts               # All design tokens mapped here
└── next.config.ts

Design Token → Tailwind Mapping

The tailwind.config.ts will define all tokens from the design system so class names remain semantic throughout the codebase.

colors:
  brown:    #4A2E1E   → text-brown, bg-brown
  gold:     #B8772E   → text-gold, bg-gold, border-gold
  gold-hover: #A3681F
  green:    #3B5A40   → text-green, bg-green
  green-hover: #456B4B
  cream:    #FAF5EC   → bg-cream (page background)
  sand:     #F0E7D6   → bg-sand (cards, alternating sections)
  charcoal: #2B2420   → text-charcoal (body)
  line:     #E3D8C5   → border-line
  muted:    #6B6058
  faint:    #9C8A6E
  sub-brown: #D8CAB2

fontFamily:
  serif:  ['Fraunces', ...]
  sans:   ['Source Sans 3', ...]
  arabic: ['IBM Plex Sans Arabic', ...]
  mono:   ['IBM Plex Mono', ...]

maxWidth:
  site: 1240px

borderRadius:
  btn: 7px
  card: 14px
  pill: 100px

Phase 1 — MVP

Goal: Live site that captures B2B leads and sells DTC. Every page from the design prototype is implemented faithfully. Timeline: 3–4 weeks Cost: $0 (Vercel free + Resend free)


Task 1.1 — Project Setup

  • npx create-next-app@latest alnuzhadates --typescript --tailwind --app --src-dir no
  • Install dependencies: react-hook-form, zod, @hookform/resolvers, resend, clsx
  • Configure tailwind.config.ts with all design tokens (colors, fonts, spacing, radii, shadows)
  • Set up Google Fonts in app/layout.tsx: Fraunces (400, 500, 600), Source Sans 3 (400, 500, 600, 700), IBM Plex Sans Arabic (400, 500), IBM Plex Mono (400)
  • Add CSS custom properties in globals.css for any values Tailwind can't express (e.g. nuzhaPop and nuzhaFade keyframe animations)
  • Create CartContext.tsx with localStorage key nuzha_cart, item shape { id, name, grade, price, qty }, merge key id+"|"+grade, tab-sync via window.storage event
  • Create data/products.ts with all 9 products (varieties + value-added + gift boxes) including SAR prices
  • Create .env.local with RESEND_API_KEY, INQUIRY_EMAIL_TO, CATALOGUE_PDF_URL
  • Set up GitHub repo + connect to Vercel for automatic deploys

Task 1.2 — UI Component Library (components/ui/)

Implement all base components from Design System.dc.html before building pages.

Button.tsx

  • variant: 'primary' | 'secondary' | 'green' | 'text'
  • size: 'sm' | 'default' | 'lg'
  • Primary: bg-gold text-white hover:bg-gold-hover shadow-[0_2px_4px_rgba(74,46,30,.18)]
  • Secondary: border-[1.5px] border-brown text-brown hover:bg-brown hover:text-cream
  • Green: bg-green text-cream hover:bg-green-hover
  • Text link: text-brown border-b-[1.5px] border-gold hover:text-gold
  • Disabled: bg-[#D8C4A3] cursor-not-allowed

Badge.tsx

  • variant: 'instock' | 'bestseller' | 'newharvest' | 'wholesale'
  • All use border-radius: 100px, 12–13px, weight 600
  • In stock: sand pill + green dot
  • Best seller: solid green / cream text
  • New harvest: solid gold / white text
  • Wholesale only: white, 1px solid brown, brown text

Input.tsx

  • Border 1.5px solid #E3D8C5, bg cream, radius 8px, padding 12–13px × 15px
  • Focus: border-gold bg-white
  • Label: 13.5px, weight 600, brown, 7–8px gap below

Card.tsx

  • Rest: 1px solid #E3D8C5, no shadow
  • Hover: shadow-[0_16px_32px_rgba(74,46,30,.10)] -translate-y-1
  • Transition: transition-[transform,box-shadow] duration-200 ease
  • Radius 12–16px

SectionWrapper.tsx

  • max-w-[1240px] mx-auto px-8 (32px horizontal padding)
  • Accepts className for section-level overrides

Eyebrow.tsx

  • text-[12-13px] font-semibold uppercase tracking-[.14em] text-gold

Toast.tsx

  • Fixed bottom-center, green bg, white text
  • Animate in: nuzhaFade (translateY + opacity), 0.3s ease
  • Auto-dismiss after 1.8s
  • Used on "Add to cart" in Shop and Product pages

Task 1.3 — Layout Components

AnnouncementBar.tsx

  • Date Brown background (bg-brown)
  • Left: "Certified & Documented · HACCP · Halal · ISO 22000 · Ships to 20+ countries" — dot-separated, Fraunces 14px, text-sub-brown
  • Right: [EN | AR] toggle button — outline pill, click calls toggleLang() from context

Header.tsx

  • Logo: brown circle "N" + "Al Nuzha / MADINAH DATES" wordmark (swap for real logo later)
  • Nav links: Products, Wholesale, Our Story, Quality, Markets, Contact
  • CTAs: [Request a Quote] (primary) + [Shop] (secondary)
  • Cart icon with live count badge (reads from CartContext)
  • Sticky: position: sticky; top: 0; z-index: 50
  • Scroll behavior: useScrolled hook — when scrollY > 16, reduce vertical padding + add shadow-[0_6px_22px_rgba(74,46,30,.08)]
  • Mobile: hamburger menu, nav collapses to drawer

Footer.tsx

  • Date Brown background, 4-column layout:
    • Col 1: Brand (circle "N" logo + tagline) + WhatsApp button (green, 💬 WhatsApp us)
    • Col 2: Products (links to each variety + value-added)
    • Col 3: Company (Our Story, Wholesale, Certifications, Markets, Blog)
    • Col 4: Contact (Madinah address, email, phone)
  • Bottom row: certification logos + copyright + EN/AR toggle

WhatsAppButton.tsx

  • Fixed, bottom-6 right-6 (or left-6 for RTL)
  • Green circle, 💬 or WhatsApp icon, 56px
  • href="https://wa.me/[NUMBER]" — placeholder until number confirmed
  • target="_blank" rel="noopener noreferrer"

Task 1.4 — Homepage (app/page.tsx)

Implement all 13 sections from Al Nuzha Homepage.dc.html in order:

Section 1: Announcement Bar — (AnnouncementBar component, already in layout)

Section 2: Header — (Header component, already in layout)

Section 3: Hero

  • 2-column grid grid-cols-[1.05fr_1fr] on desktop, stacked on mobile
  • Left: green eyebrow pill "Single-origin · Madinah Al-Munawwarah", H1 "Premium dates from Madinah — the home of Ajwa.", sub-headline, two CTAs [Wholesale Inquiry] (primary) + [Shop Dates] (secondary)
  • Stats row: "20+ countries · 15+ varieties · 4 certifications" with top border divider above
  • Right: rounded image placeholder (striped #E7DCC7 + #DCCDB0) for hero photo
  • Full-bleed cream background

Section 4: Trust Strip

  • Date Brown band, centered
  • "Certified & documented · HACCP · Halal · ISO 22000 · Certificate of Origin · Phytosanitary" — dot-separated, Fraunces 18px, text-sub-brown

Section 5: Our Varieties

  • Section header: eyebrow + H2 "Our varieties" + "View all varieties →" link to /shop
  • 3-column grid of 6 cards: Ajwa, Safawi, Sukkari, Mabroom, Ambari, Khudri
  • Each card: sand bg, image placeholder, Fraunces variety name, short note
  • Card hover lift (Card component)
  • Mobile: 2-up grid or horizontal scroll

Section 6: Dual Path

  • Sand background band
  • 2 equal panels side-by-side (stacked on mobile):
    • Left: Date Brown panel, "For businesses", headline, "Wholesale, private label & bulk export", [Request a Quote] (primary)
    • Right: White panel, "For you", headline, "Gift boxes & premium packs, delivered", [Shop Now] (primary)

Section 7: From Madinah

  • 2-column: image placeholder left, text right (reverse on mobile)
  • Eyebrow + H2 "From the palms of Madinah", 2–3 sentences origin story, "Read our story →" link to /our-story

Section 8: Why Source From Us

  • Date Brown background
  • Centered H2
  • 4-column grid of value-prop cards: amber top border, square numbered icon, title, short description
    1. Single-origin Madinah
    2. Certified & documented
    3. Reliable supply & lead times
    4. Private-label ready

Section 9: Value-Added Range

  • Cream background, centered header
  • 4-column grid: Stuffed dates · Chocolate-coated · Date paste · Date syrup
  • Each: image placeholder, eyebrow category, name, link to product page

Section 10: Markets / Social Proof

  • Sand background band, 2-column
  • Left: H3 "Trusted by buyers in", country chips (UAE, Kuwait, Qatar, UK, Germany, France, Malaysia, Indonesia, USA, Canada), testimonial blockquote
  • Right: square map placeholder (or real map embed)

Section 11: Lead Magnet

  • Palm Green rounded panel (rounded-2xl)
  • 2-column: copy left ("Download our 2026 wholesale catalogue & price list" + description), email capture form right
  • On submit → calls /api/catalogue route → shows inline success "Check your inbox ✓" state
  • Form: email input + [Get the catalogue] button

Section 12: Footer — (Footer component, already in layout)

Section 13: WhatsApp button — (WhatsAppButton component, already in layout)

EN/AR toggle behavior

  • LanguageContext with lang: 'en' | 'ar' state
  • On toggle: flip <html dir="rtl/ltr">, swap font to IBM Plex Sans Arabic, replace data-i18n text from lib/i18n.ts map
  • Mirror WhatsApp button position on RTL

Task 1.5 — Shop Page (app/shop/page.tsx)

From Shop.dc.html:

Page header block

  • Title "Madinah's finest, delivered" (Fraunces H1)
  • Subtitle + link "Need bulk quantities? Request a wholesale quote →" → /wholesale/request-quote

FilterSidebar.tsx (sticky)

  • Category buttons: All products / Whole dates / Gift boxes / Value-added
  • Active state: sand background, weight 600
  • Variety chips below (display, no filter logic needed in MVP)
  • "All certified & documented" note at bottom

ProductGrid.tsx (3-column)

  • Maps data/products.ts filtered by active category
  • Each ProductCard:
    • White card, image placeholder, optional corner Badge (Best seller / New harvest)
    • Eyebrow category label, Fraunces product name (links to /products/[slug]), short note
    • Price (Fraunces, SAR [price])
    • [Add to cart] primary button
    • Hover lift
    • On add: pushes to CartContext, shows Toast "Ajwa Dates added to cart ✓"

Cart icon in Header

  • Live count badge — reads cartItems.reduce((sum, i) => sum + i.qty, 0) from CartContext

Task 1.6 — Product Detail Page (app/products/[slug]/page.tsx)

From Product.dc.html:

  • generateStaticParams() from data/products.ts slugs — pre-rendered at build
  • Breadcrumb: Home / Shop / [Product name]
  • 2-column layout: Gallery | Info

Gallery.tsx

  • Square main image placeholder
  • 4 thumbnail placeholders; clicking sets active; active thumbnail has amber border

ProductInfo.tsx

  • Badges (Best seller / In stock)
  • Eyebrow (variety type), H1 product name
  • Description paragraph
  • Live price display (changes with selected grade)
  • Grade/size selector buttons: 500g / 1kg / 2kg — selected = Date Brown fill, white text
  • Quantity stepper: button, number input, + button; min 1
  • [Add to cart · SAR {qty × price}] — shows live total; on click → CartContext + Toast
  • [Request a wholesale quote] secondary button → /wholesale/request-quote?product=[name]
  • Detail rows: Origin & grading / Certification / Shipping info
  • Cert strip (HACCP · Halal · ISO 22000)

RelatedProducts.tsx

  • "You may also like" — 3-up grid from other products
  • Same card style as shop

Task 1.7 — Cart Page (app/cart/page.tsx)

From Cart.dc.html:

Empty state

  • Centered card, 🛒 emoji, "Your cart is empty", [Browse the shop] button → /shop

Populated state (reads from CartContext)

CartLineItem.tsx (per item)

  • Image placeholder, product name, grade label
  • Remove link
  • Qty stepper (decrement below 1 → removes item)
  • Line total: SAR {price × qty}

OrderSummary.tsx (sticky)

  • Subtotal: Σ price × qty
  • Shipping: free if subtotal ≥ 250 SAR, else 25 SAR, 0 when empty
  • Total = subtotal + shipping
  • Format: SAR {n.toLocaleString()}
  • [Checkout securely] primary button → triggers "placed" success state, clears cart to []
  • Success state: Palm Green card "Order placed ✓" with contact details note
  • "Need an invoice / bulk order? Request a quote →" link
  • Trust row: 🔒 Secure checkout · HACCP · Halal · Worldwide shipping

Note: Checkout in MVP shows a success state and clears cart. Real payment (Stripe) is Phase 3. Add a note on the cart page: "Complete your order via WhatsApp or email" as interim.


Task 1.8 — Wholesale Hub (app/wholesale/)

Wholesale landing page (/wholesale)

  • Hero: H1 "Source from Madinah — the home of Ajwa", sub-headline, [Request a Quote] CTA
  • 4 value props (same as homepage Section 8 but expanded)
  • Product catalogue preview (4–6 variety cards) with [Download Catalogue]/wholesale/catalogue
  • Private label callout → /wholesale/private-label
  • Certifications summary → /certifications

Inquiry Form page (/wholesale/request-quote)

  • Full InquiryForm component
  • Fields (all from README spec):
    • Company name (required)
    • Contact name (required)
    • Country (required, select dropdown — list of target markets first, then all countries)
    • Email (required, validated)
    • Phone / WhatsApp (required)
    • Varieties of interest (multi-select checkboxes: Ajwa, Safawi, Sukkari, Mabroom, Ambari, Khudri, Value-added)
    • Estimated volume (select: <1 MT / 1–5 MT / 5–10 MT / 10–20 MT / 1 container+)
    • Pack format (checkboxes: Bulk, Retail-ready 500g, Private label, Gift boxes)
    • Additional notes (textarea)
  • Validation via Zod schema
  • On submit: POST to /api/inquiry → sends formatted email to INQUIRY_EMAIL_TO via Resend → show inline success

API route (/api/inquiry/route.ts)

  • Parse and validate body
  • Send email to business inbox with all form fields formatted
  • Send auto-reply to submitter with catalogue PDF link + "we'll be in touch within 48h" message
  • Return { success: true } or { error: string }

Catalogue gate page (/wholesale/catalogue)

  • Teaser content (variety thumbnails, "what's inside" bullets)
  • CatalogueGate form: email + company name
  • On submit: POST to /api/catalogue → sends email with download link + adds to list → show download button

API route (/api/catalogue/route.ts)

  • Validate email
  • Send email with catalogue PDF download link
  • Return success

Private Label page (/wholesale/private-label)

  • What we offer: pack formats, labelling, MOQs for private label
  • 3-step process: Inquiry → Sample → Production
  • CTA → /wholesale/request-quote?type=private-label

Task 1.9 — Supporting Pages (MVP)

Our Story (/our-story)

  • Hero section with image placeholder (Madinah / farms)
  • Origin story: Madinah Al-Munawwarah, the Ajwa significance, climate
  • Factory & process section: image placeholders for facility, packing, cold chain
  • Values: transparency, provenance, the anti-fraud stance
  • CTA back to Wholesale inquiry

Certifications (/certifications)

  • Intro: "We believe buyers deserve proof, not promises"
  • Certification cards: HACCP, Halal, ISO 22000 — each with logo placeholder, explanation, download link for PDF
  • Placeholder cards for BRCGS / Organic / Fairtrade with "In progress" badge
  • Per-shipment docs section: COO, Phytosanitary — what they are, how to request
  • Anti-fraud statement block

Contact (/contact)

  • Contact form (name, email, subject, message)
  • WhatsApp number (click-to-chat)
  • Email address
  • Factory address: Madinah Al-Munawwarah, Saudi Arabia
  • Social links
  • Form submits to /api/inquiry with type: 'contact'

Task 1.10 — Performance, SEO & Deployment

SEO (built-in from day 1)

  • metadata export on every page (title, description, OG tags)
  • Page titles follow pattern: [Page] | Al Nuzha — Premium Dates from Madinah
  • Each product page gets type: 'Product' JSON-LD schema
  • Root layout: Organization JSON-LD schema
  • robots.txt and sitemap.xml via app/robots.ts and app/sitemap.ts
  • <html lang="en"> (switches to ar on toggle)

Performance

  • All images: next/image with proper width, height, priority on hero
  • Fonts: loaded via next/font/google (no layout shift)
  • Code splitting is automatic with App Router

Deployment

  • Push to GitHub → Vercel auto-deploys on every push to main
  • Add RESEND_API_KEY and INQUIRY_EMAIL_TO to Vercel environment variables
  • Connect alnuzhadates.com domain in Vercel dashboard
  • Verify SSL (automatic via Vercel)
  • Add site to Google Search Console
  • Add GA4 script via app/layout.tsx or next/script

MVP Deliverables Checklist

  • Homepage — all 13 sections pixel-faithful to design
  • Shop page — product grid + filters + add-to-cart + toast
  • Product detail — grade selector + qty stepper + add-to-cart + B2B path
  • Cart — line items, order summary, shipping logic, checkout success state
  • Wholesale hub — landing + inquiry form + catalogue gate + private-label page
  • Our Story page
  • Certifications page
  • Contact page
  • Working email delivery (inquiry + catalogue gate)
  • Cart persists across pages and tabs (localStorage)
  • EN/AR toggle functional on homepage
  • Mobile responsive (all breakpoints)
  • Floating WhatsApp button
  • GA4 connected
  • Deployed on Vercel at alnuzhadates.com

Phase 2 — Content & SEO Engine

Goal: Add the content pages that drive organic traffic and deepen credibility. Timeline: Weeks 5–10 after MVP launch Trigger: Start Phase 2 once B2B inquiries are coming in from Phase 1.

Task 2.1 — Individual Variety Pages

One dedicated SEO page per variety under /products/[slug] (already handled by the dynamic route from Phase 1, but now with full content):

PagePrimary SEO target
/products/ajwa-dates"ajwa dates wholesale supplier", "buy ajwa dates online"
/products/safawi-dates"safawi dates wholesale", "buy safawi dates"
/products/sukkari-dates"sukkari dates wholesale", "sukkari dates supplier"
/products/mabroom-dates"mabroom dates wholesale"
/products/ambari-dates"ambari dates wholesale", "anbara dates"
/products/khudri-dates"khudri dates wholesale"

Each page expands to include: full origin story for that variety, grade table (count/kg, moisture %, pack formats), spec sheet download, dual CTA.

Task 2.2 — Blog / Resources

  • Blog index page /blog — card grid of articles
  • MDX setup for blog posts (or simple .ts data + page template)
  • Write and publish 4 priority cornerstone articles:
    1. "Complete Guide to Ajwa Dates" — targets "ajwa dates" high volume
    2. "Madinah Date Varieties Explained" — internal link to all variety pages
    3. "How to Import Dates into the EU and UK" — B2B outreach asset
    4. "Date Paste as a Sugar Replacement" — food manufacturer audience
  • Each article: internal links to relevant product page + /wholesale/request-quote CTA at end

Task 2.3 — Markets Pages

  • /markets — hub page with GCC, UK, Europe panels
  • /markets/gcc — pack format norms for GCC, varieties popular, contact CTA
  • /markets/uk — Fairtrade note, ethnic distributor info, Halal certs
  • /markets/europe — ISO 22000, pitted preference in Germany, organic interest

Task 2.4 — Full Arabic Localisation

  • Switch from simple data-i18n map to next-intl library
  • Create /messages/en.json and /messages/ar.json
  • All page text localised
  • RTL layout: dir="rtl" on <html>, WhatsApp button mirrors, nav reorders
  • Arabic product names and descriptions
  • Test on a real Arabic-language device

Task 2.5 — Email Newsletter System

  • Resend Audiences or integrate with Mailchimp/Brevo free tier
  • Segment: B2B vs B2C (set on catalogue download vs DTC purchase)
  • Welcome sequence: 2-email series after catalogue download
  • Monthly newsletter template

Phase 3 — Payments & Growth

Goal: Real DTC checkout + advanced B2B features. Timeline: Months 3–6 after launch Trigger: Start when DTC orders are coming in consistently.

Task 3.1 — Stripe Payment Integration

  • Install stripe and @stripe/stripe-js
  • /api/checkout/route.ts — creates Stripe Checkout Session from cart items
  • Cart [Checkout securely] redirects to Stripe-hosted checkout
  • Stripe webhook /api/webhooks/stripe/route.ts — listens for checkout.session.completed, sends order confirmation email
  • Order confirmation page /order-confirmation
  • Product prices stored with Stripe Price IDs in data/products.ts

Task 3.2 — B2B Customer Portal

  • Authentication: NextAuth.js with email magic-link (no password)
  • B2B account application form → manual approval flow → email notification
  • Approved accounts see wholesale pricing tier in product pages and cart
  • Wholesale pricing stored as a separate price field in product data
  • Account dashboard: past orders, repeat-order button, invoice download (PDF)

Task 3.3 — Database (if needed)

  • Supabase free tier (PostgreSQL, 500 MB)
  • Tables: orders, inquiry_leads, catalogue_downloads, b2b_accounts
  • Migrate from static data/products.ts to Supabase products table (only if dynamic updates are needed — otherwise keep static)

Task 3.4 — Subscriptions (Date Box)

  • Stripe Billing for recurring subscriptions
  • "Monthly Ajwa box" product with subscription option
  • Customer manages subscription from account portal

Task 3.5 — SEO & Performance Audit

  • Lighthouse audit — target 90+ on Performance, Accessibility, SEO
  • Core Web Vitals: LCP < 2.5s, CLS < 0.1, FID/INP < 200ms
  • Image optimisation: real photography replaces all placeholders with WebP + srcset
  • Add FAQPage schema to certifications and variety pages
  • Google Shopping feed from product data

Cost Summary

ItemMonthlyNotes
Vercel (hosting)$0Free tier: 100 GB bandwidth, plenty for MVP
Resend (email)$0Free: 100 emails/day, 3,000/month
Domain~$1~$12/year for .com
Supabase (DB, Phase 3)$0Free: 500 MB, 50,000 MAU
Stripe (payments, Phase 3)2.9% + 30¢ per txnNo monthly fee
Total (Phases 1–2)~$1/monthJust the domain prorated
Total (Phase 3)~$1/month + txn feesScales only with revenue

Key Technical Decisions

Why Next.js App Router (not Pages Router)? Static generation (generateStaticParams) for product pages = fast SEO-optimised pages served from Vercel CDN. API routes for form handling without a separate backend.

Why static data/products.ts for MVP? Zero database setup time, zero cost, instant. Products don't change daily. Migrating to a database later is straightforward when dynamic updates are needed.

Why Resend over SendGrid or Mailgun? 100 emails/day free, simple API, excellent Next.js integration, reliable deliverability. Sufficient for MVP lead volume.

Why localStorage for cart (not server-side)? Exact specification from the design README. No auth required = faster to build and use. Correct for a guest checkout MVP. Replace with server-side sessions in Phase 3 when auth is added.

Why not a headless CMS for Phase 1? Unnecessary complexity for MVP. Static data is faster to ship, easier to maintain, and free. Add a CMS (e.g., Sanity free tier) in Phase 2 if the client needs to self-manage content.