# Clinic Samen — AI / Project Context ## Source of truth - Live site being cloned: https://www.clinicsamen.com/ - Prompt instructions: `Ai-data/prompt.txt` - Backend / Meshkee Website API: https://api.meshkee.com/docs/website - Static image slots prompt: `Ai-data/prompt-images-slot.txt` - Backend connect prompt: `Ai-data/prompt-connect-backend.txt` - SEO prompt: `Ai-data/prompt-seo.txt` - Domain: `clinicsamen.com` (`NEXT_PUBLIC_WEBSITE_DOMAIN`) - Tenant business id: `21` (from `GET /tenants/clinicsamen.com`) ## Stack - Next.js 15 (App Router) + React 19 + TypeScript - Tailwind CSS v4 (utility import) + custom CSS in `src/app/globals.css` - Language: `fa`, direction: `rtl` - Fonts (downloaded from Meshkee CDN into `public/fonts/`): - `iran-sans` (default body / Persian UI) - `montserrat` (English labels) ## Color palette (from live site CSS vars / accents) - Primary soft blue: `#DFEAFE` (`--wb-primary-color`) - Secondary / brand blue: `#0141C5` (`--wb-secondary-color`) - Accent blue: `#0946C7` - Mint accent: `#3ED2A7` - Footer navy: `#0B1F4D` - Muted text: `#707070` ## Pages | Route | Purpose | |-------|---------| | `/` | Homepage | | `/about` | درباره ما | | `/contact` | تماس با ما | | `/ourdr` | درمانگران | | `/blog` | مقالات (Meshkee blogs API) | | `/blog/{id}/{titleSlug}` | جزئیات مقاله | | `/workshops` | کارگاه‌ها (Meshkee workshops API) | | `/workshops/{slug}` | جزئیات کارگاه | ## Meshkee API integration Base: `{NEXT_PUBLIC_MESHKEE_API_BASE}/tenants/{domain}/...` Helpers: `src/lib/meshkee.ts` → `meshkeeGet`, `tenantPath`, `getTenant`, `getBusinessId` ### Blog - List: `GET /blogs?page=&pageSize=` - Detail: `GET /blogs/by-id/{id}` (canonical URL `/blog/{id}/{titleSlug}`) - Legacy redirect: `/blog/{slug}` → canonical - Comments: `GET /comments?entityType=blog&entityId={id}` - Lib: `src/lib/blog.ts` ### Workshops - List: `GET /workshops?page=&pageSize=` - Detail: `GET /workshops/{slug}` (URL `/workshops/{slug}`) - Register (auth): `POST /workshops/{workshopId}/register` via `src/app/api/workshops/[workshopId]/register/route.ts` - Cancel registration (auth): `DELETE /workshops/{workshopId}/register` - Comments: included on workshop detail when API provides `comments`; otherwise empty - Lib: `src/lib/workshops.ts` - **Note:** Tenant currently has no published workshops in API; homepage/list fall back to static samples in `src/data/site.ts`. ### Auth / customer portal - Login / user icon → `https://customer.{domain}/login` (`customerPortalUrl` in `src/lib/config.ts` → `customer.clinicsamen.com`) - Session: `src/lib/session.tsx` + shared cookies (`src/lib/shared-auth-cookie.ts`) — reads `meshkee_customer_access_token` from parent domain - Profile API proxy: `GET /api/auth/me` → Meshkee `/auth/me` - Admin handoff: `POST /api/auth/handoff` → Meshkee `/auth/handoff` → `https://business.clinicsamen.com` - Logged-in header: `{firstName lastName} عزیز` via `userDisplayName` - Dropdown (`AccountMenu`): پروفایل من → `/profile`; مدیریت وبسایت (admins/owners/team only, handoff ticket); خروج (clears shared cookies) - Component: `src/components/AccountMenu.tsx` (wired in `Header` topbar) ## Static image slots API: `GET /tenants/{domain}/website/static-images?pageKey=home` Catalog for dashboard Refresh: `GET /meshkee/static-image-slots` → `STATIC_IMAGE_SLOTS` in `src/lib/static-images.ts` | key | kind | itemCount | aspectRatio | recommendedWidth | homepage section | | --- | --- | --- | --- | --- | --- | | `slider` | list (duplicatable) | null | `1920:740` | 1180 | Hero slider | | `our-experts` | list (duplicatable) | null | `325:356` | 280 | Home therapists / experts row | | `two-service-banner` | list | 2 | `540:312` | 560 | Dual promo banners under services | Field → UI mapping (match original homepage; empty API → local placeholders): - `slider`: `url` → slide image; `linkUrl` → wrap slide. `titleFa` / `titleEn` / `subtext` not rendered in hero (image-only). - `our-experts`: `url` → photo; `linkUrl` → card link (fallback `/ourdr`); `titleFa` → name (`h3`); `subtext` → role (`p`). `titleEn` not shown (original therapist cards have no English line). - `two-service-banner`: `url` → banner background; `linkUrl` → CTA href; `titleFa` → banner title (`h3`). `titleEn` / `subtext` not shown on banners. Service icons on the homepage stay local (`serviceCards` in `src/data/site.ts`) — not a Meshkee static-image slot. Rules: - Use `slot.images` (all if `kind=list`, first if `kind=single`) - `url` → ``; `linkUrl` → wrap in link - Empty / fail → keep local placeholders from `src/data/site.ts` / `public/images/` - Use `slot.aspectRatio` (via `parseAspectRatio`) - **If a slot’s on-page size or aspect ratio changes in CSS, update `STATIC_IMAGE_SLOTS` in the same change** (Meshkee reads the catalog as the static-image source of truth) Helpers: `src/lib/static-images.ts`, `src/components/SlotImage.tsx`, `src/components/SlotLink.tsx` Home wiring: `src/app/page.tsx` ## Content & assets - Site copy, therapists bios, phones, address, socials live in `src/data/site.ts` - Static workshop/article fallbacks in `src/data/site.ts` (used when API empty) - Logos, banners, therapist photos, icons in `public/images/` - Favicon: `/favicon.png` ## Footer Meshkee credit - Bottom row matches Safeteb-style Meshkee credit - Component: `src/components/Footer.tsx` → `.meshkee-credit` - Styles: `src/app/globals.css` - Links to `https://meshkee.com` - Logo: `public/images/footer/MeshkeeLogo-White.png` ## Important paths - Layout / shell: `src/app/layout.tsx`, `src/components/Providers.tsx` - Header + account: `src/components/Header.tsx`, `src/components/AccountMenu.tsx` - Footer: `src/components/Footer.tsx` - Home: `src/app/page.tsx`, `src/components/HeroSlider.tsx`, `src/components/HomeSections.tsx` - Blog: `src/app/blog/`, `src/components/ArticlesCarousel.tsx` - Workshops: `src/app/workshops/`, `src/components/WorkshopGallery.tsx`, `src/components/WorkshopRegistration.tsx`, `src/components/EntityTabs.tsx` - Config: `src/lib/config.ts` - Data: `src/data/site.ts` ## Contact - Phones: `025-32706211`, `025-32702623`, `09936221511` - Address: بنیاد - میدان جوان - بلوار آفرینش - خیابان ذوالفقار - نبش کوچه ۳ - Socials: Instagram `@Psy.samen`, WhatsApp, Telegram, Eitaa - Map embed: OpenStreetMap iframe on contact page ## Env ```bash NEXT_PUBLIC_WEBSITE_DOMAIN=clinicsamen.com NEXT_PUBLIC_MESHKEE_API_BASE=https://api.meshkee.com/api/v1 # Optional overrides: # NEXT_PUBLIC_CUSTOMER_PORTAL_URL=https://customer.clinicsamen.com # NEXT_PUBLIC_BUSINESS_ORIGIN=https://business.clinicsamen.com ``` ## Commands ```bash npm install npm run dev npm run build ``` ## SEO canonical URLs - Blog: `/blog/{id}/{titleSlug}` → `GET /blogs/by-id/{id}` - Workshop: `/workshops/{slug}` → `GET /workshops/{slug}` - Slugify helper: `src/lib/seo-slug.ts` - Page metadata helper: `src/lib/seo.ts` → `pageMetadata()` (title, description, canonical, Open Graph) ## Sitemap + robots - **Do not** add `public/sitemap.xml` or `public/robots.txt` (nginx proxies to Meshkee API) - Live sitemap index: `/sitemap.xml` → `/sitemap-main.xml` + CMS URLs - Static pages config: `GET /meshkee/sitemap-config.json` - 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 ### On-page SEO rules - Unique `` + meta description on every public page (via `pageMetadata` or `generateMetadata`) - Exactly one `<h1>` per page (homepage: header brand; inner pages: page hero) - Section headings use `<h2>` / `<h3>` - CMS images use meaningful `alt` (title when available)