152 lines
8.4 KiB
Markdown
152 lines
8.4 KiB
Markdown
# FarrokhWin — AI / Project Context
|
||
|
||
## Source of truth
|
||
- Live reference: https://www.farrokhwin.com/
|
||
- Backend / Meshkee Website API: https://api.meshkee.com/docs/website
|
||
- Domain: `farrokhwin.com` (`NEXT_PUBLIC_WEBSITE_DOMAIN`)
|
||
- Tenant business id: `28` (`GET /tenants/farrokhwin.com`)
|
||
- `enabledModules`: products, portfolio, blog, finance
|
||
- Customer portal (login / profile / cart): `https://customer.farrokhwin.com`
|
||
- Business dashboard: `https://business.farrokhwin.com`
|
||
- Language: `fa`, direction: `rtl`
|
||
|
||
## Stack
|
||
- Next.js 15 (App Router) + React 19 + TypeScript
|
||
- Tailwind CSS v4 (utility import) + custom CSS in `src/app/globals.css`
|
||
- Fonts (downloaded from the live Meshkee CDN into `public/fonts/`):
|
||
- `morabba` — default UI / headings
|
||
- `iran-yekan` — numbers / accent figures
|
||
- `Montserrat` via `next/font/google` (English labels, class `.en`)
|
||
|
||
## Color palette (from live site `:root`)
|
||
- Primary: `#19377d`
|
||
- Secondary / accent: `#34ace0`
|
||
- Header: `#23242D`
|
||
- Page background: `#1F2128` / `#23262D`
|
||
- Muted text: `#8F8F8F`
|
||
- White: `#FFFFFF`
|
||
|
||
## Pages
|
||
| Route | Purpose |
|
||
|-------|---------|
|
||
| `/` | Homepage (hero, stats, intro, Aparat video, glass article, window types, why us, features, **latest blogs carousel**, CTA, **latest products carousel**, brands) |
|
||
| `/about` | درباره ما |
|
||
| `/contact` | تماس با ما (info + FAQ + Meshkee contact form) |
|
||
| `/products` | Meshkee product catalog (`GET /tenants/{domain}/products`) |
|
||
| `/products/category/{id}/{nameFaSlug}` | Product category (`GET /tenants/{domain}/categories/by-id/{id}`) |
|
||
| `/products/{id}/{nameFaSlug}` | Product details (gallery, zoom, tabs, comments, similar products) |
|
||
| `/blog` | Meshkee blog list (`GET /tenants/{domain}/blogs`) |
|
||
| `/blog/{id}/{titleSlug}` | Blog details (body HTML + comments) |
|
||
| `/portfolio` | Meshkee portfolio list (`GET /tenants/{domain}/portfolios`) |
|
||
| `/portfolios/{id}/{titleFaSlug}` | Portfolio details (`GET /tenants/{domain}/portfolios/by-id/{id}`) |
|
||
| `/videos` | Placeholder — videos from Meshkee later |
|
||
|
||
Header: logo + phones + **AccountMenu** + hamburger overlay (image panel + RTL menu). Cart still in the hamburger.
|
||
|
||
## Auth / account menu
|
||
- Login / user icon → `https://customer.farrokhwin.com` (`customerPortalUrl` in `src/lib/config.ts`)
|
||
- Shared session cookies: `src/lib/shared-auth-cookie.ts` + `src/lib/session.tsx`
|
||
- `GET /api/auth/me` proxies Meshkee `/auth/me`
|
||
- Logged in: show `{name} عزیز` with dropdown **پروفایل من**, **خروج**, and if website admin **مدیریت وبسایت**
|
||
- Admin handoff: `POST /api/auth/handoff` → `business.farrokhwin.com?handoff=…`
|
||
- Admin = super_admin or membership on business id `28` (`isOwner` or `teamRole`)
|
||
- Comments: form only when authenticated; otherwise a login box linking to the customer portal. `POST /api/comments` → Meshkee tenant comments
|
||
|
||
## Meshkee API
|
||
Base: `{NEXT_PUBLIC_MESHKEE_API_BASE}/tenants/{domain}/...`
|
||
Helpers: `src/lib/meshkee.ts` → `meshkeeGet`, `meshkeeGetOrNull`, `tenantPath`, `getTenant`, `getBusinessId`
|
||
|
||
| Resource | List | Detail |
|
||
|----------|------|--------|
|
||
| Products | `GET /tenants/{domain}/products` (`src/lib/products.ts`) | `GET /tenants/{domain}/products/by-id/{id}` + `/technical-info` |
|
||
| Blogs | `GET /tenants/{domain}/blogs` (`src/lib/blog.ts`) | `GET /tenants/{domain}/blogs/by-id/{id}` |
|
||
| Comments | `GET /tenants/{domain}/comments?entityType=&entityId=` | `POST` via `/api/comments` |
|
||
| Portfolio | `GET /tenants/{domain}/portfolios` | not wired yet |
|
||
| Contact | `POST /tenants/{domain}/contact-submissions` via `POST /api/contact` | Body: `{ title, name, text, email?, cellNumber? }` |
|
||
|
||
Canonical URLs:
|
||
- Product: `/products/{id}/{nameFaSlug}` (`productHref` / `slugifyForUrl`)
|
||
- Blog: `/blog/{id}/{titleSlug}` (`blogHref`)
|
||
|
||
Product details:
|
||
- Lightbox gallery + hover zoom (`src/components/ProductGallery.tsx`)
|
||
- Tabs: توضیحات / مشخصات فنی / نظرات (`src/components/ProductTabs.tsx`)
|
||
- Similar products from `relatedProducts`, else other catalog items
|
||
|
||
Homepage carousels (`src/components/MediaCarousel.tsx`): latest blogs and latest products, **max 12** each. API items are primary; static slot images overlay by index when present.
|
||
|
||
## Static image slots
|
||
API: `GET /tenants/{domain}/website/static-images?pageKey=home|about|contact`
|
||
Catalog: `GET /meshkee/static-image-slots` → `STATIC_IMAGE_SLOTS` in `src/lib/static-images.ts`
|
||
|
||
| key | kind | itemCount | aspectRatio | recommendedWidth | section |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| `slider` | list | null | `1920:1080` | 1920 | Homepage hero banners |
|
||
| `home-video-poster` | single | 1 | `16:9` | 1280 | Homepage video |
|
||
| `home-windows` | list | 4 | `12:17` | 720 | Window type cards |
|
||
| `home-why-image` | single | 1 | `1:1` | 640 | Why Farrokh graphic |
|
||
| `home-blog` | list | 12 | `1:1` | 720 | Homepage latest-blog carousel (square overlay cards) |
|
||
| `home-products` | list | 12 | `4:3` | 640 | Homepage latest-products carousel (equal 4:3 boxes, contain) |
|
||
| `home-clients` | list | 4 | `3:2` | 320 | Brand logos |
|
||
| `about-hero` | single | 1 | `1920:480` | 1440 | About hero (currently CSS navy band) |
|
||
| `about-photo` | single | 1 | `4:3` | 800 | About photo |
|
||
| `contact-hero` | single | 1 | `1920:480` | 1440 | Contact hero band |
|
||
| `contact-faq-image` | single | 1 | `4:3` | 960 | Contact FAQ photo |
|
||
|
||
Rules:
|
||
- Use `slot.images` (all if `kind=list`, first if `kind=single`)
|
||
- `url` → image src; `linkUrl` → wrap in link
|
||
- Empty / fail → local fallbacks from `src/data/site.ts` / `public/images/`
|
||
- Homepage blog/product carousels keep Meshkee API items (ids, titles, hrefs); slot images only replace `image` at the same index
|
||
- **If a slot’s on-page size or aspect ratio changes in CSS, update `STATIC_IMAGE_SLOTS` in the same change**
|
||
|
||
## Content & assets
|
||
- Site copy, phones, addresses, FAQs: `src/data/site.ts`
|
||
- Logo: `public/images/logo/logo.png` (from live `kC9gmfo7ef.png`)
|
||
- Hero banners: `public/images/hero/slide-1.jpg` … `slide-3.jpg`
|
||
- Favicon: `/favicon.png`
|
||
- Meshkee footer credit (same as safeteb.com): `public/images/footer/MeshkeeLogo-White.png`
|
||
- Contact: `02538203597` · `09002032333` · `02533342698`
|
||
- Office: قم، بلوار امام رضا(ع)، مجتمع فردوس، واحد ۱۳۸
|
||
- Factory: قم، شهرک صنعتی شکوهیه، فاز دو، خیابان فکوری، کوچه ۲، پلاک KH214
|
||
- Social: Instagram / Telegram `@farrokhwin`, WhatsApp `989002032333`
|
||
- Homepage video: Aparat `w21jpe0` via official embed script (`src/components/AparatVideo.tsx`)
|
||
|
||
## Important paths
|
||
- Layout / shell: `src/app/layout.tsx`, `src/components/Header.tsx`, `src/components/Footer.tsx`, `src/components/Providers.tsx`
|
||
- Account: `src/components/AccountMenu.tsx`, `src/lib/session.tsx`
|
||
- Home: `src/app/page.tsx`, `src/components/HeroSlider.tsx`, `src/components/MediaCarousel.tsx`
|
||
- Products: `src/app/products/page.tsx`, `src/app/products/[id]/[slug]/page.tsx`
|
||
- Blog: `src/app/blog/page.tsx`, `src/app/blog/[id]/[slug]/page.tsx`
|
||
- About / contact: `src/app/about/page.tsx`, `src/app/contact/page.tsx`
|
||
- Config: `src/lib/config.ts`
|
||
|
||
## Env
|
||
```bash
|
||
NEXT_PUBLIC_WEBSITE_DOMAIN=farrokhwin.com
|
||
NEXT_PUBLIC_MESHKEE_API_BASE=https://api.meshkee.com/api/v1
|
||
NEXT_PUBLIC_CUSTOMER_PORTAL_URL=https://customer.farrokhwin.com
|
||
NEXT_PUBLIC_BUSINESS_ORIGIN=https://business.farrokhwin.com
|
||
```
|
||
|
||
## Commands
|
||
```bash
|
||
npm install
|
||
npm run dev
|
||
npm run build
|
||
```
|
||
|
||
## Sitemap + robots
|
||
- **Do not** add `public/sitemap.xml` or `public/robots.txt` (nginx proxies both to the Meshkee API)
|
||
- Publish `GET /meshkee/sitemap-config.json` (generated at build from app routes)
|
||
- Generated at build: `scripts/generate-sitemap-config.mjs` → `src/lib/sitemap-config.generated.json`
|
||
- Run manually: `npm run generate:sitemap-config`
|
||
- After deploy: business dashboard → Website → Settings → Sync sitemap config
|
||
- Dynamic `/products/{id}/{slug}`, `/products/category/{id}/{slug}`, `/blog/{id}/{slug}`, and `/portfolios/{id}/{slug}` are not listed in the static sitemap config; Meshkee CMS syncs those URLs
|
||
|
||
### On-page SEO rules
|
||
- Unique `<title>` + meta description on every crawlable page (`src/lib/seo.ts` → `pageMetadata`)
|
||
- Exactly one `<h1>` per page; section headings use `<h2>` / `<h3>`
|
||
- Content images have meaningful `alt`
|
||
- Footer bottom Meshkee credit must stay in the safeteb.com style (animated frame + white logo + “Designed And Developed By Meshkee E-Commerce Team”)
|