@AGENTS.md # Arad Arisman — Meshkee backend integration This site is a Next.js storefront for **aradarisman.com**, backed by the Meshkee Website API (`https://api.meshkee.com/api/v1`, docs at `https://api.meshkee.com/docs/website`). All backend access goes through `src/lib/meshkee.ts` — do not call the API directly from components/pages. - Products (`getProducts`, `getProduct`) and blog posts (`getPosts`, `getPost`) are fetched live, tenant-scoped to `TENANT_DOMAIN` (`aradarisman.com`). Blog field names (`Post` type) are **inferred** from the Product/Category naming convention since no tenant has published posts to verify against yet — accessors fall back across plausible field names (`postTitle`, `postContent`, etc.). Re-check against a real published post once one exists and simplify the fallbacks if the guess was wrong. - Category tiles are derived from live products (`getCategorySummary`), not the raw `/categories` endpoint — that taxonomy has duplicate entries sharing the same display name under different ids (backend data-entry artifact). The summary merges by name and links to whichever id holds the most products under that name. - Business contact data (`getBusinessInfo` / `getResolvedBusinessContact`) comes from `GET /tenants/{domain}/website/business-info` — landline/cell (`phoneNumbers`), addresses, emails, social. Footer, contact page, and `HomeContactStrip` consume the resolved helper. Empty/failed fetches keep the previous hardcoded address and phone fallbacks. ## Static image slots (business-managed overrides) `getStaticImageSlots` / `getStaticImageSlot(key)` read `/tenants/{domain}/website/static-images` — named slots the business owner can fill with their own images from the Meshkee dashboard. Current mapping: | Slot key | Kind | Component | Fallback when empty/unset | |-------------------|--------|--------------------|----------------------------------------| | `hero-category-icons` | list (duplicatable) | `HeroSlider` boxes | SVG icons + top-level category names | | `categories` | list | `CategoryShowcase` | photo cards derived from live product categories | | `four-icon-image` | list(4)| `Features` | 4 local icons + authored copy, per-index override | | `about-us` | single | `About` | local `hero-2.jpg` | | `brands` | list | `Partners` | 6 local partner logos | **Rule: a slot with zero images (or a failed fetch) must never break the page — always fall back to the existing local/derived content.** `getStaticImageSlots` already swallows fetch errors and returns `[]`. Each `StaticImageItem` carries `url`, optional `titleFa`/`subtext`/ `linkUrl`, and its own `width`/`height`. Respect `slot.aspectRatio` (`"21:9"` etc, via `aspectRatioToCss`) for slot-driven image containers instead of hardcoding a Tailwind aspect class — if you resize/recrop a *local* fallback image during development, update the corresponding component's fallback styling **and** the catalog entry in `src/app/meshkee/static-image-slots/route.ts` to match, since slot-driven and fallback images render through the same container and must not look broken when swapped. ### Dashboard catalog (required for Refresh) The Meshkee dashboard **Refresh** button does not invent slots. It imports keys from this site: `GET https://aradarisman.com/meshkee/static-image-slots` That route is `src/app/meshkee/static-image-slots/route.ts`. Until it is deployed and the dashboard Refresh is clicked, `/tenants/aradarisman.com/website/static-images` returns `{ items: [] }` and the storefront correctly shows fallbacks. Do not invent upload/CMS APIs. Owners add images in the Meshkee dashboard after Refresh has imported the catalog.