# Core-Extensions Email Service - Roadmap ## Current Status ✅ - **Order Created**: Working perfectly (customer name, phone, all languages) - **Order Fulfilled**: Working but shows email instead of customer name - **Order Cancelled**: Working but shows email instead of customer name - **All webhooks firing**: ✅ Emails sent via Resend - **Multi-language support**: ✅ Working (tested all 4 languages - SR, EN, DE, FR) - **Admin notifications**: ✅ Both admins receiving emails --- ## PHASE 1: Fix Broken Things (Priority) ### 1.1 Fix Customer Name in Fulfilled/Cancelled Emails **Problem**: Fulfilled and Cancelled webhooks receive partial data from Saleor (no `shippingAddress.firstName`, no `languageCode`) **Solution**: Query Saleor API when these webhooks fire to get full order details **Files to modify**: - `src/pages/api/webhooks/order-fulfilled.ts` - `src/pages/api/webhooks/order-cancelled.ts` **Tasks**: - [ ] Add GraphQL query to fetch full order data including `shippingAddress` and `languageCode` - [ ] Update email template functions to use complete order data - [ ] Test with real fulfillments and cancellations **Effort**: Medium **Impact**: High (fixes broken UX) --- ### 1.2 Fix Environment Variables Usage **Problem**: Hardcoded values in webhook files override env vars **Current**: ```typescript const ADMIN_EMAILS = ["me@hytham.me", "tamara@hytham.me"]; from: "Manoon Oils " ``` **Should be**: ```typescript const ADMIN_EMAILS = process.env.ADMIN_EMAILS?.split(",") || []; from: `${process.env.FROM_NAME} <${process.env.FROM_EMAIL}>` ``` **Files to modify**: - `src/pages/api/webhooks/order-created.ts` - `src/pages/api/webhooks/order-fulfilled.ts` - `src/pages/api/webhooks/order-cancelled.ts` **Tasks**: - [ ] Replace hardcoded `ADMIN_EMAILS` with env var - [ ] Replace hardcoded `from` addresses with env vars - [ ] Update `.env.example` with all required variables - [ ] Document env vars in README **Effort**: Low **Impact**: Medium (first step toward reusability) --- ### 1.3 Fix Resend Daily Quota Issue **Problem**: Multiple emails per order (3 customer + 6 admin = 9 emails per order) **Solutions to consider**: 1. Batch admin emails (send one email with multiple recipients) 2. Add option to disable admin emails for testing 3. Use BCC for admin emails **Tasks**: - [ ] Change admin email sending to use single email with multiple recipients or BCC - [ ] Add `DISABLE_ADMIN_EMAILS` env var for testing - [ ] Consider batching order confirmations **Effort**: Low **Impact**: High (saves quota) --- ## PHASE 2: Make It Reusable (Foundation) ### 2.1 Extract Brand Configuration to Env Vars **Problem**: 20+ hardcoded Manoon Oils references **Files to modify**: - `src/lib/email-templates/order-created.ts` - `src/lib/email-templates/order-shipped.ts` - `src/lib/email-templates/order-cancelled.ts` **New env vars needed**: ``` COMPANY_NAME=Manoon Oils LOGO_URL=https://minio-api.nodecrew.me/... SITE_URL=https://manoonoils.com DASHBOARD_URL=https://dashboard.manoonoils.com TRACKING_URL_TEMPLATE=https://track.manoonoils.com/{trackingNumber} SUPPORT_EMAIL=support@manoonoils.com ``` **Tasks**: - [ ] Replace all hardcoded company names - [ ] Replace all hardcoded URLs - [ ] Replace logo URL - [ ] Update all email templates **Effort**: Medium **Impact**: High (enables reusability) --- ### 2.2 Unify Email Template System **Problem**: Two competing systems (React Email vs Handlebars) **Decision needed**: - **Option A**: Stick with Handlebars (simpler, already working) - **Option B**: Migrate to React Email (type-safe, better for complex layouts) - **Option C**: Support both (more complex) **Recommendation**: Stick with Handlebars for now (it's working), document the React Email files as "future improvement" **Tasks**: - [ ] Document the two systems in README - [ ] Remove unused React Email code OR move to separate folder - [ ] Keep Handlebars as primary system **Effort**: Low **Impact**: Low (cleanup) --- ## PHASE 3: Advanced Features ### 3.1 Configuration via Saleor Metadata **Problem**: Currently requires code changes to customize **Solution**: Store configuration in Saleor's app metadata **Benefits**: - No code changes needed for new stores - Configurable via Saleor dashboard - Single deployment serves multiple stores **Files to modify**: - Add configuration service - Modify all webhook handlers to fetch config - Add settings UI in app **Tasks**: - [ ] Create configuration interface - [ ] Add GraphQL queries to fetch config from Saleor metadata - [ ] Update webhook handlers to use dynamic config - [ ] Create settings page in app - [ ] Cache configuration to avoid API calls on every webhook **Effort**: High **Impact**: High (true multi-tenancy) --- ### 3.2 Add Email Preview/Test Feature **Problem**: Hard to test email templates without creating real orders **Solution**: Add API endpoint to preview/test emails **Tasks**: - [ ] Create `/api/test-email` endpoint - [ ] Allow sending test emails to any address - [ ] Include sample order data for preview - [ ] Add to app UI for easy testing **Effort**: Medium **Impact**: Medium (developer experience) --- ### 3.3 Phone Number Validation **Problem**: Phone validation failing for some formats (GB numbers rejected) **Solution**: Make phone optional OR improve validation **Tasks**: - [ ] Investigate Saleor's phone validation - [ ] Either fix validation or make phone optional in templates - [ ] Update GraphQL fragments if needed **Effort**: Low **Impact**: Low (edge case) --- ## PHASE 4: Documentation & Deployment ### 4.1 Comprehensive README **Sections needed**: - Installation instructions - Environment variables reference - Webhook configuration guide - Testing instructions - Troubleshooting ### 4.2 Docker Compose for Development - Local Saleor instance for testing - Easy development setup ### 4.3 CI/CD Pipeline - Automated testing - Automated deployment - Version tagging --- ## 🎯 Recommended Order of Work ### Next (Do First): 1. **Fix Customer Name in Fulfilled/Cancelled** - Broken UX, high impact 2. **Fix Env Var Usage** - Quick win, enables reusability 3. **Fix Quota Issue** - Save money immediately ### Then: 4. **Extract Brand Config** - Makes it reusable 5. **Documentation** - Helps with future work ### Later: 6. **Saleor Metadata Config** - True multi-tenancy 7. **Email Preview Feature** - Nice to have 8. **Advanced Features** - When needed --- ## Architecture Notes ### Current Hardcoded Values #### Brand/Company Identity: - Company name: "ManoonOils" (12+ instances) - Logo URL: MinIO URL to Manoon logo - Support email: support@manoonoils.com #### URLs: - Site: https://manoonoils.com - Dashboard: https://dashboard.manoonoils.com/orders - Tracking: https://track.manoonoils.com/{trackingNumber} #### Email Addresses: - Admin recipients: me@hytham.me, tamara@hytham.me - From address: Manoon Oils ### Two Email Systems 1. **React Email** (`/src/emails/*.tsx`) - Type-safe React components - Currently unused in webhooks - Good for complex layouts 2. **Handlebars** (`/src/lib/email-templates/*.ts`) - Simple string templates - Currently used by webhooks - Easy to customize with translations **Recommendation**: Stick with Handlebars for production use ### Webhook Data Inconsistency Saleor sends different data for different events: - **ORDER_CREATED**: Full order data ✅ - **ORDER_FULFILLED**: Partial data (missing shippingAddress details, languageCode) ❌ - **ORDER_CANCELLED**: Partial data (missing shippingAddress details, languageCode) ❌ **Fix**: Query Saleor API in fulfilled/cancelled webhooks to fetch complete order data --- ## Environment Variables Reference ### Current (Working): ```bash RESEND_API_KEY= # Required - Resend API key ``` ### Needed (Not implemented): ```bash ADMIN_EMAILS= # Comma-separated admin emails FROM_EMAIL= # Sender email address FROM_NAME= # Sender display name COMPANY_NAME= # Company/brand name LOGO_URL= # URL to logo image SITE_URL= # Customer-facing storefront URL DASHBOARD_URL= # Admin dashboard URL TRACKING_URL_TEMPLATE= # Tracking URL with {trackingNumber} placeholder SUPPORT_EMAIL= # Support email shown in templates DISABLE_ADMIN_EMAILS= # Set to "true" to disable admin notifications ``` --- *Last Updated: March 28, 2026*