# Sohan Salehnia Website Context ## Project - 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: `public/images`. Fonts: `public/fonts`. ## Meshkee API - 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. ## 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 ``, 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 | |---|---| | Primary | `#706C01` | | Gold | `#868215` | | Page | `#F9F9F9` | | Heading | `#4B4B4B` | | Muted | `#5E5E5E` | ## Notes - 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.