Files
Alireza HassaniandCursor 6cd85e7e59 Add portfolio, blog, customer login, and Meshkee SEO.
Wire CMS routes and account UI, match the original header icons, and publish sitemap-config with unique page metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-31 14:03:46 +03:30

5.7 KiB

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.