Zopping

The layout system

Storefront pages are merchant-configured, not hard-coded. Instead of building fixed pages, you fetch a layout for a page and render the sections it returns. This is the heart of building a Zopping storefront — get it and the rest follows.

Pages are composed of sections

A layout endpoint returns an ordered list of sections (widgets). Each section has four fields:

FieldUse it for
nameThe component type to render — e.g. ProductCollection, ImageSlideShow, BannerWithText. Also a stable CSS class for theming.
valueThe resolved content to render — actual products, images, categories. Always render from value.
dataBackend configuration (prefixed ids, layout type, sorting). Implementation detail — don't render from it.
statusENABLED / DISABLED — skip disabled sections.

Always render from value, not data. data holds internal config (ids like "T12"); value holds the resolved, human-readable content (with slug, entityType, products, images).

Fetch a page layout

# Homepage
curl https://<store-domain>/api/layout/home
{
  "page": {
    "id": 1,
    "name": "HOME"
  },
  "layouts": [
    {
      "name": "ImageSlideShow",
      "value": {
        "images": [
          {
            "url": "...",
            "link": "/category/fruits"
          }
        ]
      },
      "status": "ENABLED"
    },
    {
      "name": "ProductCollection",
      "data": {
        "layoutType": "SCROLLER",
        "title": "Best Sellers"
      },
      "value": {
        "collection": {
          "count": 5000,
          "limit": 20,
          "product": []
        }
      },
      "status": "ENABLED"
    }
  ]
}

Your renderer maps each name → a component, and feeds it section.value.

Page types

Each storefront page type has its own layout endpoint. The detail pages also return the focused entity (with breadcrumbs) on page.entity:

EndpointPage
GET /api/layout/homeHome
GET /api/layout/category?url={slug}Category (with parent chain on page.entity)
GET /api/layout/brand?url={slug}Brand
GET /api/layout/product?url={slug}Product detail (full product on page.entity)
GET /api/layout/tag?url={slug}Tag / collection
GET /api/layout/search?q={query}Search results
GET /api/layout/page?url={slug}Static/CMS page (about, terms…)
GET /api/layout/{page}Any custom page type

Common section types

You'll get these names back; implement a component for each you support (and a fallback for the rest):

  • Products & collections — ProductCollection, CategoryCollection, BrandCollection, SingleProductDetail, GridCollection
  • Media & banners — ImageSlideShow, Image, BannerWithText, BannerWithButton, ImageGrid, HotSpot
  • Content — RichText, ContentBlock, ImageWithText, Accordion, Testimonial, BlogCollection
  • Marketing — FeatureGrid, Highlights, Marquee, VideoCardCarousel
  • Forms & maps — ContactForm, AppointmentForm, Map

What value contains (common sections)

The two you'll meet most:

ProductCollection — a resolved product collection:

"value": { "collection": {
  "count": 240, "limit": 20, "offset": 0,
  "product": [ {
    "id": 10231, "name": "Tata Salt 1kg", "slug": "tata-salt-1kg",
    "images": ["https://…/p1.jpg"],
    "storeSpecificData": [ { "storeId": "<store-id>", "mrp": "28.00", "discount": "10", "stock": 240 } ]
  } ]
} }

Each product matches the storefront product shape — note price lives on storeSpecificData (mrp and a discount percentage, both strings). See Build a complete storefront for the price math.

ImageSlideShow — banners:

"value": { "images": [ { "url": "https://…/banner.jpg", "link": "/category/fruits", "alt": "Fruits" } ] }

Banner sections (BannerWithText, DynamicHeroBanner) carry image, text, link, ctaText. For any section type you don't recognize, render a safe fallback from whatever value holds.

Navigation & chrome

  • GET /api/nav — the header menu hierarchy (up to 3 levels via nested menu); item URLs look like /category/{slug} or /tag/{slug}.
  • GET /api/footerLinks — footer link groups.
  • GET /api/announcement — the announcement bar (description is raw HTML; send Accept-Language).

Drafts & preview

Merchants edit pages before publishing. Mirror the published endpoints under GET /api/draft/{page} (and /api/preview/*) to render unpublished changes — useful for a "preview" mode in your app.

Next