Files
samen-clinic/CONTEXT.md
T
Alireza HassaniandCursor f19d09c27d Initial commit: Clinic Samen Next.js site.
Clone of clinicsamen.com with Meshkee backend integration for blog, workshops, auth, static image slots, and SEO sitemap config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 00:40:31 +03:30

154 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 icon → `https://customer.clinicsamen.com` (`customerPortalUrl` in `src/lib/config.ts`)
- Session: `src/lib/session.tsx` + shared cookies (`src/lib/shared-auth-cookie.ts`)
- 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: user name + «عزیز»; dropdown: پروفایل من، خروج، مدیریت وبسایت (admins only)
- Component: `src/components/AccountMenu.tsx`
## 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 | null | `1920:740` | 1180 | Hero slider |
| `4-people-image` | list | 4 | `325:356` | 280 | Home therapists row |
| `our-services-icon` | list | 4 | `1:1` | 110 | Services icons |
| `two-banner-bg` | list | 2 | `540:312` | 560 | Dual promo banners |
Rules:
- Use `slot.images` (all if `kind=list`, first if `kind=single`)
- `url` → `<img src>`; `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**
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 `<title>` + 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)