Connect Meshkee catalog, customer login, and SEO sitemap config.

Wire products and articles to the public API, send guests to the customer portal, and publish sitemap-config for Meshkee nginx.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-03 09:31:15 +03:30
co-authored by Cursor
parent 4ca234b20f
commit 11fd1cf454
44 changed files with 2159 additions and 118 deletions
+71 -36
View File
@@ -2,50 +2,85 @@
## Project
- Persian RTL storefront clone of `sohansalehnia.com` (سوهان صالح نیا, traditional Qom sohan sweets).
- Persian RTL storefront clone of `sohansalehnia.com` (سوهان صالح نیا).
- Next.js 16 App Router, React 19, TypeScript, Tailwind 4, `src/app`.
- Language: `fa`, direction: `rtl`.
- Local images live in `public/images`. Fonts (Iran Yekan, Montserrat ExtraLight, Fontello/WMi icons) live in `public/fonts`.
- Local images: `public/images`. Fonts: `public/fonts`.
## Scope (this clone)
## Meshkee API
Implemented pages:
- Docs: `https://api.meshkee.com/docs/website`
- API base: `https://api.meshkee.com/api/v1`
- Tenant domain: `sohansalehnia.com` (`TENANT_DOMAIN` in `src/lib/meshkee.ts`, `src/lib/config.ts`)
- All public fetches go through `src/lib/meshkee.ts`. Authenticated calls go through `src/app/api/*` + `src/lib/meshkee-server.ts`.
- Tenant id is `32` (`Salehnia Sohan` / `salehnia-sohan`). Enabled modules: products, blog, finance.
- `/` homepage
- `/aboutus` about
- `/contactus` contact (form is client-side only; no backend submit yet)
- `/products` and `/articles` are placeholders. Products, workshops, and blog will be read from Meshkee later.
## Auth / account
- Guest login/user icon → `https://customer.sohansalehnia.com`
- Logged-in header shows `{name} عزیز` with dropdown: پروفایل من, خروج, and مدیریت وبسایت if admin.
- Profile: `https://customer.sohansalehnia.com/profile`
- Admin dashboard: `https://business.sohansalehnia.com` via `/api/auth/handoff`
- Session: `src/lib/session.tsx` + shared cookies in `src/lib/shared-auth-cookie.ts`
- Favicon: `GET /tenants/sohansalehnia.com/website/favicon`. If `faviconUrl` is empty, fall back to `/images/logo.png`.
## Routes
| Path | Source |
|---|---|
| `/` | static homepage clone |
| `/aboutus` | static about |
| `/contactus` | static contact (form still local) |
| `/products` | `GET /tenants/{domain}/products` |
| `/products/[id]/[slug]` | product by id + technical-info + comments + similar |
| `/articles` | `GET /tenants/{domain}/blogs` |
| `/articles/[id]/[slug]` | blog by id + comments |
Product detail: lightbox gallery, hover zoom, tabs (توضیحات / اطلاعات فنی / دیدگاه‌ها). Comments require login; guests see a login box.
## SEO + sitemap
- Do **not** add `public/sitemap.xml` or `public/robots.txt` (nginx proxies both to Meshkee API).
- Live sitemap is an index: `/sitemap.xml` → `/sitemap-main.xml` + `/sitemap-products.xml`.
- Static pages: `GET /meshkee/sitemap-config.json` (generated at build from app routes).
- Generator: `scripts/generate-sitemap-config.mjs` → `src/lib/sitemap-config.generated.json`
- Run manually: `npm run generate:sitemap-config`
- Excludes `api`, `meshkee`, `admin`, `auth`, `login`, `checkout`, `cart`, `account`
- Blog / product details are **not** listed in sitemap-config (Meshkee XML covers CMS URLs)
- After deploy: business dashboard → Website → Settings → Sync sitemap config (needed for static pages)
### Canonical URL shapes
Meshkee defaults — omit `templates` unless customized. This site customizes **blog** to `/articles`:
- Product: `/products/{id}/{nameFaSlug}` → `GET /tenants/{domain}/products/by-id/{id}`
- Category: `/products/category/{id}/{nameFaSlug}` (not built; catalog empty)
- Blog: `/articles/{id}/{titleSlug}` → `GET /tenants/{domain}/blogs/by-id/{id}` (`templates.blog` in sitemap-config)
- Portfolio: not built
- Slugify (`src/lib/slugify.ts`): Farsi letters kept, spaces → `-`, strip other punctuation. Do not use legacy DB slug in public URLs.
### On-page SEO
- Helper: `src/lib/seo.ts` (`pageMetadata`, unique absolute `<title>`, clipped meta description ~158 chars, canonical, OG)
- Homepage title is unique (`سوهان صالح نیا | تولید و عرضه سوهان سنتی قم`) and does not rely on the Next.js default
- Exactly one visible H1 per page (PageHeader wraps kicker + gold title; homepage H1 is the product-types row). Do not use `sr-only` H1.
- H2/H3 for real sections (feature block, why-us, similar/related, comments)
- Prefer CMS `nameFa` / `title` / `summary` / `descriptionHtml` for product and article metadata
- Content images have meaningful `alt` (CMS title when available). Decorative pattern uses `alt=""`
- `src/app/not-found.tsx`: unique title + one H1, `noindex`
## Brand
| Token | Value | Use |
|---|---|---|
| Primary | `#706C01` | links, buttons, product titles, branch details |
| Gold | `#868215` | section accents, counters, English labels |
| Page | `#F9F9F9` | page background, header, footer |
| Heading | `#4B4B4B` | titles |
| Muted | `#5E5E5E` | labels, footer copy |
| Icon gray | `#939393` | social icons |
| Token | Value |
|---|---|
| Primary | `#706C01` |
| Gold | `#868215` |
| Page | `#F9F9F9` |
| Heading | `#4B4B4B` |
| Muted | `#5E5E5E` |
Logo: `public/images/logo.png` (from the live Meshkee theme). Hero, banners, product icons, pattern, and sohan photos are downloaded from the original theme CDN.
## Notes
## Content source
Copy, addresses, phones, map embed, and section structure are taken from the live Meshkee site. Do not invent replacement marketing copy unless asked.
Branches:
- شعبه یکم: ميدان جهاد،باجك اول،نبش كوي ٤٤ — `02537728181`
- شعبه دوم: قم،بلوار الغدیر،روبروی دانشگاه قم — `02537728181`
Login still points to `https://app.sohansalehnia.com/auth/login`.
## Footer credit
Bottom row follows the SafeTeb Meshkee credit pattern (`Designed And Developed By / Meshkee E-Commerce Team` with animated frame + white Meshkee logo), recolored to the olive/gold theme. Component: `src/components/MeshkeeCredit.tsx`.
## Next work
- Wire `/products` and `/articles` (and any workshops) to Meshkee public API.
- Replace contact form local success state with the real endpoint.
- Products and blogs may be empty until published in Meshkee.
- Do not invent Meshkee endpoints. Product specs use `.../products/by-id/{id}/technical-info` (join `form.fields[].id` ↔ `values[].fieldId`).
- Keep `CONTEXT.md` updated when routes, brand tokens, or data sources change.