Add the FarrokhWin Next.js site for Meshkee hosting.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+151
@@ -0,0 +1,151 @@
|
||||
# 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”)
|
||||
Reference in New Issue
Block a user