Compare commits

..

4 Commits

Author SHA1 Message Date
Unchained 4d3bf5038e fix(storefront): bump memory limit to 1.5Gi, request to 256Mi
Build and Deploy / build (push) Successful in 1s
- Fixes OOMKills from Next.js SSR memory spikes
- Keeps low request for idle scaling
- Limit allows 3x headroom over baseline
2026-04-21 07:36:29 +02:00
Unchained 7f99b5e328 docs: remove dev.manoonoils.com from AGENTS.md
Build and Deploy / build (push) Successful in 0s
2026-04-18 06:52:24 +02:00
Unchained 2d18909440 docs: correct AGENTS.md - site is fully migrated to Next.js
Build and Deploy / build (push) Successful in 0s
2026-04-18 06:48:31 +02:00
Unchained 4af9544224 docs: add comprehensive AGENTS.md for coding agents
Build and Deploy / build (push) Successful in 0s
2026-04-18 06:40:05 +02:00
2 changed files with 537 additions and 2 deletions
+535
View File
@@ -0,0 +1,535 @@
# 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:** Migrated to Next.js headless storefront with Saleor backend.
**Production URL:** https://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)
- Redis (cache + task queue)
### Domains & Routing
```
manoonoils.com → Next.js storefront (production)
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
- Middleware applies cache headers to all localized pages except checkout/cart/api
### 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*
+2 -2
View File
@@ -61,10 +61,10 @@ spec:
resources:
limits:
cpu: 500m
memory: 512Mi
memory: 1.5Gi
requests:
cpu: 50m
memory: 128Mi
memory: 256Mi
startupProbe:
httpGet:
path: /favicon.ico