Files
backend/docs/website-api/AI_PROMPT.md
T
Alireza HassaniandCursor 2e8d7c1cfd Add backend-generated sitemap with website manifest sync and nginx SEO proxy support.
Stores synced route config from /meshkee/sitemap-config.json, serves sitemap.xml and robots.txt per tenant, and invalidates cache on CMS writes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 15:15:32 +03:30

6.7 KiB
Raw Blame History

Meshkee Website API — AI / designer brief

Copy everything below into a new AI chat when building a Meshkee storefront.


System context (paste this)

You are building a Meshkee business website (storefront). You must use the Meshkee Website API only — never invent admin/CMS endpoints.

Canonical docs (always prefer these):

API base URL: https://api.meshkee.com/api/v1
(Optional alias if configured: https://api.<WEBSITE_DOMAIN>/api/v1 — same backend.)

This website’s apex domain: <WEBSITE_DOMAIN>
(example: sanihome.ir — no www., no api., no customer., no business.)

Hard rules

  1. Resolve tenant first: GET /tenants/<WEBSITE_DOMAIN> → save businessId from id.
  2. All public content uses /tenants/<WEBSITE_DOMAIN>/... (no auth).
  3. Cart, orders, favorites use /businesses/<businessId>/... with Authorization: Bearer <accessToken>.
  4. Customer register body must include "domain": "<WEBSITE_DOMAIN>". If the cell already exists on another Meshkee site and the password differs, API returns 409 with CELL_EXISTS_OTHER_SITE:.... Retry register with "acknowledgeExistingAccount": true to link that account (profile unchanged; password is replaced with the new signup password), then complete SMS OTP.
  5. Cell numbers are E.164 (+98912...).
  6. Do not call dashboard/CMS routes (/businesses/.../products write APIs, media upload, domain-admin, etc.).
  7. Partner SMS (POST /public/sms/send) is for external partner backends with an issued X-Api-Key only — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md

Typical bootstrap sequence

  1. GET /tenants/{domain} → branding + businessId + specialProductsSource (product or store_item)
  2. Homepage: business-info, static-images, sliders, category-groups, brand-groups, store-specials (source repeats the tenant setting; items are store listings when source is store_item)
  3. Catalog: categories, products (GET /products/{slug} includes relatedProducts: same category then same brand, in-stock first), store-items (name instant search: in-stock first, then updatedAt), user-products (customer stock listings)
  4. Auth: register/login → store tokens. Optional: POST /auth/send-otp then POST /auth/login-otp (passwordless) or POST /auth/reset-password (forgot password). POST /auth/verify-otp only marks the cell verified (no tokens).
  5. Cart checkout with addressId or inline shippingAddress + payment
    • For online pay: payment.type = "e_payment_gate", gatewayType (e.g. "mellat" or "zarinpal"), and absolute returnUrl
    • Response includes payment.redirect { method, url, fields } — POST/redirect shopper to the bank
    • Bank callback hits API then redirects to returnUrl?status=success|failed&orderId=…
    • Enabled gateways: GET /tenants/{domain} → ePayment, or GET /businesses/{businessId}/payments/methods

User products (customer listings)

Public marketplace listings owned by customers — not catalog products.

  • GET /tenants/{domain}/user-products — list published (name/q, categoryId, cityId, countryId, condition, promoted, pagination)
  • GET /tenants/{domain}/user-products/{slug} — details + gallery
  • GET /tenants/{domain}/user-products/{slug}/technical-info — category form + values Use product categories from GET /tenants/{domain}/categories?entityType=product for filters. Creating/editing listings is customer-dashboard only (/businesses/.../my-user-products), not website-facing.

Static images

Named slots the business dashboard can replace. Fetch once per page:

  • GET /tenants/{domain}/website/static-images — all slots
  • GET /tenants/{domain}/website/static-images?pageKey=home — slots for one page (home, products, about, …)
  • GET /tenants/{domain}/website/static-images/{key} — one slot (e.g. home-hero)

Use slot.key in the placeholder. Match pageKey to the website page. For a single image: images[0]?.url. For a list: map images (if itemCount is set, that many images are expected). Each image may include titleFa, titleEn, subtext, and linkUrl. If linkUrl is set, wrap in <a href={linkUrl}>. Pick titleFa or titleEn from the site locale. If images is empty, keep the local fallback.

Also publish a slot catalog on this website so the business dashboard Refresh button can import keys from the main domain:

GET https://<WEBSITE_DOMAIN>/meshkee/static-image-slots

{
  "slots": [
    {
      "key": "slider",
      "label": "Homepage slider",
      "kind": "list",
      "pageKey": "home",
      "aspectRatio": "16:9",
      "itemCount": null,
      "recommendedWidth": 1440
    },
    {
      "key": "home-side-banner",
      "label": "Side banner",
      "kind": "single",
      "pageKey": "home",
      "aspectRatio": "12:19",
      "itemCount": 1,
      "recommendedWidth": 480
    }
  ]
}

kind is single (one image) or list (duplicatable). For a fixed row, set itemCount (e.g. 2). Leave itemCount null for an unbounded slider. aspectRatio must look like 16:9. Do not invent CMS/upload APIs.

Sitemap (SEO)

Meshkee generates https://<WEBSITE_DOMAIN>/sitemap.xml on the API from published CMS content plus a manifest your site publishes. Nginx on the storefront proxies /sitemap.xml and /robots.txt to the API — do not hardcode a static sitemap file in the repo unless you know nginx is not proxying yet.

Publish route manifest so the business dashboard can sync static pages and URL templates:

GET https://<WEBSITE_DOMAIN>/meshkee/sitemap-config.json

{
  "baseUrl": "https://sanihome.ir",
  "staticPages": [
    { "path": "/", "changefreq": "daily", "priority": 1.0 },
    { "path": "/about", "priority": 0.6 },
    { "path": "/contact", "priority": 0.5 },
    { "path": "/blog", "priority": 0.7 }
  ],
  "templates": {
    "product": "/products/{slug}",
    "blog": "/blog/{slug}",
    "portfolio": "/portfolios/{slug}"
  }
}
  • path must start with /. Do not include checkout, login, or customer-dashboard URLs.
  • Each templates value must include {slug} and match how this site routes detail pages.
  • After deploy, the business owner syncs from Website → Settings in the dashboard.
  • Dynamic URLs (products, blogs, portfolios) come from the CMS; only paths/templates are declared here.

If OpenAPI and this brief conflict, OpenAPI wins.


What to tell each website team

Replace <WEBSITE_DOMAIN> once per project. Everything else is global — same Postman, same OpenAPI, same base URL.