# Khiyal Studio Website Context ## Project - English LTR architecture studio site for Khiyal Architecture Studio (Mostafa Heydarhoseini). - Next.js 16 App Router, React 19, TypeScript, Tailwind 4, `src/app`. - Apex domain: `khiyalstudio.com`. - Language: `en`, direction: `ltr`. - Local images live in `public/images`; local fonts live in `public/fonts` (Antonio + Plus Jakarta Sans, matching the source site). - Public routes: `/`, `/about-us`, `/contact-us`, `/portfolios`, `/portfolios/{id}/{slug}`, `/blog`, `/blog/{id}/{slug}`. - Homepage project/news cards still use local placeholders when Meshkee lists are empty. ## Source clone - Visual language cloned from `https://khiyalstudio.com/` (Crafto Architecture theme: dark gray `#191919`, accent `#efff02`, Antonio headings, Plus Jakarta Sans body). - Logo, banners, project photos, about/contact heroes, and partner marks were downloaded from the live theme/storage. - Color tokens: `--base-color: #efff02`, `--dark-gray: #191919`, `--nero-grey: #1F1F1F`, `--medium-gray: #737373`, `--charcoal-grey: #3E3E3E`. - Footer bottom credit row matches `https://safeteb.com/` (Meshkee animated frame + white logo + “Designed And Developed By Meshkee E-Commerce Team”). ## Meshkee API - Canonical docs: `https://api.meshkee.com/docs/website` - API base: `https://api.meshkee.com/api/v1` - Tenant domain: `khiyalstudio.com` (`SITE_DOMAIN` in `src/lib/site.ts`) - Enabled modules currently include `portfolio` and `blog`. This site does **not** use workshops. - All public GET fetches go through `src/lib/meshkee.ts`. - Empty or failed static-image slots keep local placeholders. - Do not invent dashboard/CMS/upload endpoints. - Do not add `public/sitemap.xml`, `public/robots.txt`, `app/sitemap.ts`, or `app/robots.ts`; nginx proxies these URLs to Meshkee. ## Customer account - Login / user icon goes to `https://customer.khiyalstudio.com`. - Logged-in header shows `{firstName} عزیز` with dropdown: `پروفایل من`, `خروج`, and `مدیریت وبسایت` when the user is an admin (`https://business.khiyalstudio.com`). - Auth check: `GET /auth/me` with localStorage token (`accessToken` / `meshkee_access_token`) or credentials cookie. ## Content routes | Kind | List | Detail | API | |---|---|---|---| | Portfolio | `/portfolios` | `/portfolios/{id}/{slug}` | `GET /tenants/{domain}/portfolios`, `.../portfolios/by-id/{id}` | | Blog | `/blog` | `/blog/{id}/{slug}` | `GET /tenants/{domain}/blogs`, `.../blogs/by-id/{id}` | - Portfolio/blog details use Meshkee canonical `{id}/{slug}` URLs and redirect if the slug is stale. - Portfolio details: lightbox gallery, hover zoom, similar-projects row. - Detail galleries prefer `titleImageUrl` plus `gallery` URLs. ## Homepage static-image slots Dashboard import catalog: `GET /meshkee/static-image-slots`. | Key | Kind | itemCount | Aspect | Width | Used on | |---|---|---|---|---|---| | `slider` | list | null | 16:9 | 1920 | Hero (`HeroSlider`) | | `signature` | single | 1 | 16:5 | 480 | Intro signature | | `partners` | list | 4 | 3:2 | 320 | Partner / video logos | | `video-cover` | single | 1 | 16:9 | 1200 | Watch-video cover | | `recent-projects` | list | 3 | 16:8 | 1600 | Recent projects slider | | `news` | list | 3 | 4:5 | 800 | Projects under construction | | `about-hero` | single | 1 | 16:6 | 1920 | About header | | `about-gallery` | list | 3 | 3:4 | 720 | About photos | | `about-owner` | single | 1 | 16:9 | 1400 | Founder portrait | | `contact-hero` | single | 1 | 16:6 | 1920 | Contact header | If a rendered image size or crop ratio changes, update the catalog in `src/app/meshkee/static-image-slots/route.ts` (and `STATIC_IMAGE_SLOT_CATALOG`). ## Sitemap and SEO - Do **not** add `public/sitemap.xml`, `public/robots.txt`, `app/sitemap.ts`, or `app/robots.ts`. Nginx proxies `/sitemap.xml` and `/robots.txt` to Meshkee. - Live sitemap index: `/sitemap.xml` → `/sitemap-main.xml` plus module sitemaps (`/sitemap-portfolios.xml`, `/sitemap-blogs.xml`). - `GET /meshkee/sitemap-config.json` is generated at build time by scanning public static `src/app/**/page.*` routes (`/`, `/about-us`, `/contact-us`, `/portfolios`, `/blog`). CORS `*` is set so the business dashboard can sync it (Website → Settings → Sync sitemap config). - Dynamic `{id}/{slug}` pages are omitted from that static list; Meshkee fills them from CMS. URL templates are omitted because this site uses Meshkee defaults (`/blog/{id}/{titleSlug}`, `/portfolios/{id}/{titleFaSlug}`). - Public slugs are built with `slugify()` (letters/numbers kept, spaces → `-`, punctuation stripped). Do **not** use the legacy DB `slug` field in public URLs. Portfolio slugs prefer `titleFa`; blog slugs prefer `title`. - Auth, admin, checkout, cart, and Meshkee integration routes are excluded. - Sitemap base URL uses `NEXT_PUBLIC_SITE_URL`, then `SITE_URL`, with `https://khiyalstudio.com` as the fallback. - Every crawlable page has unique title + meta description (CMS fields on details), exactly one H1, H2/H3 for real sections, Open Graph, and meaningful image alt text (CMS `titleEn` / `title` / `titleFa` when available). 404 is `noindex`. - Shared helper: `src/lib/seo.ts` (`pageMetadata`). ## Contact - Phone: `0912 252 50 08` (`09122525008`) - Email: `Mostafa.eng@live.com` - Instagram: `mostafa_heydar_hoseini` - WhatsApp / Telegram / Bale links live in `src/lib/site.ts` - Contact form is client-side (success state only) until a Meshkee contact endpoint is connected. ## Verification - Run `npm run lint` and `npm run build`. - Verify `/meshkee/static-image-slots` returns the slot catalog. - Verify `/meshkee/sitemap-config.json` lists `/`, `/about-us`, `/contact-us`, `/portfolios`, `/blog`. - Check homepage, about, contact, and empty states for portfolios/blog. Header user icon should open the customer portal when logged out.