diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..163f8a6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,537 @@ +# ManoonOils Storefront - AGENTS.md + +## Project Overview + +**ManoonOils** is a premium natural cosmetics e-commerce storefront built as a headless Next.js application. It serves the Serbian market primarily (with German, French, and English localization) selling natural oils and serums for hair and skin care. + +**Current Status:** Active development - migrating from WordPress/WooCommerce to Saleor headless commerce. + +**Production URL:** https://manoonoils.com (currently WordPress, transitioning to Next.js) +**Staging/Dev URL:** https://dev.manoonoils.com (Next.js storefront) +**Saleor API:** https://api.manoonoils.com +**Saleor Dashboard:** https://dashboard.manoonoils.com + +--- + +## Tech Stack + +| Layer | Technology | Version | +|-------|-----------|---------| +| **Framework** | Next.js (App Router) | 16.1.6 | +| **Language** | TypeScript | 5.x | +| **React** | React | 19.2.3 | +| **Styling** | Tailwind CSS | 4.x | +| **State Management** | Zustand | 5.x | +| **i18n** | next-intl | 4.8.3 | +| **API Client** | Apollo Client | 4.1.6 | +| **Backend** | Saleor (GraphQL) | Cloud-hosted | +| **Deployment** | Docker + K3s (Kubernetes) | - | +| **Object Storage** | MinIO | - | +| **Analytics** | OpenPanel + Rybbit | - | +| **Email** | Resend | - | + +--- + +## Development Environment + +### Setup Commands +```bash +# Install dependencies +npm install + +# Start development server +npm run dev +# Server runs on http://localhost:3000 + +# Build for production +npm run build + +# Run tests +npm test # Interactive mode +npm run test:run # Single run +npm run test:coverage # With coverage + +# Run e2e tests +npm run test:e2e # Headless +npm run test:e2e:ui # With UI + +# Linting +npm run lint +``` + +### Environment Variables +Create `.env.local` with: +```env +NEXT_PUBLIC_SALEOR_API_URL=https://api.manoonoils.com/graphql/ +NEXT_PUBLIC_SITE_URL=https://manoonoils.com +NEXT_PUBLIC_OPENPANEL_CLIENT_ID=your-client-id +NEXT_PUBLIC_RYBBIT_HOST=https://rybbit.nodecrew.me +NEXT_PUBLIC_RYBBIT_SITE_ID=your-site-id +``` + +--- + +## Architecture + +### Directory Structure +``` +src/ +├── app/ # Next.js App Router +│ ├── [locale]/ # Localized routes (sr, en, de, fr) +│ │ ├── page.tsx # Homepage +│ │ ├── products/ +│ │ │ ├── page.tsx # Product listing +│ │ │ └── [slug]/ # Product detail +│ │ ├── solutions/ # Programmatic SEO pages +│ │ │ ├── page.tsx # Solutions hub +│ │ │ ├── [slug]/ # Oil-for-concern pages +│ │ │ ├── by-oil/ # Browse by oil +│ │ │ └── by-concern/ # Browse by concern +│ │ ├── about/ +│ │ ├── contact/ +│ │ └── checkout/ +│ ├── api/ # API routes +│ ├── layout.tsx # Root layout +│ ├── sitemap.ts # Dynamic sitemap +│ └── robots.ts # Robots.txt +├── components/ +│ ├── cart/ # Cart drawer +│ ├── home/ # Homepage sections +│ ├── layout/ # Header, Footer, MobileMenu +│ ├── payment/ # Payment components +│ ├── product/ # Product cards, details +│ ├── programmatic-seo/ # SEO page templates +│ ├── providers/ # Context providers +│ ├── seo/ # Schema markup components +│ ├── solutions/ # Breadcrumb, etc. +│ └── ui/ # Reusable UI (Drawer, Marquee) +├── lib/ +│ ├── analytics/ # Analytics tracking +│ ├── config/ # Configuration (shipping, payments) +│ ├── i18n/ # Locale config, metadata +│ ├── programmatic-seo/ # SEO data loading, types +│ ├── saleor/ # GraphQL queries, mutations +│ ├── seo/ # Keywords, schema +│ └── services/ # Business logic services +├── stores/ # Zustand stores +├── types/ # TypeScript types +└── i18n/ # Translation messages +``` + +--- + +## Supported Locales + +| Locale | Code | Saleor Mapping | Flag | +|--------|------|----------------|------| +| Serbian | `sr` | SR | 🇷🇸 | +| English | `en` | EN | 🇬🇧 | +| German | `de` | EN | 🇩🇪 | +| French | `fr` | EN | 🇫🇷 | + +**Default Locale:** Serbian (`sr`) + +**URL Structure:** +- Serbian: `https://manoonoils.com/` (root) or `/sr/` +- English: `https://manoonoils.com/en/` +- German: `https://manoonoils.com/de/` +- French: `https://manoonoils.com/fr/` + +--- + +## Existing Features + +### 1. Homepage (`/`) +- Hero video section +- Problem/solution narrative +- Product showcase +- How it works +- Before/after gallery +- Testimonials +- Newsletter signup +- Trust badges +- Exit intent popup (email capture) +- Ticker bar with promotions + +### 2. Product Listing (`/products`) +- Grid layout with product cards +- Filtering and sorting +- Localization support +- SEO-optimized with keywords + +### 3. Product Detail (`/products/[slug]`) +- Product images (from Saleor/MinIO) +- Pricing and variants +- Add to cart functionality +- Product benefits display +- Bundle selector (2x, 3x packs) +- Related products +- Product reviews +- SEO schema markup (ProductSchema) + +### 4. Cart & Checkout +- **Cart Drawer:** Slide-out cart with quantity controls +- **Checkout Page:** + - Shipping address form + - Shipping method selector + - Payment method (Cash on Delivery - COD) + - Order summary + - Analytics tracking +- **Free Shipping:** Orders over 10,000 RSD + +### 5. Programmatic SEO (`/solutions`) +- **Solutions Hub:** Entry point to all solution pages +- **Oil-for-Concern Pages:** 40 pages (10 pairs × 4 locales) + - Example: `/sr/solutions/arganovo-ulje-za-bore` + - Example: `/en/solutions/argan-oil-for-wrinkles` +- **Browse by Oil:** `/solutions/by-oil` +- **Browse by Concern:** `/solutions/by-concern` +- **Content:** JSON-driven with localized slugs, titles, descriptions, FAQs +- **Schema:** FAQSchema for rich snippets + +### 6. Static Pages +- **About:** Brand story, mission +- **Contact:** Contact form + +### 7. Internationalization +- Full i18n with next-intl +- 4 language translations +- SEO metadata per locale +- Hreflang tags for all pages +- Locale-aware routing + +### 8. SEO +- Dynamic sitemap.xml (48+ URLs) +- Canonical URLs with locale prefix +- OpenGraph tags +- Twitter Card tags +- Product schema markup +- Organization schema +- FAQ schema (programmatic pages) +- Breadcrumb schema +- Keywords strategy per page type + +### 9. Analytics & Tracking +- **OpenPanel:** User behavior analytics +- **Rybbit:** Session replay and tracking + - Client-side script injection + - Proxy configuration for privacy +- **Mautic:** Email marketing tracking +- **Custom Analytics:** + - Add to cart events + - Checkout funnel + - Cart views + - Remove from cart + +### 10. Email +- **Resend** integration for transactional emails +- Email capture popup on exit intent + +--- + +## Data Architecture + +### Programmatic SEO Content +``` +data/ +├── taxonomy/ +│ ├── oils.json # 5 oils with metadata +│ └── concerns.json # 9 skin concerns +└── content/ + └── oil-for-concern/ # 10 content files + ├── argan-oil-wrinkles.json + ├── argan-oil-dry-skin.json + ├── argan-oil-under-eye-bags.json + ├── jojoba-oil-acne.json + ├── jojoba-oil-oily-skin.json + ├── rosehip-oil-wrinkles.json + ├── rosehip-oil-dark-spots.json + ├── rosehip-oil-acne-scars.json + ├── sea-buckthorn-oil-hyperpigmentation.json + └── sweet-almond-oil-sensitive-skin.json +``` + +### Content JSON Structure +Each file contains localized content: +- `pageTitle` (per locale) +- `metaTitle` / `metaDescription` (per locale) +- `oilName` / `concernName` (per locale) +- `whyThisWorks` (per locale) +- `keyBenefits`, `howToApply` (per locale arrays) +- `faqs` (localized Q&A) +- `localizedSlugs` (sr, en, de, fr) + +--- + +## API Routes + +| Route | Purpose | +|-------|---------| +| `/api/analytics/track-order` | Order completion tracking | +| `/api/email-capture` | Email subscription endpoint | +| `/api/geoip` | GeoIP detection for localization | +| `/api/rybbit/track` | Rybbit analytics proxy | + +--- + +## E-commerce Backend (Saleor) + +### Current Integration +- **Products:** Fetched via GraphQL +- **Variants:** Size/options support +- **Checkout:** Saleor checkout API +- **Payments:** Cash on Delivery (COD) only +- **Orders:** Tracked in Saleor + +### Shipping Configuration +```typescript +// src/lib/config/shipping.ts +FREE_SHIPPING_THRESHOLD_RSD = 10000; // 10,000 RSD +DEFAULT_SHIPPING_COST_RSD = 500; // 500 RSD +``` + +### Payment Methods +- Cash on Delivery (COD) - Available +- Credit Card - Coming soon +- Bank Transfer - Coming later + +--- + +## Infrastructure + +### Deployment Stack +- **Container:** Docker (node:20-slim) +- **Orchestration:** K3s (Kubernetes) +- **Ingress:** Traefik +- **Object Storage:** MinIO +- **Databases:** + - PostgreSQL (Saleor) + - MariaDB (WordPress - legacy) + - Redis (cache + task queue) + +### Domains & Routing +``` +manoonoils.com → WordPress (production, being phased out) +dev.manoonoils.com → Next.js storefront (staging) +api.manoonoils.com → Saleor GraphQL API +dashboard.manoonoils.com → Saleor Admin Dashboard +minio-api.nodecrew.me → MinIO Object Storage +``` + +### Image Domains (Next.js) +- `manoonoils.com` +- `minio-api.nodecrew.me` +- `api.manoonoils.com` +- `**.saleor.cloud` +- `images.unsplash.com` + +### Build Output +- `output: 'standalone'` (Next.js standalone mode) +- Static files served from `.next/static/` +- Port: 3000 + +--- + +## Planned Features (Roadmap) + +### Phase 1: Essential (Current Focus) +- [x] Saleor core products integration +- [x] Programmatic SEO (40 pages) +- [x] Multi-language support (4 locales) +- [x] Cart and checkout flow +- [x] Analytics tracking +- [ ] Product reviews (Judge.me or custom) +- [ ] Upsells & cross-sells +- [ ] AJAX add to cart (no page reload) +- [ ] Mautic abandoned cart recovery + +### Phase 2: Growth (1-3 months) +- [ ] Email marketing campaigns (Mautic) +- [ ] Wishlist/favorites +- [ ] Product bundles +- [ ] Recently viewed products +- [ ] Back in stock notifications + +### Phase 3: Advanced (6+ months) +- [ ] Loyalty/rewards program +- [ ] AI/ML product recommendations +- [ ] Subscription/recurring products +- [ ] Product comparison +- [ ] Quick view modal +- [ ] Dynamic pricing/volume discounts + +--- + +## Code Conventions + +### File Naming +- Components: `PascalCase.tsx` +- Utilities: `camelCase.ts` +- API routes: `route.ts` +- Pages: `page.tsx` +- Layouts: `layout.tsx` + +### Styling +- Tailwind CSS utility classes +- Custom colors: `[#1A1A1A]`, `[#FAF9F7]`, `[#666666]`, etc. +- Responsive breakpoints: `sm:`, `md:`, `lg:` + +### State Management +- **Zustand** for global state (cart, checkout) +- **React state** for local component state + +### API Calls +- **Apollo Client** for GraphQL (Saleor) +- **REST** for custom API routes + +### Error Handling +- Error boundaries for React components +- Try/catch for async operations +- Console logging for build-time errors + +--- + +## Testing + +### Unit Tests +- **Framework:** Vitest +- **Location:** `src/__tests__/unit/` +- Run: `npm run test:run` + +### Integration Tests +- **Location:** `src/__tests__/integration/` +- API route testing with MSW + +### E2E Tests +- **Framework:** Playwright +- **Location:** Root `e2e/` directory +- Run: `npm run test:e2e` + +--- + +## SEO Checklist + +### Implemented +- [x] Dynamic sitemap.xml (auto-generated) +- [x] Robots.txt +- [x] Canonical URLs +- [x] Hreflang tags (all 4 locales) +- [x] OpenGraph meta tags +- [x] Twitter Card meta tags +- [x] Product schema (JSON-LD) +- [x] Organization schema +- [x] FAQ schema (programmatic pages) +- [x] Breadcrumb schema +- [x] Keywords per page type +- [x] Localized metadata + +### Pending +- [ ] Blog/Content marketing pages +- [ ] Review schema (when reviews added) +- [ ] Article schema (for blog posts) + +--- + +## Analytics Events + +### Tracked Events +| Event | Trigger | Data | +|-------|---------|------| +| `add_to_cart` | Click "Add to Cart" | Product ID, name, price, quantity | +| `remove_from_cart` | Click remove button | Product ID, name, quantity | +| `view_cart` | Open cart drawer | Total, item count, currency | +| `begin_checkout` | Start checkout | Cart contents | +| `purchase` | Complete order | Order ID, total, items | +| `page_view` | Page load | URL, referrer | + +--- + +## Important Notes + +### Cache Strategy +- Static pages: `public, max-age=3600, stale-while-revalidate=86400` +- Checkout/cart pages: No cache +- API routes: No cache + +### Image Optimization +- Next.js Image component with automatic optimization +- Avif and WebP formats supported +- Responsive sizing with deviceSizes and imageSizes + +### Security +- Environment variables for sensitive config +- No secrets in client-side code +- CORS configured for API routes + +### Performance +- `output: 'standalone'` for Docker optimization +- Image optimization via Next.js +- Code splitting by route +- Lazy loading for below-fold content + +--- + +## Common Tasks + +### Adding a New Programmatic SEO Page +1. Add content JSON to `data/content/oil-for-concern/` +2. Run `node scripts/validate-taxonomy.js` +3. Run `node scripts/generate-urls.js` +4. Build and verify: `npm run build` + +### Adding a New Locale +1. Add locale to `SUPPORTED_LOCALES` in `src/lib/i18n/locales.ts` +2. Add translations to `src/i18n/messages/[locale].json` +3. Add SEO keywords in `src/lib/seo/keywords/locales/[locale].ts` +4. Add page metadata in `src/lib/i18n/pageMetadata.ts` +5. Update sitemap logic if needed + +### Adding a New Product +1. Add product in Saleor Dashboard +2. Upload images to MinIO +3. Set pricing and variants +4. Build will auto-generate product pages + +### Updating Shipping Threshold +1. Edit `src/lib/config/shipping.ts` +2. Change `FREE_SHIPPING_THRESHOLD_RSD` +3. Rebuild and redeploy + +--- + +## Troubleshooting + +### Build Issues +- Check `NEXT_PUBLIC_SALEOR_API_URL` is set +- Verify MinIO is accessible +- Run `npm run lint` before building + +### Locale Issues +- Check locale cookie (`NEXT_LOCALE`) +- Verify messages JSON files exist +- Check `SUPPORTED_LOCALES` array + +### Cart Issues +- Verify Saleor checkout API is accessible +- Check `saleorCheckoutStore.ts` for errors +- Clear browser localStorage if needed + +### Image Issues +- Check MinIO bucket permissions +- Verify image domains in `next.config.ts` +- Check image URLs are HTTPS + +--- + +## Contact & Resources + +- **Repository:** Private Git repository +- **Saleor Dashboard:** https://dashboard.manoonoils.com +- **MinIO Console:** https://minio-api.nodecrew.me +- **Analytics:** OpenPanel + Rybbit +- **Email Service:** Resend + +--- + +*Last updated: April 2026* +*Maintained by: ManoonOils Development Team*