Files
manoon-headless/AGENTS.md
T
Unchained 4af9544224
Build and Deploy / build (push) Successful in 0s
docs: add comprehensive AGENTS.md for coding agents
2026-04-18 06:40:05 +02:00

538 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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*